checkin jpl under //depot/perlext/jpl/...
Gurusamy Sarathy [Fri, 23 Oct 1998 21:11:56 +0000 (21:11 +0000)]
p4raw-id: //depot/perlext/jpl@2041

30 files changed:
JNI/Changes [new file with mode: 0644]
JNI/JNI.pm [new file with mode: 0644]
JNI/JNI.xs [new file with mode: 0644]
JNI/MANIFEST [new file with mode: 0644]
JNI/Makefile.PL [new file with mode: 0644]
JNI/test.pl [new file with mode: 0644]
JNI/typemap [new file with mode: 0644]
JPL/AutoLoader.pm [new file with mode: 0644]
JPL/Class.pm [new file with mode: 0644]
JPL/Compile.pm [new file with mode: 0755]
JPL/Makefile.PL [new file with mode: 0644]
JPL_Rolo/JPL_Rolo.jpl [new file with mode: 0755]
JPL_Rolo/Makefile.PL [new file with mode: 0644]
JPL_Rolo/README [new file with mode: 0644]
JPL_Rolo/cardfile [new file with mode: 0755]
PerlInterpreter/Makefile [new file with mode: 0644]
PerlInterpreter/Makefile.PL [new file with mode: 0644]
PerlInterpreter/PerlInterpreter.c [new file with mode: 0644]
PerlInterpreter/PerlInterpreter.h [new file with mode: 0644]
PerlInterpreter/PerlInterpreter.java [new file with mode: 0644]
README [new file with mode: 0644]
Sample/Makefile.PL [new file with mode: 0644]
Sample/Sample.jpl [new file with mode: 0644]
Test/Makefile.PL [new file with mode: 0644]
Test/Test.jpl [new file with mode: 0644]
bin/jpl [new symlink]
get_jdk/README [new file with mode: 0644]
get_jdk/get_jdk.pl [new file with mode: 0755]
get_jdk/jdk_hosts [new file with mode: 0644]
install-jpl [new file with mode: 0755]

diff --git a/JNI/Changes b/JNI/Changes
new file mode 100644 (file)
index 0000000..dd2edf7
--- /dev/null
@@ -0,0 +1,5 @@
+Revision history for Perl extension JNI.
+
+0.01  Wed Jun  4 13:16:03 1997
+       - original version; created by h2xs 1.18
+
diff --git a/JNI/JNI.pm b/JNI/JNI.pm
new file mode 100644 (file)
index 0000000..b0e87af
--- /dev/null
@@ -0,0 +1,280 @@
+package JNI;
+
+use strict;
+use Carp;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD $JVM @JVM_ARGS $JAVALIB);
+
+require Exporter;
+require DynaLoader;
+require AutoLoader;
+
+@ISA = qw(Exporter DynaLoader);
+
+@EXPORT = qw(
+       JNI_ABORT
+       JNI_COMMIT
+       JNI_ERR
+       JNI_FALSE
+       JNI_H
+       JNI_OK
+       JNI_TRUE
+       GetVersion
+       DefineClass
+       FindClass
+       GetSuperclass
+       IsAssignableFrom
+       Throw
+       ThrowNew
+       ExceptionOccurred
+       ExceptionDescribe
+       ExceptionClear
+       FatalError
+       NewGlobalRef
+       DeleteGlobalRef
+       DeleteLocalRef
+       IsSameObject
+       AllocObject
+       NewObject
+       NewObjectA
+       GetObjectClass
+       IsInstanceOf
+       GetMethodID
+       CallObjectMethod
+       CallObjectMethodA
+       CallBooleanMethod
+       CallBooleanMethodA
+       CallByteMethod
+       CallByteMethodA
+       CallCharMethod
+       CallCharMethodA
+       CallShortMethod
+       CallShortMethodA
+       CallIntMethod
+       CallIntMethodA
+       CallLongMethod
+       CallLongMethodA
+       CallFloatMethod
+       CallFloatMethodA
+       CallDoubleMethod
+       CallDoubleMethodA
+       CallVoidMethod
+       CallVoidMethodA
+       CallNonvirtualObjectMethod
+       CallNonvirtualObjectMethodA
+       CallNonvirtualBooleanMethod
+       CallNonvirtualBooleanMethodA
+       CallNonvirtualByteMethod
+       CallNonvirtualByteMethodA
+       CallNonvirtualCharMethod
+       CallNonvirtualCharMethodA
+       CallNonvirtualShortMethod
+       CallNonvirtualShortMethodA
+       CallNonvirtualIntMethod
+       CallNonvirtualIntMethodA
+       CallNonvirtualLongMethod
+       CallNonvirtualLongMethodA
+       CallNonvirtualFloatMethod
+       CallNonvirtualFloatMethodA
+       CallNonvirtualDoubleMethod
+       CallNonvirtualDoubleMethodA
+       CallNonvirtualVoidMethod
+       CallNonvirtualVoidMethodA
+       GetFieldID
+       GetObjectField
+       GetBooleanField
+       GetByteField
+       GetCharField
+       GetShortField
+       GetIntField
+       GetLongField
+       GetFloatField
+       GetDoubleField
+       SetObjectField
+       SetBooleanField
+       SetByteField
+       SetCharField
+       SetShortField
+       SetIntField
+       SetLongField
+       SetFloatField
+       SetDoubleField
+       GetStaticMethodID
+       CallStaticObjectMethod
+       CallStaticObjectMethodA
+       CallStaticBooleanMethod
+       CallStaticBooleanMethodA
+       CallStaticByteMethod
+       CallStaticByteMethodA
+       CallStaticCharMethod
+       CallStaticCharMethodA
+       CallStaticShortMethod
+       CallStaticShortMethodA
+       CallStaticIntMethod
+       CallStaticIntMethodA
+       CallStaticLongMethod
+       CallStaticLongMethodA
+       CallStaticFloatMethod
+       CallStaticFloatMethodA
+       CallStaticDoubleMethod
+       CallStaticDoubleMethodA
+       CallStaticVoidMethod
+       CallStaticVoidMethodA
+       GetStaticFieldID
+       GetStaticObjectField
+       GetStaticBooleanField
+       GetStaticByteField
+       GetStaticCharField
+       GetStaticShortField
+       GetStaticIntField
+       GetStaticLongField
+       GetStaticFloatField
+       GetStaticDoubleField
+       SetStaticObjectField
+       SetStaticBooleanField
+       SetStaticByteField
+       SetStaticCharField
+       SetStaticShortField
+       SetStaticIntField
+       SetStaticLongField
+       SetStaticFloatField
+       SetStaticDoubleField
+       NewString
+       GetStringLength
+       GetStringChars
+       NewStringUTF
+       GetStringUTFLength
+       GetStringUTFChars
+       GetArrayLength
+       NewObjectArray
+       GetObjectArrayElement
+       SetObjectArrayElement
+       NewBooleanArray
+       NewByteArray
+       NewCharArray
+       NewShortArray
+       NewIntArray
+       NewLongArray
+       NewFloatArray
+       NewDoubleArray
+       GetBooleanArrayElements
+       GetByteArrayElements
+       GetCharArrayElements
+       GetShortArrayElements
+       GetIntArrayElements
+       GetLongArrayElements
+       GetFloatArrayElements
+       GetDoubleArrayElements
+       GetBooleanArrayRegion
+       GetByteArrayRegion
+       GetCharArrayRegion
+       GetShortArrayRegion
+       GetIntArrayRegion
+       GetLongArrayRegion
+       GetFloatArrayRegion
+       GetDoubleArrayRegion
+       SetBooleanArrayRegion
+       SetByteArrayRegion
+       SetCharArrayRegion
+       SetShortArrayRegion
+       SetIntArrayRegion
+       SetLongArrayRegion
+       SetFloatArrayRegion
+       SetDoubleArrayRegion
+       RegisterNatives
+       UnregisterNatives
+       MonitorEnter
+       MonitorExit
+       GetJavaVM
+);
+
+$VERSION = '0.01';
+
+sub AUTOLOAD {
+    # This AUTOLOAD is used to 'autoload' constants from the constant()
+    # XS function.  If a constant is not found then control is passed
+    # to the AUTOLOAD in AutoLoader.
+
+    my $constname;
+    ($constname = $AUTOLOAD) =~ s/.*:://;
+    my $val = constant($constname, @_ ? $_[0] : 0);
+    if ($! != 0) {
+       if ($! =~ /Invalid/) {
+           $AutoLoader::AUTOLOAD = $AUTOLOAD;
+           goto &AutoLoader::AUTOLOAD;
+       }
+       else {
+               croak "Your vendor has not defined JNI macro $constname";
+       }
+    }
+    eval "sub $AUTOLOAD { $val }";
+    goto &$AUTOLOAD;
+}
+
+bootstrap JNI $VERSION;
+
+if (not $JPL::_env_) {
+    $ENV{JAVA_HOME} ||= "/usr/local/java";
+
+    chop(my $arch = `uname -p`);
+    chop($arch = `uname -m`) unless -d "$ENV{JAVA_HOME}/lib/$arch";
+
+    my @CLASSPATH = split(/:/, $ENV{CLASSPATH});
+    @CLASSPATH = "." unless @CLASSPATH;
+    push @CLASSPATH,
+       "$ENV{JAVA_HOME}/classes",
+       "$ENV{JAVA_HOME}/lib/classes.zip";
+    $ENV{CLASSPATH} = join(':', @CLASSPATH);
+
+    $ENV{THREADS_TYPE} ||= "green_threads";
+
+    $JAVALIB = "$ENV{JAVA_HOME}/lib/$arch/$ENV{THREADS_TYPE}";
+    $ENV{LD_LIBRARY_PATH} .= ":$JAVALIB";
+
+    $JVM = GetJavaVM("$JAVALIB/libjava.so",@JVM_ARGS);
+}
+
+# Preloaded methods go here.
+
+# Autoload methods go after =cut, and are processed by the autosplit program.
+
+1;
+__END__
+# Below is the stub of documentation for your module. You better edit it!
+
+=head1 NAME
+
+JNI - Perl extension for blah blah blah
+
+=head1 SYNOPSIS
+
+  use JNI;
+  blah blah blah
+
+=head1 DESCRIPTION
+
+Stub documentation for JNI was created by h2xs. It looks like the
+author of the extension was negligent enough to leave the stub
+unedited.
+
+Blah blah blah.
+
+=head1 Exported constants
+
+  JNI_ABORT
+  JNI_COMMIT
+  JNI_ERR
+  JNI_FALSE
+  JNI_H
+  JNI_OK
+  JNI_TRUE
+
+
+=head1 AUTHOR
+
+A. U. Thor, a.u.thor@a.galaxy.far.far.away
+
+=head1 SEE ALSO
+
+perl(1).
+
+=cut
diff --git a/JNI/JNI.xs b/JNI/JNI.xs
new file mode 100644 (file)
index 0000000..d54a6cc
--- /dev/null
@@ -0,0 +1,3143 @@
+/*
+ * Copyright 1997, O'Reilly & Associate, Inc.
+ *
+ * This package may be copied under the same terms as Perl itself.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#ifdef __cplusplus
+}
+#endif
+
+#include <perl.h>
+#include <jni.h>
+#include <dlfcn.h>
+
+extern SV** stack_sp;
+extern JNIEnv* jplcurenv;
+extern int jpldebug;
+
+#define SysRet jint
+
+static void call_my_exit(jint status)
+{
+    my_exit(status);
+}
+
+jvalue*
+makeargs(char *sig, SV** svp, int items)
+{
+    jvalue* jv = (jvalue*)safemalloc(sizeof(jvalue) * items);
+    int ix = 0;
+    char *s = sig;
+    JNIEnv* env = jplcurenv;
+    char *start;
+
+    if (jpldebug)
+       fprintf(stderr, "sig = %s, items = %d\n", sig, items);
+    if (*s++ != '(')
+       goto cleanup;
+
+    while (items--) {
+       SV *sv = *svp++;
+       start = s;
+       switch (*s++) {
+       case 'Z':
+           jv[ix++].z = (jboolean)(SvIV(sv) != 0);
+           break;
+       case 'B':
+           jv[ix++].b = (jbyte)SvIV(sv);
+           break;
+       case 'C':
+           jv[ix++].c = (jchar)SvIV(sv);
+           break;
+       case 'S':
+           jv[ix++].s = (jshort)SvIV(sv);
+           break;
+       case 'I':
+           jv[ix++].i = (jint)SvIV(sv);
+           break;
+       case 'J':
+           jv[ix++].j = (jlong)SvNV(sv);
+           break;
+       case 'F':
+           jv[ix++].f = (jfloat)SvNV(sv);
+           break;
+       case 'D':
+           jv[ix++].d = (jdouble)SvNV(sv);
+           break;
+       case '[':
+           switch (*s++) {
+           case 'Z':
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       jboolean* buf = (jboolean*)malloc(len * sizeof(jboolean));
+                       int i;
+                       SV** esv;
+
+                       jbooleanArray ja = (*env)->NewBooleanArray(env, len);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+                           buf[i] = (jboolean)SvIV(*esv);
+                       (*env)->SetBooleanArrayRegion(env, ja, 0, len, buf);
+                       free((void*)buf);
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else if (SvPOK(sv)) {
+                   jsize len = sv_len(sv) / sizeof(jboolean);
+
+                   jbooleanArray ja = (*env)->NewBooleanArray(env, len);
+                   (*env)->SetBooleanArrayRegion(env, ja, 0, len, (jboolean*)SvPV(sv,na));
+                   jv[ix++].l = (jobject)ja;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           case 'B':
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       jbyte* buf = (jbyte*)malloc(len * sizeof(jbyte));
+                       int i;
+                       SV** esv;
+
+                       jbyteArray ja = (*env)->NewByteArray(env, len);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+                           buf[i] = (jbyte)SvIV(*esv);
+                       (*env)->SetByteArrayRegion(env, ja, 0, len, buf);
+                       free((void*)buf);
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else if (SvPOK(sv)) {
+                   jsize len = sv_len(sv) / sizeof(jbyte);
+
+                   jbyteArray ja = (*env)->NewByteArray(env, len);
+                   (*env)->SetByteArrayRegion(env, ja, 0, len, (jbyte*)SvPV(sv,na));
+                   jv[ix++].l = (jobject)ja;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           case 'C':
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       jchar* buf = (jchar*)malloc(len * sizeof(jchar));
+                       int i;
+                       SV** esv;
+
+                       jcharArray ja = (*env)->NewCharArray(env, len);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+                           buf[i] = (jchar)SvIV(*esv);
+                       (*env)->SetCharArrayRegion(env, ja, 0, len, buf);
+                       free((void*)buf);
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else if (SvPOK(sv)) {
+                   jsize len = sv_len(sv) / sizeof(jchar);
+
+                   jcharArray ja = (*env)->NewCharArray(env, len);
+                   (*env)->SetCharArrayRegion(env, ja, 0, len, (jchar*)SvPV(sv,na));
+                   jv[ix++].l = (jobject)ja;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           case 'S':
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       jshort* buf = (jshort*)malloc(len * sizeof(jshort));
+                       int i;
+                       SV** esv;
+
+                       jshortArray ja = (*env)->NewShortArray(env, len);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+                           buf[i] = (jshort)SvIV(*esv);
+                       (*env)->SetShortArrayRegion(env, ja, 0, len, buf);
+                       free((void*)buf);
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else if (SvPOK(sv)) {
+                   jsize len = sv_len(sv) / sizeof(jshort);
+
+                   jshortArray ja = (*env)->NewShortArray(env, len);
+                   (*env)->SetShortArrayRegion(env, ja, 0, len, (jshort*)SvPV(sv,na));
+                   jv[ix++].l = (jobject)ja;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           case 'I':
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       jint* buf = (jint*)malloc(len * sizeof(jint));
+                       int i;
+                       SV** esv;
+
+                       jintArray ja = (*env)->NewIntArray(env, len);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+                           buf[i] = (jint)SvIV(*esv);
+                       (*env)->SetIntArrayRegion(env, ja, 0, len, buf);
+                       free((void*)buf);
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else if (SvPOK(sv)) {
+                   jsize len = sv_len(sv) / sizeof(jint);
+
+                   jintArray ja = (*env)->NewIntArray(env, len);
+                   (*env)->SetIntArrayRegion(env, ja, 0, len, (jint*)SvPV(sv,na));
+                   jv[ix++].l = (jobject)ja;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           case 'J':
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       jlong* buf = (jlong*)malloc(len * sizeof(jlong));
+                       int i;
+                       SV** esv;
+
+                       jlongArray ja = (*env)->NewLongArray(env, len);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+                           buf[i] = (jlong)SvNV(*esv);
+                       (*env)->SetLongArrayRegion(env, ja, 0, len, buf);
+                       free((void*)buf);
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else if (SvPOK(sv)) {
+                   jsize len = sv_len(sv) / sizeof(jlong);
+
+                   jlongArray ja = (*env)->NewLongArray(env, len);
+                   (*env)->SetLongArrayRegion(env, ja, 0, len, (jlong*)SvPV(sv,na));
+                   jv[ix++].l = (jobject)ja;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           case 'F':
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       jfloat* buf = (jfloat*)malloc(len * sizeof(jfloat));
+                       int i;
+                       SV** esv;
+
+                       jfloatArray ja = (*env)->NewFloatArray(env, len);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+                           buf[i] = (jfloat)SvNV(*esv);
+                       (*env)->SetFloatArrayRegion(env, ja, 0, len, buf);
+                       free((void*)buf);
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else if (SvPOK(sv)) {
+                   jsize len = sv_len(sv) / sizeof(jfloat);
+
+                   jfloatArray ja = (*env)->NewFloatArray(env, len);
+                   (*env)->SetFloatArrayRegion(env, ja, 0, len, (jfloat*)SvPV(sv,na));
+                   jv[ix++].l = (jobject)ja;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           case 'D':
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       jdouble* buf = (jdouble*)malloc(len * sizeof(jdouble));
+                       int i;
+                       SV** esv;
+
+                       jdoubleArray ja = (*env)->NewDoubleArray(env, len);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+                           buf[i] = (jdouble)SvNV(*esv);
+                       (*env)->SetDoubleArrayRegion(env, ja, 0, len, buf);
+                       free((void*)buf);
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else if (SvPOK(sv)) {
+                   jsize len = sv_len(sv) / sizeof(jdouble);
+
+                   jdoubleArray ja = (*env)->NewDoubleArray(env, len);
+                   (*env)->SetDoubleArrayRegion(env, ja, 0, len, (jdouble*)SvPV(sv,na));
+                   jv[ix++].l = (jobject)ja;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           case 'L':
+               while (*s != ';') s++;
+               s++;
+               if (strnEQ(start, "[Ljava/lang/String;", 19)) {
+                   if (SvROK(sv)) {
+                       SV* rv = (SV*)SvRV(sv);
+                       if (SvOBJECT(rv))
+                           jv[ix++].l = (jobject)(void*)SvIV(rv);
+                       else if (SvTYPE(rv) == SVt_PVAV) {
+                           jsize len = av_len((AV*)rv) + 1;
+                           int i;
+                           SV** esv;
+                           static jclass jcl = 0;
+                           jarray ja;
+
+                           if (!jcl)
+                               jcl = (*env)->FindClass(env, "java/lang/String");
+                           ja = (*env)->NewObjectArray(env, len, jcl, 0);
+                           for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) {
+                               jobject str = (jobject)(*env)->NewStringUTF(env, SvPV(*esv,na));
+                               (*env)->SetObjectArrayElement(env, ja, i, str);
+                           }
+                           jv[ix++].l = (jobject)ja;
+                       }
+                       else
+                           jv[ix++].l = (jobject)(void*)0;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+                   break;
+               }
+               /* FALL THROUGH */
+           default:
+               if (SvROK(sv)) {
+                   SV* rv = (SV*)SvRV(sv);
+                   if (SvOBJECT(rv))
+                       jv[ix++].l = (jobject)(void*)SvIV(rv);
+                   else if (SvTYPE(rv) == SVt_PVAV) {
+                       jsize len = av_len((AV*)rv) + 1;
+                       int i;
+                       SV** esv;
+                      static jclass jcl = 0;
+                       jarray ja;
+
+                       if (!jcl)
+                           jcl = (*env)->FindClass(env, "java/lang/Object");
+                       ja = (*env)->NewObjectArray(env, len, jcl, 0);
+                       for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) {
+                           if (SvROK(*esv) && (rv = SvRV(*esv)) && SvOBJECT(rv)) {
+                               (*env)->SetObjectArrayElement(env, ja, i,
+                                   (jobject)(void*)SvIV(rv));
+                           }
+                           else {
+                               jobject str = (jobject)(*env)->NewStringUTF(env,
+                                   SvPV(*esv,na));
+                               (*env)->SetObjectArrayElement(env, ja, i, str);
+                           }
+                       }
+                       jv[ix++].l = (jobject)ja;
+                   }
+                   else
+                       jv[ix++].l = (jobject)(void*)0;
+               }
+               else
+                   jv[ix++].l = (jobject)(void*)0;
+               break;
+           }
+           break;
+       case 'L':
+           if (!SvROK(sv) || strnEQ(s, "java/lang/String;", 17)) {
+               s += 17;
+               jv[ix++].l = (jobject)(*env)->NewStringUTF(env,
+                               (char*) SvPV(sv,na));
+               break;
+           }
+           while (*s != ';') s++;
+           s++;
+           if (SvROK(sv)) {
+               SV* rv = SvRV(sv);
+               jv[ix++].l = (jobject)(void*)SvIV(rv);
+           }
+           break;
+       case ')':
+           croak("too many arguments, signature: %s", sig);
+           goto cleanup;
+       default:
+           croak("panic: malformed signature: %s", s-1);
+           goto cleanup;
+       }
+
+    }
+    if (*s != ')') {
+       croak("not enough arguments, signature: %s", sig);
+       goto cleanup;
+    }
+    return jv;
+
+cleanup:
+    safefree((char*)jv);
+    return 0;
+}
+
+static int
+not_here(s)
+char *s;
+{
+    croak("%s not implemented on this architecture", s);
+    return -1;
+}
+
+static double
+constant(name, arg)
+char *name;
+int arg;
+{
+    errno = 0;
+    switch (*name) {
+    case 'A':
+       break;
+    case 'B':
+       break;
+    case 'C':
+       break;
+    case 'D':
+       break;
+    case 'E':
+       break;
+    case 'F':
+       break;
+    case 'G':
+       break;
+    case 'H':
+       break;
+    case 'I':
+       break;
+    case 'J':
+       if (strEQ(name, "JNI_ABORT"))
+#ifdef JNI_ABORT
+           return JNI_ABORT;
+#else
+           goto not_there;
+#endif
+       if (strEQ(name, "JNI_COMMIT"))
+#ifdef JNI_COMMIT
+           return JNI_COMMIT;
+#else
+           goto not_there;
+#endif
+       if (strEQ(name, "JNI_ERR"))
+#ifdef JNI_ERR
+           return JNI_ERR;
+#else
+           goto not_there;
+#endif
+       if (strEQ(name, "JNI_FALSE"))
+#ifdef JNI_FALSE
+           return JNI_FALSE;
+#else
+           goto not_there;
+#endif
+       if (strEQ(name, "JNI_H"))
+#ifdef JNI_H
+           return JNI_H;
+#else
+           goto not_there;
+#endif
+       if (strEQ(name, "JNI_OK"))
+#ifdef JNI_OK
+           return JNI_OK;
+#else
+           goto not_there;
+#endif
+       if (strEQ(name, "JNI_TRUE"))
+#ifdef JNI_TRUE
+           return JNI_TRUE;
+#else
+           goto not_there;
+#endif
+       break;
+    case 'K':
+       break;
+    case 'L':
+       break;
+    case 'M':
+       break;
+    case 'N':
+       break;
+    case 'O':
+       break;
+    case 'P':
+       break;
+    case 'Q':
+       break;
+    case 'R':
+       break;
+    case 'S':
+       break;
+    case 'T':
+       break;
+    case 'U':
+       break;
+    case 'V':
+       break;
+    case 'W':
+       break;
+    case 'X':
+       break;
+    case 'Y':
+       break;
+    case 'Z':
+       break;
+    }
+    errno = EINVAL;
+    return 0;
+
+not_there:
+    errno = ENOENT;
+    return 0;
+}
+
+#define FETCHENV jplcurenv
+#define RESTOREENV jplcurenv = env
+
+MODULE = JNI           PACKAGE = JNI           
+
+PROTOTYPES: ENABLE
+
+double
+constant(name,arg)
+       char *          name
+       int             arg
+
+jint
+GetVersion()
+       JNIEnv *                env = FETCHENV;
+    CODE:
+       {
+           RETVAL = (*env)->GetVersion(env);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jclass
+DefineClass(name, loader, buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jsize                   buf_len_ = NO_INIT;
+       const char *            name
+       jobject                 loader
+       const jbyte *           buf
+    CODE:
+       {
+           RETVAL = (*env)->DefineClass(env,  name, loader, buf, (jsize)buf_len_);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jclass
+FindClass(name)
+       JNIEnv *                env = FETCHENV;
+       const char *            name
+    CODE:
+       {
+           RETVAL = (*env)->FindClass(env,  name);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jclass
+GetSuperclass(sub)
+       JNIEnv *                env = FETCHENV;
+       jclass                  sub
+    CODE:
+       {
+           RETVAL = (*env)->GetSuperclass(env,  sub);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+IsAssignableFrom(sub, sup)
+       JNIEnv *                env = FETCHENV;
+       jclass                  sub
+       jclass                  sup
+    CODE:
+       {
+           RETVAL = (*env)->IsAssignableFrom(env,  sub, sup);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+SysRet
+Throw(obj)
+       JNIEnv *                env = FETCHENV;
+       jthrowable              obj
+    CODE:
+       {
+           RETVAL = (*env)->Throw(env,  obj);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL    
+
+SysRet
+ThrowNew(clazz, msg)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       const char *            msg
+    CODE:
+       {
+           RETVAL = (*env)->ThrowNew(env,  clazz, msg);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jthrowable
+ExceptionOccurred()
+       JNIEnv *                env = FETCHENV;
+    CODE:
+       {
+           RETVAL = (*env)->ExceptionOccurred(env);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+void
+ExceptionDescribe()
+       JNIEnv *                env = FETCHENV;
+    CODE:
+       {
+           (*env)->ExceptionDescribe(env);
+           RESTOREENV;
+       }
+
+void
+ExceptionClear()
+       JNIEnv *                env = FETCHENV;
+    CODE:
+       {
+           (*env)->ExceptionClear(env);
+           RESTOREENV;
+       }
+
+void
+FatalError(msg)
+       JNIEnv *                env = FETCHENV;
+       const char *            msg
+    CODE:
+       {
+           (*env)->FatalError(env,  msg);
+           RESTOREENV;
+       }
+
+jobject
+NewGlobalRef(lobj)
+       JNIEnv *                env = FETCHENV;
+       jobject                 lobj
+    CODE:
+       {
+           RETVAL = (*env)->NewGlobalRef(env, lobj);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+void
+DeleteGlobalRef(gref)
+       JNIEnv *                env = FETCHENV;
+       jobject                 gref
+    CODE:
+       {
+           (*env)->DeleteGlobalRef(env, gref);
+           RESTOREENV;
+       }
+
+void
+DeleteLocalRef(obj)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+    CODE:
+       {
+           (*env)->DeleteLocalRef(env,  obj);
+           RESTOREENV;
+       }
+
+jboolean
+IsSameObject(obj1,obj2)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj1
+       jobject                 obj2
+    CODE:
+       {
+           RETVAL = (*env)->IsSameObject(env, obj1,obj2);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+AllocObject(clazz)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+    CODE:
+       {
+           RETVAL = (*env)->AllocObject(env, clazz);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+NewObject(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->NewObjectA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+NewObjectA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->NewObjectA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jclass
+GetObjectClass(obj)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+    CODE:
+       {
+           RETVAL = (*env)->GetObjectClass(env, obj);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+IsInstanceOf(obj,clazz)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+    CODE:
+       {
+           RETVAL = (*env)->IsInstanceOf(env, obj,clazz);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jmethodID
+GetMethodID(clazz,name,sig)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       const char *            name
+       const char *            sig
+    CODE:
+       {
+           RETVAL = (*env)->GetMethodID(env, clazz,name,sig);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+CallObjectMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallObjectMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+CallObjectMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallObjectMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+CallBooleanMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallBooleanMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+CallBooleanMethodA(obj,methodID, args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallBooleanMethodA(env, obj,methodID, args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyte
+CallByteMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallByteMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyte
+CallByteMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallByteMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jchar
+CallCharMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallCharMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jchar
+CallCharMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallCharMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshort
+CallShortMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallShortMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshort
+CallShortMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallShortMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jint
+CallIntMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallIntMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jint
+CallIntMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallIntMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlong
+CallLongMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallLongMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlong
+CallLongMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallLongMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloat
+CallFloatMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallFloatMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloat
+CallFloatMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallFloatMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdouble
+CallDoubleMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallDoubleMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdouble
+CallDoubleMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallDoubleMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+void
+CallVoidMethod(obj,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           (*env)->CallVoidMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+
+void
+CallVoidMethodA(obj,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           (*env)->CallVoidMethodA(env, obj,methodID,args);
+           RESTOREENV;
+       }
+
+jobject
+CallNonvirtualObjectMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualObjectMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+CallNonvirtualObjectMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualObjectMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+CallNonvirtualBooleanMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualBooleanMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+CallNonvirtualBooleanMethodA(obj,clazz,methodID, args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualBooleanMethodA(env, obj,clazz,methodID, args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyte
+CallNonvirtualByteMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualByteMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyte
+CallNonvirtualByteMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualByteMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jchar
+CallNonvirtualCharMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualCharMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jchar
+CallNonvirtualCharMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualCharMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshort
+CallNonvirtualShortMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualShortMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshort
+CallNonvirtualShortMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualShortMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jint
+CallNonvirtualIntMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualIntMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jint
+CallNonvirtualIntMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualIntMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlong
+CallNonvirtualLongMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualLongMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlong
+CallNonvirtualLongMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualLongMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloat
+CallNonvirtualFloatMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualFloatMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloat
+CallNonvirtualFloatMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualFloatMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdouble
+CallNonvirtualDoubleMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallNonvirtualDoubleMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdouble
+CallNonvirtualDoubleMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallNonvirtualDoubleMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+void
+CallNonvirtualVoidMethod(obj,clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           (*env)->CallNonvirtualVoidMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+
+void
+CallNonvirtualVoidMethodA(obj,clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           (*env)->CallNonvirtualVoidMethodA(env, obj,clazz,methodID,args);
+           RESTOREENV;
+       }
+
+jfieldID
+GetFieldID(clazz,name,sig)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       const char *            name
+       const char *            sig
+    CODE:
+       {
+           RETVAL = (*env)->GetFieldID(env, clazz,name,sig);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+GetObjectField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetObjectField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+GetBooleanField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetBooleanField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyte
+GetByteField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetByteField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jchar
+GetCharField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetCharField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshort
+GetShortField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetShortField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jint
+GetIntField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetIntField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlong
+GetLongField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetLongField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloat
+GetFloatField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetFloatField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdouble
+GetDoubleField(obj,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetDoubleField(env, obj,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+void
+SetObjectField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jobject                 val
+    CODE:
+       {
+           (*env)->SetObjectField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+void
+SetBooleanField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jboolean                val
+    CODE:
+       {
+           (*env)->SetBooleanField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+void
+SetByteField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jbyte                   val
+    CODE:
+       {
+           (*env)->SetByteField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+void
+SetCharField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jchar                   val
+    CODE:
+       {
+           (*env)->SetCharField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+void
+SetShortField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jshort                  val
+    CODE:
+       {
+           (*env)->SetShortField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+void
+SetIntField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jint                    val
+    CODE:
+       {
+           (*env)->SetIntField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+void
+SetLongField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jlong                   val
+    CODE:
+       {
+           (*env)->SetLongField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+void
+SetFloatField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jfloat                  val
+    CODE:
+       {
+           (*env)->SetFloatField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+void
+SetDoubleField(obj,fieldID,val)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jdouble                 val
+    CODE:
+       {
+           (*env)->SetDoubleField(env, obj,fieldID,val);
+           RESTOREENV;
+       }
+
+jmethodID
+GetStaticMethodID(clazz,name,sig)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       const char *            name
+       const char *            sig
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticMethodID(env, clazz,name,sig);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+CallStaticObjectMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticObjectMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+CallStaticObjectMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticObjectMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+CallStaticBooleanMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticBooleanMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+CallStaticBooleanMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticBooleanMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyte
+CallStaticByteMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticByteMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyte
+CallStaticByteMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticByteMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jchar
+CallStaticCharMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticCharMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jchar
+CallStaticCharMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticCharMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshort
+CallStaticShortMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticShortMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshort
+CallStaticShortMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticShortMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jint
+CallStaticIntMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticIntMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jint
+CallStaticIntMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticIntMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlong
+CallStaticLongMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticLongMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlong
+CallStaticLongMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticLongMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloat
+CallStaticFloatMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticFloatMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloat
+CallStaticFloatMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticFloatMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdouble
+CallStaticDoubleMethod(clazz,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           RETVAL = (*env)->CallStaticDoubleMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdouble
+CallStaticDoubleMethodA(clazz,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           RETVAL = (*env)->CallStaticDoubleMethodA(env, clazz,methodID,args);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+void
+CallStaticVoidMethod(cls,methodID,...)
+       JNIEnv *                env = FETCHENV;
+       jclass                  cls
+       jmethodID               methodID
+       char *                  sig = 0;
+       int                     argoff = $min_args;
+    CODE:
+       {
+           jvalue * args = makeargs(sig, &ST(argoff), items - argoff);
+           (*env)->CallStaticVoidMethodA(env, cls,methodID,args);
+           RESTOREENV;
+       }
+
+void
+CallStaticVoidMethodA(cls,methodID,args)
+       JNIEnv *                env = FETCHENV;
+       jclass                  cls
+       jmethodID               methodID
+       char *                  sig = 0;
+       jvalue *                args
+    CODE:
+       {
+           (*env)->CallStaticVoidMethodA(env, cls,methodID,args);
+           RESTOREENV;
+       }
+
+jfieldID
+GetStaticFieldID(clazz,name,sig)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       const char *            name
+       const char *            sig
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticFieldID(env, clazz,name,sig);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+GetStaticObjectField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticObjectField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean
+GetStaticBooleanField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticBooleanField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyte
+GetStaticByteField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticByteField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jchar
+GetStaticCharField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticCharField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshort
+GetStaticShortField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticShortField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jint
+GetStaticIntField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticIntField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlong
+GetStaticLongField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticLongField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloat
+GetStaticFloatField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticFloatField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdouble
+GetStaticDoubleField(clazz,fieldID)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+    CODE:
+       {
+           RETVAL = (*env)->GetStaticDoubleField(env, clazz,fieldID);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+void
+SetStaticObjectField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jobject                 value
+    CODE:
+       {
+         (*env)->SetStaticObjectField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+void
+SetStaticBooleanField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jboolean                value
+    CODE:
+       {
+         (*env)->SetStaticBooleanField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+void
+SetStaticByteField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jbyte                   value
+    CODE:
+       {
+         (*env)->SetStaticByteField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+void
+SetStaticCharField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jchar                   value
+    CODE:
+       {
+         (*env)->SetStaticCharField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+void
+SetStaticShortField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jshort                  value
+    CODE:
+       {
+         (*env)->SetStaticShortField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+void
+SetStaticIntField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jint                    value
+    CODE:
+       {
+         (*env)->SetStaticIntField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+void
+SetStaticLongField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jlong                   value
+    CODE:
+       {
+         (*env)->SetStaticLongField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+void
+SetStaticFloatField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jfloat                  value
+    CODE:
+       {
+         (*env)->SetStaticFloatField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+void
+SetStaticDoubleField(clazz,fieldID,value)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       jfieldID                fieldID
+       char *                  sig = 0;
+       jdouble                 value
+    CODE:
+       {
+         (*env)->SetStaticDoubleField(env, clazz,fieldID,value);
+           RESTOREENV;
+       }
+
+jstring
+NewString(unicode)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jsize                   unicode_len_ = NO_INIT;
+       const jchar *           unicode
+    CODE:
+       {
+           RETVAL = (*env)->NewString(env, unicode, unicode_len_);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jsize
+GetStringLength(str)
+       JNIEnv *                env = FETCHENV;
+       jstring                 str
+    CODE:
+       {
+           RETVAL = (*env)->GetStringLength(env, str);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+const jchar *
+GetStringChars(str)
+       JNIEnv *                env = FETCHENV;
+       jstring                 str
+       jboolean                isCopy = NO_INIT;
+       jsize                   RETVAL_len_ = NO_INIT;
+    CODE:
+       {
+           RETVAL = (*env)->GetStringChars(env, str,&isCopy);
+           RETVAL_len_ = (*env)->GetStringLength(env, str);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+    CLEANUP:
+           (*env)->ReleaseStringChars(env, str,RETVAL);
+
+jstring
+NewStringUTF(utf)
+       JNIEnv *                env = FETCHENV;
+       const char *            utf
+    CODE:
+       {
+           RETVAL = (*env)->NewStringUTF(env, utf);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jsize
+GetStringUTFLength(str)
+       JNIEnv *                env = FETCHENV;
+       jstring                 str
+    CODE:
+       {
+           RETVAL = (*env)->GetStringUTFLength(env, str);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+const char *
+GetStringUTFChars(str)
+       JNIEnv *                env = FETCHENV;
+       jstring                 str
+       jboolean                isCopy = NO_INIT;
+    CODE:
+       {
+           RETVAL = (*env)->GetStringUTFChars(env, str,&isCopy);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+    CLEANUP:
+       (*env)->ReleaseStringUTFChars(env, str, RETVAL);
+
+
+jsize
+GetArrayLength(array)
+       JNIEnv *                env = FETCHENV;
+       jarray                  array
+    CODE:
+       {
+           RETVAL = (*env)->GetArrayLength(env, array);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobjectArray
+NewObjectArray(len,clazz,init)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+       jclass                  clazz
+       jobject                 init
+    CODE:
+       {
+           RETVAL = (*env)->NewObjectArray(env, len,clazz,init);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jobject
+GetObjectArrayElement(array,index)
+       JNIEnv *                env = FETCHENV;
+       jobjectArray            array
+       jsize                   index
+    CODE:
+       {
+           RETVAL = (*env)->GetObjectArrayElement(env, array,index);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+void
+SetObjectArrayElement(array,index,val)
+       JNIEnv *                env = FETCHENV;
+       jobjectArray            array
+       jsize                   index
+       jobject                 val
+    CODE:
+       {
+           (*env)->SetObjectArrayElement(env, array,index,val);
+           RESTOREENV;
+       }
+
+jbooleanArray
+NewBooleanArray(len)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+    CODE:
+       {
+           RETVAL = (*env)->NewBooleanArray(env, len);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jbyteArray
+NewByteArray(len)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+    CODE:
+       {
+           RETVAL = (*env)->NewByteArray(env, len);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jcharArray
+NewCharArray(len)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+    CODE:
+       {
+           RETVAL = (*env)->NewCharArray(env, len);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jshortArray
+NewShortArray(len)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+    CODE:
+       {
+           RETVAL = (*env)->NewShortArray(env, len);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jintArray
+NewIntArray(len)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+    CODE:
+       {
+           RETVAL = (*env)->NewIntArray(env, len);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jlongArray
+NewLongArray(len)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+    CODE:
+       {
+           RETVAL = (*env)->NewLongArray(env, len);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jfloatArray
+NewFloatArray(len)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+    CODE:
+       {
+           RETVAL = (*env)->NewFloatArray(env, len);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jdoubleArray
+NewDoubleArray(len)
+       JNIEnv *                env = FETCHENV;
+       jsize                   len
+    CODE:
+       {
+           RETVAL = (*env)->NewDoubleArray(env, len);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+jboolean *
+GetBooleanArrayElements(array)
+       JNIEnv *                env = FETCHENV;
+       jsize                   RETVAL_len_ = NO_INIT;
+       jbooleanArray           array
+       jboolean                isCopy = NO_INIT;
+    PPCODE:
+       {
+           RETVAL = (*env)->GetBooleanArrayElements(env, array,&isCopy);
+           RETVAL_len_ = (*env)->GetArrayLength(env, array);
+           if (GIMME == G_ARRAY) {
+               int i;
+               jboolean* r = RETVAL;
+               EXTEND(sp, RETVAL_len_);
+               for (i = RETVAL_len_; i; --i) {
+                   PUSHs(sv_2mortal(newSViv(*r++)));
+               }
+           }
+           else {
+               if (RETVAL_len_) {
+                   PUSHs(sv_2mortal(newSVpv((char*)RETVAL,
+                       (STRLEN)RETVAL_len_ * sizeof(jboolean))));
+               }
+               else
+                   PUSHs(&sv_no);
+           }
+           (*env)->ReleaseBooleanArrayElements(env, array,RETVAL,JNI_ABORT);
+           RESTOREENV;
+       }
+
+jbyte *
+GetByteArrayElements(array)
+       JNIEnv *                env = FETCHENV;
+       jsize                   RETVAL_len_ = NO_INIT;
+       jbyteArray              array
+       jboolean                isCopy = NO_INIT;
+    PPCODE:
+       {
+           RETVAL = (*env)->GetByteArrayElements(env, array,&isCopy);
+           RETVAL_len_ = (*env)->GetArrayLength(env, array);
+           if (GIMME == G_ARRAY) {
+               int i;
+               jbyte* r = RETVAL;
+               EXTEND(sp, RETVAL_len_);
+               for (i = RETVAL_len_; i; --i) {
+                   PUSHs(sv_2mortal(newSViv(*r++)));
+               }
+           }
+           else {
+               if (RETVAL_len_) {
+                   PUSHs(sv_2mortal(newSVpv((char*)RETVAL,
+                       (STRLEN)RETVAL_len_ * sizeof(jbyte))));
+               }
+               else
+                   PUSHs(&sv_no);
+           }
+           (*env)->ReleaseByteArrayElements(env, array,RETVAL,JNI_ABORT);
+           RESTOREENV;
+       }
+
+jchar *
+GetCharArrayElements(array)
+       JNIEnv *                env = FETCHENV;
+       jsize                   RETVAL_len_ = NO_INIT;
+       jcharArray              array
+       jboolean                isCopy = NO_INIT;
+    PPCODE:
+       {
+           RETVAL = (*env)->GetCharArrayElements(env, array,&isCopy);
+           RETVAL_len_ = (*env)->GetArrayLength(env, array);
+           if (GIMME == G_ARRAY) {
+               int i;
+               jchar* r = RETVAL;
+               EXTEND(sp, RETVAL_len_);
+               for (i = RETVAL_len_; i; --i) {
+                   PUSHs(sv_2mortal(newSViv(*r++)));
+               }
+           }
+           else {
+               if (RETVAL_len_) {
+                   PUSHs(sv_2mortal(newSVpv((char*)RETVAL,
+                       (STRLEN)RETVAL_len_ * sizeof(jchar))));
+               }
+               else
+                   PUSHs(&sv_no);
+           }
+           (*env)->ReleaseCharArrayElements(env, array,RETVAL,JNI_ABORT);
+           RESTOREENV;
+       }
+
+jshort *
+GetShortArrayElements(array)
+       JNIEnv *                env = FETCHENV;
+       jsize                   RETVAL_len_ = NO_INIT;
+       jshortArray             array
+       jboolean                isCopy = NO_INIT;
+    PPCODE:
+       {
+           RETVAL = (*env)->GetShortArrayElements(env, array,&isCopy);
+           RETVAL_len_ = (*env)->GetArrayLength(env, array);
+           if (GIMME == G_ARRAY) {
+               int i;
+               jshort* r = RETVAL;
+               EXTEND(sp, RETVAL_len_);
+               for (i = RETVAL_len_; i; --i) {
+                   PUSHs(sv_2mortal(newSViv(*r++)));
+               }
+           }
+           else {
+               if (RETVAL_len_) {
+                   PUSHs(sv_2mortal(newSVpv((char*)RETVAL,
+                       (STRLEN)RETVAL_len_ * sizeof(jshort))));
+               }
+               else
+                   PUSHs(&sv_no);
+           }
+           (*env)->ReleaseShortArrayElements(env, array,RETVAL,JNI_ABORT);
+           RESTOREENV;
+       }
+
+jint *
+GetIntArrayElements(array)
+       JNIEnv *                env = FETCHENV;
+       jsize                   RETVAL_len_ = NO_INIT;
+       jintArray               array
+       jboolean                isCopy = NO_INIT;
+    PPCODE:
+       {
+           RETVAL = (*env)->GetIntArrayElements(env, array,&isCopy);
+           RETVAL_len_ = (*env)->GetArrayLength(env, array);
+           if (GIMME == G_ARRAY) {
+               int i;
+               jint* r = RETVAL;
+               EXTEND(sp, RETVAL_len_);
+               for (i = RETVAL_len_; i; --i) {
+                   PUSHs(sv_2mortal(newSViv(*r++)));
+               }
+           }
+           else {
+               if (RETVAL_len_) {
+                   PUSHs(sv_2mortal(newSVpv((char*)RETVAL,
+                       (STRLEN)RETVAL_len_ * sizeof(jint))));
+               }
+               else
+                   PUSHs(&sv_no);
+           }
+           (*env)->ReleaseIntArrayElements(env, array,RETVAL,JNI_ABORT);
+           RESTOREENV;
+       }
+
+jlong *
+GetLongArrayElements(array)
+       JNIEnv *                env = FETCHENV;
+       jsize                   RETVAL_len_ = NO_INIT;
+       jlongArray              array
+       jboolean                isCopy = NO_INIT;
+    PPCODE:
+       {
+           RETVAL = (*env)->GetLongArrayElements(env, array,&isCopy);
+           RETVAL_len_ = (*env)->GetArrayLength(env, array);
+           if (GIMME == G_ARRAY) {
+               int i;
+               jlong* r = RETVAL;
+               EXTEND(sp, RETVAL_len_);
+               for (i = RETVAL_len_; i; --i) {
+                   PUSHs(sv_2mortal(newSViv(*r++)));
+               }
+           }
+           else {
+               if (RETVAL_len_) {
+                   PUSHs(sv_2mortal(newSVpv((char*)RETVAL,
+                       (STRLEN)RETVAL_len_ * sizeof(jlong))));
+               }
+               else
+                   PUSHs(&sv_no);
+           }
+           (*env)->ReleaseLongArrayElements(env, array,RETVAL,JNI_ABORT);
+           RESTOREENV;
+       }
+
+jfloat *
+GetFloatArrayElements(array)
+       JNIEnv *                env = FETCHENV;
+       jsize                   RETVAL_len_ = NO_INIT;
+       jfloatArray             array
+       jboolean                isCopy = NO_INIT;
+    PPCODE:
+       {
+           RETVAL = (*env)->GetFloatArrayElements(env, array,&isCopy);
+           RETVAL_len_ = (*env)->GetArrayLength(env, array);
+           if (GIMME == G_ARRAY) {
+               int i;
+               jfloat* r = RETVAL;
+               EXTEND(sp, RETVAL_len_);
+               for (i = RETVAL_len_; i; --i) {
+                   PUSHs(sv_2mortal(newSVnv(*r++)));
+               }
+           }
+           else {
+               if (RETVAL_len_) {
+                   PUSHs(sv_2mortal(newSVpv((char*)RETVAL,
+                       (STRLEN)RETVAL_len_ * sizeof(jfloat))));
+               }
+               else
+                   PUSHs(&sv_no);
+           }
+           (*env)->ReleaseFloatArrayElements(env, array,RETVAL,JNI_ABORT);
+           RESTOREENV;
+       }
+
+jdouble *
+GetDoubleArrayElements(array)
+       JNIEnv *                env = FETCHENV;
+       jsize                   RETVAL_len_ = NO_INIT;
+       jdoubleArray            array
+       jboolean                isCopy = NO_INIT;
+    PPCODE:
+       {
+           RETVAL = (*env)->GetDoubleArrayElements(env, array,&isCopy);
+           RETVAL_len_ = (*env)->GetArrayLength(env, array);
+           if (GIMME == G_ARRAY) {
+               int i;
+               jdouble* r = RETVAL;
+               EXTEND(sp, RETVAL_len_);
+               for (i = RETVAL_len_; i; --i) {
+                   PUSHs(sv_2mortal(newSVnv(*r++)));
+               }
+           }
+           else {
+               if (RETVAL_len_) {
+                   PUSHs(sv_2mortal(newSVpv((char*)RETVAL,
+                       (STRLEN)RETVAL_len_ * sizeof(jdouble))));
+               }
+               else
+                   PUSHs(&sv_no);
+           }
+           (*env)->ReleaseDoubleArrayElements(env, array,RETVAL,JNI_ABORT);
+           RESTOREENV;
+       }
+
+void
+GetBooleanArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       jbooleanArray           array
+       jsize                   start
+       jsize                   len
+       STRLEN                  tmplen = len * sizeof(jboolean) + 1;
+       char *                  tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen);
+       jboolean *              buf = (jboolean*)sv_grow(ST(3),len * sizeof(jboolean)+1);
+    CODE:
+       {
+           (*env)->GetBooleanArrayRegion(env, array,start,len,buf);
+           SvCUR_set(ST(3), len * sizeof(jboolean));
+           *SvEND(ST(3)) = '\0';
+           RESTOREENV;
+       }
+
+void
+GetByteArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       jbyteArray              array
+       jsize                   start
+       jsize                   len
+       STRLEN                  tmplen = len * sizeof(jboolean) + 1;
+       char *                  tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen);
+       jbyte *                 buf = (jbyte*)sv_grow(ST(3),len * sizeof(jbyte)+1);
+    CODE:
+       {
+           (*env)->GetByteArrayRegion(env, array,start,len,buf);
+           SvCUR_set(ST(3), len * sizeof(jbyte));
+           *SvEND(ST(3)) = '\0';
+           RESTOREENV;
+       }
+
+void
+GetCharArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       jcharArray              array
+       jsize                   start
+       jsize                   len
+       STRLEN                  tmplen = len * sizeof(jboolean) + 1;
+       char *                  tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen);
+       jchar *                 buf = (jchar*)sv_grow(ST(3),len * sizeof(jchar)+1);
+    CODE:
+       {
+           (*env)->GetCharArrayRegion(env, array,start,len,buf);
+           SvCUR_set(ST(3), len * sizeof(jchar));
+           *SvEND(ST(3)) = '\0';
+           RESTOREENV;
+       }
+
+void
+GetShortArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       jshortArray             array
+       jsize                   start
+       jsize                   len
+       STRLEN                  tmplen = len * sizeof(jboolean) + 1;
+       char *                  tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen);
+       jshort *                buf = (jshort*)sv_grow(ST(3),len * sizeof(jshort)+1);
+    CODE:
+       {
+           (*env)->GetShortArrayRegion(env, array,start,len,buf);
+           SvCUR_set(ST(3), len * sizeof(jshort));
+           *SvEND(ST(3)) = '\0';
+           RESTOREENV;
+       }
+
+void
+GetIntArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       jintArray               array
+       jsize                   start
+       jsize                   len
+       STRLEN                  tmplen = len * sizeof(jboolean) + 1;
+       char *                  tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen);
+       jint *                  buf = (jint*)sv_grow(ST(3),len * sizeof(jint)+1);
+    CODE:
+       {
+           (*env)->GetIntArrayRegion(env, array,start,len,buf);
+           SvCUR_set(ST(3), len * sizeof(jint));
+           *SvEND(ST(3)) = '\0';
+           RESTOREENV;
+       }
+
+void
+GetLongArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       jlongArray              array
+       jsize                   start
+       jsize                   len
+       STRLEN                  tmplen = len * sizeof(jboolean) + 1;
+       char *                  tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen);
+       jlong *                 buf = (jlong*)sv_grow(ST(3),len * sizeof(jlong)+1);
+    CODE:
+       {
+           (*env)->GetLongArrayRegion(env, array,start,len,buf);
+           SvCUR_set(ST(3), len * sizeof(jlong));
+           *SvEND(ST(3)) = '\0';
+           RESTOREENV;
+       }
+
+void
+GetFloatArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       jfloatArray             array
+       jsize                   start
+       jsize                   len
+       STRLEN                  tmplen = len * sizeof(jboolean) + 1;
+       char *                  tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen);
+       jfloat *                buf = (jfloat*)sv_grow(ST(3),len * sizeof(jfloat)+1);
+    CODE:
+       {
+           (*env)->GetFloatArrayRegion(env, array,start,len,buf);
+           SvCUR_set(ST(3), len * sizeof(jfloat));
+           *SvEND(ST(3)) = '\0';
+           RESTOREENV;
+       }
+
+void
+GetDoubleArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       jdoubleArray            array
+       jsize                   start
+       jsize                   len
+       STRLEN                  tmplen = len * sizeof(jboolean) + 1;
+       char *                  tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen);
+       jdouble *               buf = (jdouble*)sv_grow(ST(3),len * sizeof(jdouble)+1);
+    CODE:
+       {
+           (*env)->GetDoubleArrayRegion(env, array,start,len,buf);
+           SvCUR_set(ST(3), len * sizeof(jdouble));
+           *SvEND(ST(3)) = '\0';
+           RESTOREENV;
+       }
+
+void
+SetBooleanArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jbooleanArray           array
+       jsize                   start
+       jsize                   len
+       jsize                   buf_len_ = NO_INIT;
+       jboolean *              buf
+    CODE:
+       {
+           if (buf_len_ < len)
+               croak("string is too short");
+           else if (buf_len_ > len && dowarn)
+               warn("string is too long");
+           (*env)->SetBooleanArrayRegion(env, array,start,len,buf);
+           RESTOREENV;
+       }
+
+void
+SetByteArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jbyteArray              array
+       jsize                   start
+       jsize                   len
+       jsize                   buf_len_ = NO_INIT;
+       jbyte *                 buf
+    CODE:
+       {
+           if (buf_len_ < len)
+               croak("string is too short");
+           else if (buf_len_ > len && dowarn)
+               warn("string is too long");
+           (*env)->SetByteArrayRegion(env, array,start,len,buf);
+           RESTOREENV;
+       }
+
+void
+SetCharArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jcharArray              array
+       jsize                   start
+       jsize                   len
+       jsize                   buf_len_ = NO_INIT;
+       jchar *                 buf
+    CODE:
+       {
+           if (buf_len_ < len)
+               croak("string is too short");
+           else if (buf_len_ > len && dowarn)
+               warn("string is too long");
+           (*env)->SetCharArrayRegion(env, array,start,len,buf);
+           RESTOREENV;
+       }
+
+void
+SetShortArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jshortArray             array
+       jsize                   start
+       jsize                   len
+       jsize                   buf_len_ = NO_INIT;
+       jshort *                buf
+    CODE:
+       {
+           if (buf_len_ < len)
+               croak("string is too short");
+           else if (buf_len_ > len && dowarn)
+               warn("string is too long");
+           (*env)->SetShortArrayRegion(env, array,start,len,buf);
+           RESTOREENV;
+       }
+
+void
+SetIntArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jintArray               array
+       jsize                   start
+       jsize                   len
+       jsize                   buf_len_ = NO_INIT;
+       jint *                  buf
+    CODE:
+       {
+           if (buf_len_ < len)
+               croak("string is too short");
+           else if (buf_len_ > len && dowarn)
+               warn("string is too long");
+           (*env)->SetIntArrayRegion(env, array,start,len,buf);
+           RESTOREENV;
+       }
+
+void
+SetLongArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jlongArray              array
+       jsize                   start
+       jsize                   len
+       jsize                   buf_len_ = NO_INIT;
+       jlong *                 buf
+    CODE:
+       {
+           if (buf_len_ < len)
+               croak("string is too short");
+           else if (buf_len_ > len && dowarn)
+               warn("string is too long");
+           (*env)->SetLongArrayRegion(env, array,start,len,buf);
+           RESTOREENV;
+       }
+
+void
+SetFloatArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jfloatArray             array
+       jsize                   start
+       jsize                   len
+       jsize                   buf_len_ = NO_INIT;
+       jfloat *                buf
+    CODE:
+       {
+           if (buf_len_ < len)
+               croak("string is too short");
+           else if (buf_len_ > len && dowarn)
+               warn("string is too long");
+           (*env)->SetFloatArrayRegion(env, array,start,len,buf);
+           RESTOREENV;
+       }
+
+void
+SetDoubleArrayRegion(array,start,len,buf)
+       JNIEnv *                env = FETCHENV;
+       STRLEN                  tmplen = NO_INIT;
+       jdoubleArray            array
+       jsize                   start
+       jsize                   len
+       jsize                   buf_len_ = NO_INIT;
+       jdouble *               buf
+    CODE:
+       {
+           if (buf_len_ < len)
+               croak("string is too short");
+           else if (buf_len_ > len && dowarn)
+               warn("string is too long");
+           (*env)->SetDoubleArrayRegion(env, array,start,len,buf);
+           RESTOREENV;
+       }
+
+SysRet
+RegisterNatives(clazz,methods,nMethods)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+       JNINativeMethod *       methods
+       jint                    nMethods
+    CODE:
+       {
+           RETVAL = (*env)->RegisterNatives(env, clazz,methods,nMethods);
+       }
+
+SysRet
+UnregisterNatives(clazz)
+       JNIEnv *                env = FETCHENV;
+       jclass                  clazz
+    CODE:
+       {
+           RETVAL = (*env)->UnregisterNatives(env, clazz);
+       }
+    OUTPUT:
+       RETVAL  
+   
+SysRet
+MonitorEnter(obj)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+    CODE:
+       {
+           RETVAL = (*env)->MonitorEnter(env, obj);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+SysRet
+MonitorExit(obj)
+       JNIEnv *                env = FETCHENV;
+       jobject                 obj
+    CODE:
+       {
+           RETVAL = (*env)->MonitorExit(env, obj);
+           RESTOREENV;
+       }
+    OUTPUT:
+       RETVAL
+
+JavaVM *
+GetJavaVM(...)
+       JNIEnv *                env = FETCHENV;
+    CODE:
+       {
+           if (env) {  /* We're embedded. */
+               if ((*env)->GetJavaVM(env, &RETVAL) < 0)
+                   RETVAL = 0;
+           }
+           else {      /* We're embedding. */
+               JDK1_1InitArgs vm_args;
+               char *lib;
+
+               if (items--) {
+                   ++mark;
+                   lib = SvPV(*mark, na);
+               }
+               else
+                   lib = 0;
+
+               if (!dlopen("libjava.so", RTLD_LAZY|RTLD_GLOBAL)) {
+                   if (lib && !dlopen(lib, RTLD_LAZY|RTLD_GLOBAL))
+                       croak("Can't load libjava.so");
+               }
+
+               JNI_GetDefaultJavaVMInitArgs(&vm_args);
+               vm_args.exit = &call_my_exit;
+               while (items > 1) {
+                   char *s = SvPV(*++mark,na);
+                   items -= 2;
+                   if (strEQ(s, "checkSource"))
+                       vm_args.checkSource = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "nativeStackSize"))
+                       vm_args.nativeStackSize = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "javaStackSize"))
+                       vm_args.javaStackSize = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "minHeapSize"))
+                       vm_args.minHeapSize = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "maxHeapSize"))
+                       vm_args.maxHeapSize = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "verifyMode"))
+                       vm_args.verifyMode = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "classpath"))
+                       vm_args.classpath = savepv(SvPV(*++mark,na));
+                   else if (strEQ(s, "enableClassGC"))
+                       vm_args.enableClassGC = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "enableVerboseGC"))
+                       vm_args.enableVerboseGC = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "disableAsyncGC"))
+                       vm_args.disableAsyncGC = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "verbose"))
+                       vm_args.verbose = (jint)SvIV(*++mark);
+                   else if (strEQ(s, "debugging"))
+                       vm_args.debugging = (jboolean)SvIV(*++mark);
+                   else if (strEQ(s, "debugPort"))
+                       vm_args.debugPort = (jint)SvIV(*++mark);
+                   else
+                       croak("unrecognized option: %s", s);
+               }
+               JNI_CreateJavaVM(&RETVAL, &jplcurenv, &vm_args);
+           }
+       }
+
diff --git a/JNI/MANIFEST b/JNI/MANIFEST
new file mode 100644 (file)
index 0000000..14a0f6c
--- /dev/null
@@ -0,0 +1,6 @@
+Changes
+JNI.pm
+JNI.xs
+MANIFEST
+Makefile.PL
+test.pl
diff --git a/JNI/Makefile.PL b/JNI/Makefile.PL
new file mode 100644 (file)
index 0000000..2611ff1
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+
+$JPL_SRC = "..";
+
+use ExtUtils::MakeMaker;
+use Config;
+
+eval `$JPL_SRC/setvars -perl`;
+
+$java = $ENV{JAVA_HOME};
+$jpl = $ENV{JPL_HOME};
+
+$ARCHNAME = $Config{archname};
+
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+    NAME       => 'JNI',
+    VERSION_FROM => 'JNI.pm',
+    LIBS       => ["-R$Config{archlib}/CORE -L$Config{archlib}/CORE -R$jpl/lib/$ARCHNAME -L$jpl/lib/$ARCHNAME -lperl -lPerlInterpreter"],
+    DEFINE     => '',
+    LINKTYPE => 'dynamic',
+    INC        => "-I$java/include -I$java/include/$^O -I$java/include/genunix",
+);
diff --git a/JNI/test.pl b/JNI/test.pl
new file mode 100644 (file)
index 0000000..816e28b
--- /dev/null
@@ -0,0 +1,20 @@
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..1\n"; }
+END {print "not ok 1\n" unless $loaded;}
+use JNI;
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
diff --git a/JNI/typemap b/JNI/typemap
new file mode 100644 (file)
index 0000000..c5b15f6
--- /dev/null
@@ -0,0 +1,386 @@
+JavaVM *               T_JPTROBJ
+JNINativeMethod *      T_JPTROBJ
+const char *           T_PV
+const jbyte *          T_JMEM
+const jchar *          T_JMEM
+jarray                 T_JPTROBJ
+jboolean               T_IV
+jboolean *             T_JMEM
+jbooleanArray          T_JPTROBJ
+jbyte                  T_IV
+jbyte *                        T_JMEM
+jbyteArray             T_JPTROBJ
+jchar                  T_IV
+jchar *                        T_JMEM
+jcharArray             T_JPTROBJ
+jclass                 T_JPTROBJ
+jdouble                        T_NV
+jdouble *              T_JMEM
+jdoubleArray           T_JPTROBJ
+jfieldID               T_JIDSIG
+jfloat                 T_NV
+jfloat *               T_JMEM
+jfloatArray            T_JPTROBJ
+jint                   T_IV
+jint *                 T_JMEM
+jintArray              T_JPTROBJ
+jlong                  T_NV
+jlong *                        T_JMEM
+jlongArray             T_JPTROBJ
+jmethodID              T_JIDSIG
+jobject                        T_JPTROBJ
+jobjectArray           T_JPTROBJ
+jshort                 T_IV
+jshort *               T_JMEM
+jshortArray            T_JPTROBJ
+jsize                  T_IV
+jstring                        T_JSTRING
+jthrowable             T_JPTROBJ
+jvalue *               T_JVALUELIST
+
+INPUT
+T_JMEM
+       {
+           $var = ($type)SvPV($arg,tmplen);
+           ${var}_len_ = (jsize) tmplen / sizeof(${subtype});
+       }
+T_JSTRING
+       if (SvROK($arg)) {
+           $var = ($type)(void*)SvIV(SvRV($arg));
+       }
+       else
+           $var = ($type)(*env)->NewStringUTF(env, (char *) SvPV($arg,na))
+T_JVALUELIST
+       if (SvROK($arg)) {
+           AV* av = (AV*)SvRV($arg);
+           if (SvTYPE(av) == SVt_PVAV) {
+               I32 maxarg = AvFILL(av) + 1;
+               $var = makeargs(sig, AvARRAY(av), maxarg);
+           }
+           else
+               croak(\"$var is not an array reference\");
+       }
+       else
+           croak(\"$var is not a reference\")
+T_JIDSIG
+       {
+           $var = ($type)SvIV($arg);
+           sig = (char*)SvPV($arg,na);
+       }
+T_JPTROBJ
+       if (SvROK($arg) && SvOBJECT(SvRV($arg))) {
+           IV tmp = SvIV((SV*)SvRV($arg));
+           $var = ($type) tmp;
+       }
+       else
+           croak(\"$var is not of type ${ntype}\")
+
+OUTPUT
+T_JMEM
+       sv_setpvn((SV*)$arg, (char*)$var, (STRLEN)${var}_len_ * sizeof(${subtype}));
+T_JSTRING
+       {
+           static HV* ${var}_stashhv_ = 0;
+           if (!${var}_stashhv_)
+               ${var}_stashhv_ = gv_stashpv("java::lang::String", TRUE);
+        
+           sv_bless(
+               sv_setref_iv($arg, Nullch, (IV)(void*)${var}),
+               ${var}_stashhv_);
+       }
+T_JIDSIG
+       sv_setiv($arg, (IV)(void*)$var);
+       sv_setpv($arg, (char*)sig);
+       SvIOK_on($arg);
+T_JPTROBJ
+       sv_setref_pv($arg, \"${ntype}\", (void*)$var);
+
+# basic C types
+#      int                     T_IV
+#      unsigned                T_IV
+#      unsigned int            T_IV
+#      long                    T_IV
+#      unsigned long           T_IV
+#      short                   T_IV
+#      unsigned short          T_IV
+#      char                    T_CHAR
+#      unsigned char           T_U_CHAR
+#      char *                  T_PV
+#      unsigned char *         T_PV
+#      caddr_t                 T_PV
+#      wchar_t *               T_PV
+#      wchar_t                 T_IV
+#      bool_t                  T_IV
+#      size_t                  T_IV
+#      ssize_t                 T_IV
+#      time_t                  T_NV
+#      unsigned long *         T_OPAQUEPTR
+#      char **                 T_PACKED
+#      void *                  T_PTR
+#      Time_t *                T_PV
+#      SV *                    T_SV
+#      SVREF                   T_SVREF
+#      AV *                    T_AVREF
+#      HV *                    T_HVREF
+#      CV *                    T_CVREF
+#      
+#      IV                      T_IV
+#      I32                     T_IV
+#      I16                     T_IV
+#      I8                      T_IV
+#      U32                     T_U_LONG
+#      U16                     T_U_SHORT
+#      U8                      T_IV
+#      Result                  T_U_CHAR
+#      Boolean                 T_IV
+#      double                  T_DOUBLE
+#      SysRet                  T_SYSRET
+#      SysRetLong              T_SYSRET
+#      FILE *                  T_IN
+#      FileHandle              T_PTROBJ
+#      InputStream             T_IN
+#      InOutStream             T_INOUT
+#      OutputStream            T_OUT
+#      bool                    T_BOOL
+#
+#############################################################################
+#      INPUT
+#      T_SV
+#              $var = $arg
+#      T_SVREF
+#              if (sv_isa($arg, \"${ntype}\"))
+#                  $var = (SV*)SvRV($arg);
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_AVREF
+#              if (sv_isa($arg, \"${ntype}\"))
+#                  $var = (AV*)SvRV($arg);
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_HVREF
+#              if (sv_isa($arg, \"${ntype}\"))
+#                  $var = (HV*)SvRV($arg);
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_CVREF
+#              if (sv_isa($arg, \"${ntype}\"))
+#                  $var = (CV*)SvRV($arg);
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_SYSRET
+#              $var NOT IMPLEMENTED
+#      T_IV
+#              $var = ($type)SvIV($arg)
+#      T_INT
+#              $var = (int)SvIV($arg)
+#      T_ENUM
+#              $var = ($type)SvIV($arg)
+#      T_BOOL
+#              $var = (int)SvIV($arg)
+#      T_U_INT
+#              $var = (unsigned int)SvIV($arg)
+#      T_SHORT
+#              $var = (short)SvIV($arg)
+#      T_U_SHORT
+#              $var = (unsigned short)SvIV($arg)
+#      T_LONG
+#              $var = (long)SvIV($arg)
+#      T_U_LONG
+#              $var = (unsigned long)SvIV($arg)
+#      T_CHAR
+#              $var = (char)*SvPV($arg,na)
+#      T_U_CHAR
+#              $var = (unsigned char)SvIV($arg)
+#      T_FLOAT
+#              $var = (float)SvNV($arg)
+#      T_NV
+#              $var = ($type)SvNV($arg)
+#      T_DOUBLE
+#              $var = (double)SvNV($arg)
+#      T_PV
+#              $var = ($type)SvPV($arg,na)
+#      T_PTR
+#              $var = ($type)SvIV($arg)
+#      T_PTRREF
+#              if (SvROK($arg)) {
+#                  IV tmp = SvIV((SV*)SvRV($arg));
+#                  $var = ($type) tmp;
+#              }
+#              else
+#                  croak(\"$var is not a reference\")
+#      T_REF_IV_REF
+#              if (sv_isa($arg, \"${type}\")) {
+#                  IV tmp = SvIV((SV*)SvRV($arg));
+#                  $var = *($type *) tmp;
+#              }
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_REF_IV_PTR
+#              if (sv_isa($arg, \"${type}\")) {
+#                  IV tmp = SvIV((SV*)SvRV($arg));
+#                  $var = ($type) tmp;
+#              }
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_PTROBJ
+#              if (sv_derived_from($arg, \"${ntype}\")) {
+#                  IV tmp = SvIV((SV*)SvRV($arg));
+#                  $var = ($type) tmp;
+#              }
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_PTRDESC
+#              if (sv_isa($arg, \"${ntype}\")) {
+#                  IV tmp = SvIV((SV*)SvRV($arg));
+#                  ${type}_desc = (\U${type}_DESC\E*) tmp; 
+#                  $var = ${type}_desc->ptr;
+#              }
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_REFREF
+#              if (SvROK($arg)) {
+#                  IV tmp = SvIV((SV*)SvRV($arg));
+#                  $var = *($type) tmp;
+#              }
+#              else
+#                  croak(\"$var is not a reference\")
+#      T_REFOBJ
+#              if (sv_isa($arg, \"${ntype}\")) {
+#                  IV tmp = SvIV((SV*)SvRV($arg));
+#                  $var = *($type) tmp;
+#              }
+#              else
+#                  croak(\"$var is not of type ${ntype}\")
+#      T_OPAQUE
+#              $var NOT IMPLEMENTED
+#      T_OPAQUEPTR
+#              $var = ($type)SvPV($arg,na)
+#      T_PACKED
+#              $var = XS_unpack_$ntype($arg)
+#      T_PACKEDARRAY
+#              $var = XS_unpack_$ntype($arg)
+#      T_CALLBACK
+#              $var = make_perl_cb_$type($arg)
+#      T_ARRAY
+#              $var = $ntype(items -= $argoff);
+#              U32 ix_$var = $argoff;
+#              while (items--) {
+#                  DO_ARRAY_ELEM;
+#              }
+#      T_IN
+#              $var = IoIFP(sv_2io($arg))
+#      T_INOUT
+#              $var = IoIFP(sv_2io($arg))
+#      T_OUT
+#              $var = IoOFP(sv_2io($arg))
+##############################################################################
+#      OUTPUT
+#      T_SV
+#              $arg = $var;
+#      T_SVREF
+#              $arg = newRV((SV*)$var);
+#      T_AVREF
+#              $arg = newRV((SV*)$var);
+#      T_HVREF
+#              $arg = newRV((SV*)$var);
+#      T_CVREF
+#              $arg = newRV((SV*)$var);
+#      T_IV
+#              sv_setiv($arg, (IV)$var);
+#      T_INT
+#              sv_setiv($arg, (IV)$var);
+#      T_SYSRET
+#              if ($var != -1) {
+#                  if ($var == 0)
+#                      sv_setpvn($arg, "0 but true", 10);
+#                  else
+#                      sv_setiv($arg, (IV)$var);
+#              }
+#      T_ENUM
+#              sv_setiv($arg, (IV)$var);
+#      T_BOOL
+#              $arg = boolSV($var);
+#      T_U_INT
+#              sv_setiv($arg, (IV)$var);
+#      T_SHORT
+#              sv_setiv($arg, (IV)$var);
+#      T_U_SHORT
+#              sv_setiv($arg, (IV)$var);
+#      T_LONG
+#              sv_setiv($arg, (IV)$var);
+#      T_U_LONG
+#              sv_setiv($arg, (IV)$var);
+#      T_CHAR
+#              sv_setpvn($arg, (char *)&$var, 1);
+#      T_U_CHAR
+#              sv_setiv($arg, (IV)$var);
+#      T_FLOAT
+#              sv_setnv($arg, (double)$var);
+#      T_NV
+#              sv_setnv($arg, (double)$var);
+#      T_DOUBLE
+#              sv_setnv($arg, (double)$var);
+#      T_PV
+#              sv_setpv((SV*)$arg, $var);
+#      T_PTR
+#              sv_setiv($arg, (IV)$var);
+#      T_PTRREF
+#              sv_setref_pv($arg, Nullch, (void*)$var);
+#      T_REF_IV_REF
+#              sv_setref_pv($arg, \"${ntype}\", (void*)new $ntype($var));
+#      T_REF_IV_PTR
+#              sv_setref_pv($arg, \"${ntype}\", (void*)$var);
+#      T_PTROBJ
+#              sv_setref_pv($arg, \"${ntype}\", (void*)$var);
+#      T_PTRDESC
+#              sv_setref_pv($arg, \"${ntype}\", (void*)new\U${type}_DESC\E($var));
+#      T_REFREF
+#              sv_setrefref($arg, \"${ntype}\", XS_service_$ntype,
+#                          ($var ? (void*)new $ntype($var) : 0));
+#      T_REFOBJ
+#              NOT IMPLEMENTED
+#      T_OPAQUE
+#              sv_setpvn($arg, (char *)&$var, sizeof($var));
+#      T_OPAQUEPTR
+#              sv_setpvn($arg, (char *)$var, sizeof(*$var)), XFree((char *)$var);
+#      T_PACKED
+#              XS_pack_$ntype($arg, $var);
+#      T_PACKEDARRAY
+#              XS_pack_$ntype($arg, $var, count_$ntype);
+#      T_DATAUNIT      
+#              sv_setpvn($arg, $var.chp(), $var.size());
+#      T_CALLBACK
+#              sv_setpvn($arg, $var.context.value().chp(),
+#                      $var.context.value().size());
+#      T_ARRAY
+#              ST_EXTEND($var.size);
+#              for (U32 ix_$var = 0; ix_$var < $var.size; ix_$var++) {
+#                      ST(ix_$var) = sv_newmortal();
+#              DO_ARRAY_ELEM
+#              }
+#              sp += $var.size - 1;
+#      T_IN
+#              {
+#                  GV *gv = newGVgen("$Package");
+#                  if ( do_open(gv, "<&", 2, FALSE, 0, 0, $var) )
+#                      sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+#                  else
+#                      $arg = &sv_undef;
+#              }
+#      T_INOUT
+#              {
+#                  GV *gv = newGVgen("$Package");
+#                  if ( do_open(gv, "+<&", 3, FALSE, 0, 0, $var) )
+#                      sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+#                  else
+#                      $arg = &sv_undef;
+#              }
+#      T_OUT
+#              {
+#                  GV *gv = newGVgen("$Package");
+#                  if ( do_open(gv, "+>&", 3, FALSE, 0, 0, $var) )
+#                      sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+#                  else
+#                      $arg = &sv_undef;
+#              }
diff --git a/JPL/AutoLoader.pm b/JPL/AutoLoader.pm
new file mode 100644 (file)
index 0000000..94d9856
--- /dev/null
@@ -0,0 +1,352 @@
+package JPL::AutoLoader;
+
+use strict;
+
+use vars qw(@ISA @EXPORT $AUTOLOAD);
+
+use Exporter;
+@ISA = "Exporter";
+@EXPORT = ("AUTOLOAD", "getmeth");
+
+my %callmethod = (
+    V => 'Void',
+    Z => 'Boolean',
+    B => 'Byte',
+    C => 'Char',
+    S => 'Short',
+    I => 'Int',
+    J => 'Long',
+    F => 'Float',
+    D => 'Double',
+);
+
+# A lookup table to convert the data types that Java
+# developers are used to seeing into the JNI-mangled
+# versions.
+#
+# bjepson 13 August 1997
+#
+my %type_table = (
+    'void'    => 'V',
+    'boolean' => 'Z',
+    'byte'    => 'B',
+    'char'    => 'C',
+    'short'   => 'S',
+    'int'     => 'I',
+    'long'    => 'J',
+    'float'   => 'F',
+    'double'  => 'D'
+);
+
+# A cache for method ids.
+#
+# bjepson 13 August 1997
+#
+my %MID_CACHE;
+
+# A cache for methods.
+#
+# bjepson 13 August 1997
+#
+my %METHOD_CACHE;
+
+use JNI;
+
+# XXX We're assuming for the moment that method ids are persistent...
+
+sub AUTOLOAD {
+
+    print "AUTOLOAD $AUTOLOAD(@_)\n" if $JPL::DEBUG;
+    my ($classname, $methodsig) = $AUTOLOAD =~ /^(.*)::(.*)/;
+    print "class = $classname, method = $methodsig\n" if $JPL::DEBUG;
+
+    if ($methodsig eq "DESTROY") {
+        print "sub $AUTOLOAD {}\n" if $JPL::DEBUG;
+        eval "sub $AUTOLOAD {}";
+        return;
+    }
+
+    (my $jclassname = $classname) =~ s/^JPL:://;
+    $jclassname =~ s{::}{/}g;
+    my $class = JNI::FindClass($jclassname)
+        or die "Can't find Java class $jclassname\n";
+
+    # This method lookup allows the user to pass in
+    # references to two array that contain the input and
+    # output data types of the method.
+    #
+    # bjepson 13 August 1997
+    #
+    my ($methodname, $sig, $retsig, $slow_way);
+    if (ref $_[1] eq 'ARRAY' && ref $_[2] eq 'ARRAY') {
+
+       $slow_way = 1;
+
+        # First we strip out the input and output args.
+       #
+        my ($in,$out) = splice(@_, 1, 2);
+
+        # let's mangle up the input argument types.
+        #
+        my @in  = jni_mangle($in);
+
+        # if they didn't hand us any output values types, make
+        # them void by default.
+        #
+        unless (@{ $out }) {
+            $out = ['void'];
+        }
+
+        # mangle the output types
+        #
+        my @out = jni_mangle($out);
+
+        $methodname = $methodsig;
+        $retsig     = join("", @out);
+        $sig        = "(" . join("", @in) . ")" . $retsig;
+
+    } else {
+
+        ($methodname, $sig) = split /__/, $methodsig, 2;
+        $sig ||= "__V";                # default is void return
+
+        # Now demangle the signature.
+
+        $sig =~ s/_3/[/g;
+        $sig =~ s/_2/;/g;
+        my $tmp;
+        $sig =~ s{
+            (s|L[^;]*;)
+        }{
+           $1 eq 's'
+               ? "Ljava/lang/String;"
+               : (($tmp = $1) =~ tr[_][/], $tmp)
+        }egx;
+        if ($sig =~ s/(.*)__(.*)/($1)$2/) {
+            $retsig = $2;
+        }
+        else {                        # void return is assumed
+            $sig = "($sig)V";
+            $retsig = "V";
+        }
+        $sig =~ s/_1/_/g;
+    }
+    print "sig = $sig\n" if $JPL::DEBUG;
+
+    # Now look up the method's ID somehow or other.
+    #
+    $methodname = "<init>" if $methodname eq 'new';
+    my $mid;
+
+    # Added a method id cache to compensate for avoiding
+    # Perl's method cache...
+    #
+    if ($MID_CACHE{qq[$classname:$methodname:$sig]}) {
+
+        $mid = $MID_CACHE{qq[$classname:$methodname:$sig]};
+        print "got method " . ($mid + 0) . " from cache.\n" if $JPL::DEBUG;
+
+    } elsif (ref $_[0] or $methodname eq '<init>') {
+
+        # Look up an instance method or a constructor
+        #
+        $mid = JNI::GetMethodID($class, $methodname, $sig);
+
+    } else {
+
+        # Look up a static method
+        #
+        $mid = JNI::GetStaticMethodID($class, $methodname, $sig);
+
+    }
+
+    # Add this method to the cache.
+    #
+    # bjepson 13 August 1997
+    #
+    $MID_CACHE{qq[$classname:$methodname:$sig]} = $mid if $slow_way;
+
+    if ($mid == 0) {
+
+        JNI::ExceptionClear();
+        # Could do some guessing here on return type...
+        die "Can't get method id for $AUTOLOAD($sig)\n";
+
+    }
+
+    print "mid = ", $mid + 0, ", $mid\n" if $JPL::DEBUG;
+    my $rettype = $callmethod{$retsig} || "Object";
+    print "*** rettype = $rettype\n" if $JPL::DEBUG;
+
+    my $blesspack;
+    no strict 'refs';
+    if ($rettype eq "Object") {
+        $blesspack = $retsig;
+        $blesspack =~ s/^L//;
+        $blesspack =~ s/;$//;
+        $blesspack =~ s#/#::#g;
+        print "*** Some sort of wizardry...\n" if $JPL::DEBUG;
+        print %{$blesspack . "::"}, "\n" if $JPL::DEBUG;
+        print defined %{$blesspack . "::"}, "\n" if $JPL::DEBUG;
+        if (not defined %{$blesspack . "::"}) {
+            #if ($blesspack eq "java::lang::String") {
+            if ($blesspack =~ /java::/) {
+                eval <<"END" . <<'ENDQ';
+package $blesspack;
+END
+use JPL::AutoLoader;
+use overload
+        '""' => sub { JNI::GetStringUTFChars($_[0]) },
+        '0+' => sub { 0 + "$_[0]" },
+        fallback => 1;
+ENDQ
+            }
+            else {
+                eval <<"END";
+package $blesspack;
+use JPL::AutoLoader;
+END
+            }
+        }
+    }
+
+    # Finally, call the method.  Er, somehow...
+    #
+    my $METHOD;
+
+    my $real_mid = $mid + 0; # weird overloading that I
+                             # don't understand ?!
+    if (ref ${$METHOD_CACHE{qq[$real_mid]}} eq 'CODE') {
+
+        $METHOD = ${$METHOD_CACHE{qq[$real_mid]}};
+        print qq[Pulled $classname, $methodname, $sig from cache.\n] if $JPL::DEBUG;
+
+    } elsif ($methodname eq "<init>") {
+        $METHOD = sub {
+            my $self = shift;
+           my $class = JNI::FindClass($jclassname);
+            bless $class->JNI::NewObjectA($mid, \@_), $classname;
+        };
+    }
+    elsif (ref $_[0]) {
+        if ($blesspack) {
+            $METHOD = sub {
+                my $self = shift;
+                if (ref $self eq $classname) {
+                    my $callmethod = "JNI::Call${rettype}MethodA";
+                    bless $self->$callmethod($mid, \@_), $blesspack;
+                }
+                else {
+                    my $callmethod = "JNI::CallNonvirtual${rettype}MethodA";
+                    bless $self->$callmethod($class, $mid, \@_), $blesspack;
+                }
+            };
+        }
+        else {
+            $METHOD = sub {
+                my $self = shift;
+                if (ref $self eq $classname) {
+                    my $callmethod = "JNI::Call${rettype}MethodA";
+                    $self->$callmethod($mid, \@_);
+                }
+                else {
+                    my $callmethod = "JNI::CallNonvirtual${rettype}MethodA";
+                    $self->$callmethod($class, $mid, \@_);
+                }
+            };
+        }
+    }
+    else {
+        my $callmethod = "JNI::CallStatic${rettype}MethodA";
+        if ($blesspack) {
+            $METHOD = sub {
+                my $self = shift;
+                bless $class->$callmethod($mid, \@_), $blesspack;
+            };
+        }
+        else {
+            $METHOD = sub {
+                my $self = shift;
+                $class->$callmethod($mid, \@_);
+            };
+        }
+    }
+    if ($slow_way) {
+       $METHOD_CACHE{qq[$real_mid]} = \$METHOD;
+       &$METHOD;
+    }
+    else {
+       *$AUTOLOAD = $METHOD;
+       goto &$AUTOLOAD;
+    }
+}
+
+sub jni_mangle {
+
+    my $arr = shift;
+    my @ret;
+
+    foreach my $arg (@{ $arr }) {
+
+        my $ret;
+
+        # Count the dangling []s.
+        #
+       $ret = '[' x $arg =~ s/\[\]//g;
+
+        # Is it a primitive type?
+        #
+        if ($type_table{$arg}) {
+            $ret .= $type_table{$arg};
+        } else {
+            # some sort of class
+            #
+            $arg =~ s#\.#/#g;
+            $ret .= "L$arg;";
+        }
+        push @ret, $ret;
+
+    }
+
+    return @ret;
+
+}
+
+sub getmeth {
+    my ($meth, $in, $out) = @_;
+    my @in  = jni_mangle($in);
+
+    # if they didn't hand us any output values types, make
+    # them void by default.
+    #
+    unless ($out and @$out) {
+       $out = ['void'];
+    }
+
+    # mangle the output types
+    #
+    my @out = jni_mangle($out);
+
+    my $sig        = join("", '#', @in, '#', @out);
+    $sig =~ s/_/_1/g;
+    my $tmp;
+    $sig =~ s{
+       (L[^;]*;)
+    }{
+       ($tmp = $1) =~ tr[/][_], $tmp
+    }egx;
+    $sig =~ s{Ljava/lang/String;}{s}g;
+    $sig =~ s/;/_2/g;
+    $sig =~ s/\[/_3/g;
+    $sig =~ s/#/__/g;
+    $meth . $sig;
+}
+
+{
+    package java::lang::String;
+    use overload
+       '""' => sub { JNI::GetStringUTFChars($_[0]) },
+       '0+' => sub { 0 + "$_[0]" },
+       fallback => 1;
+}
+1;
diff --git a/JPL/Class.pm b/JPL/Class.pm
new file mode 100644 (file)
index 0000000..1bc9768
--- /dev/null
@@ -0,0 +1,13 @@
+package JPL::Class;
+use JPL::AutoLoader ();
+
+sub DESTROY {}
+
+sub import {
+    my $class = shift;
+    foreach $class (@_) {
+       *{$class . "::AUTOLOAD"} = *JPL::AutoLoader::AUTOLOAD;
+       *{$class . "::DESTROY"} = \&DESTROY;
+    }
+}
+1;
diff --git a/JPL/Compile.pm b/JPL/Compile.pm
new file mode 100755 (executable)
index 0000000..39dd6b8
--- /dev/null
@@ -0,0 +1,772 @@
+#!/usr/bin/perl -w
+
+# Copyright 1997, O'Reilly & Associate, Inc.
+#
+# This package may be copied under the same terms as Perl itself.
+
+package JPL::Compile;
+use Exporter ();
+@ISA = qw(Exporter);
+@EXPORT = qw(files file);
+
+use strict;
+
+
+warn "You don't have a recent JDK kit your PATH, so this may fail.\n"
+    unless $ENV{PATH} =~ /(java|jdk1.[1-9])/;
+
+sub emit;
+
+my $PERL = "";
+my $LASTCLASS = "";
+my $PERLLINE = 0;
+my $PROTO;
+
+my @protos;
+
+my $plfile;
+my $jpfile;
+my $hfile;
+my $h_file;
+my $cfile;
+my $jfile;
+my $classfile;
+
+my $DEBUG = $ENV{JPLDEBUG};
+
+my %ptype = qw(
+       Z boolean
+       B byte
+       C char
+       S short
+       I int
+       J long
+       F float
+       D double
+);
+
+$ENV{CLASSPATH} =~ s/^/.:/ unless $ENV{CLASSPATH} =~ /^\.(?::|$)/;
+
+unless (caller) {
+    files(@ARGV);
+}
+
+#######################################################################
+
+sub files {
+    foreach my $jpfile (@_) {
+       file($jpfile);
+    }
+    print "make\n";
+    system "make";
+}
+
+sub file {
+    my $jpfile = shift;
+    my $JAVA = "";
+    my $lastpos = 0;
+    my $linenum = 2;
+    my %classseen;
+    my %fieldsig;
+    my %staticfield;
+
+    (my $file = $jpfile) =~ s/\.jpl$//;
+    $jpfile = "$file.jpl";
+    $jfile = "$file.java";
+    $hfile = "$file.h";
+    $cfile = "$file.c";
+    $plfile = "$file.pl";
+    $classfile = "$file.class";
+
+    ($h_file = $hfile) =~ s/_/_0005f/g;
+
+    emit_c_header();
+
+    # Extract out arg names from .java file, since .class doesn't have 'em.
+
+    open(JPFILE, $jpfile) or die "Can't open $jpfile: $!\n";
+    undef $/;
+    $_ = <JPFILE>;
+    close JPFILE;
+
+    die "$jpfile doesn't seem to define class $file!\n"
+       unless /class\s+\b$file\b[\w\s.,]*{/;
+
+    @protos = ();
+    open(JFILE, ">$jfile") or die "Can't create $jfile: $!\n";
+
+    while (m/\bperl\b([^\n]*?\b(\w+)\s*\(\s*(.*?)\s*\)[\s\w.,]*)\{\{(.*?)\}\}/sg) {
+       $JAVA = substr($`, $lastpos);
+       $lastpos = pos $_;
+       $JAVA .= "native";
+       $JAVA .= $1;
+
+       my $method = $2;
+
+       my $proto = $3;
+
+       my $perl = $4;
+       (my $repl = $4) =~ tr/\n//cd;
+       $JAVA .= ';';
+       $linenum += $JAVA =~ tr/\n/\n/;
+       $JAVA .= $repl;
+       print JFILE $JAVA;
+
+       $proto =~ s/\s+/ /g;
+       $perl =~ s/^[ \t]+\Z//m;
+       $perl =~ s/^[ \t]*\n//;
+       push(@protos, [$method, $proto, $perl, $linenum]);
+
+       $linenum += $repl =~ tr/\n/\n/;
+    }
+
+    print JFILE <<"END";
+    static {
+       System.loadLibrary("$file");
+        PerlInterpreter pi = new PerlInterpreter().fetch();
+        // pi.eval("\$JPL::DEBUG = \$ENV{JPLDEBUG};");
+       pi.eval("warn qq{loading $file\\n} if \$JPL::DEBUG");
+       pi.eval("eval {require '$plfile'}; print \$@ if \$@;");
+    }
+END
+
+    print JFILE substr($_, $lastpos);
+
+    close JFILE;
+
+    # Produce the corresponding .h file.  Should really use make...
+
+    if (not -s $hfile or -M $hfile > -M $jfile) {
+       if (not -s $classfile or -M $classfile > -M $jfile) {
+           unlink $classfile;
+           print  "javac $jfile\n";
+           system "javac $jfile" and die "Couldn't run javac: exit $?\n";
+           if (not -s $classfile or -M $classfile > -M $jfile) {
+               die "Couldn't produce $classfile from $jfile!";
+           }
+       }
+       unlink $hfile;
+       print  "javah -jni $file\n";
+       system "javah -jni $file" and die "Couldn't run javah: exit $?\n";
+       if (not -s $hfile and -s $h_file) {
+           rename $h_file, $hfile;
+       }
+       if (not -s $hfile or -M $hfile > -M $jfile) {
+           die "Couldn't produce $hfile from $classfile!";
+       }
+    }
+
+    # Easiest place to get fields is from javap.
+
+    print  "javap -s $file\n";
+    open(JP, "javap -s $file|");
+    $/ = "\n";
+    while (<JP>) {
+       if (/^\s+([A-Za-z_].*) (\w+)[\[\d\]]*;/) {
+           my $jtype = $1;
+           my $name = $2;
+           $_ = <JP>;
+           s!^\s*/\*\s*!!;
+           s!\s*\*/\s*!!;
+           print "Field $jtype $name $_\n" if $DEBUG;
+           $fieldsig{$name} = $_;
+           $staticfield{$name} = $jtype =~ /\bstatic\b/;
+       }
+       while (m/L([^;]*);/g) {
+           my $pclass = j2p_class($1);
+           $classseen{$pclass}++;
+       }
+    }
+    close JP;
+
+    open(HFILE, $hfile) or die "Couldn't open $hfile: $!\n";
+    undef $/;
+    $_ = <HFILE>;
+    close HFILE;
+
+    die "panic: native method mismatch" if @protos != s/^JNIEXPORT/JNIEXPORT/gm;
+
+    $PROTO = 0;
+    while (m{
+       \*\s*Class:\s*(\w+)\s*
+       \*\s*Method:\s*(\w+)\s*
+       \*\s*Signature:\s*(\S+)\s*\*/\s*
+       JNIEXPORT\s*(.*?)\s*JNICALL\s*(\w+)\s*\((.*?)\)
+    }gx) {
+       my $class = $1;
+       my $method = $2;
+       my $signature = $3;
+       my $rettype = $4;
+       my $cname = $5;
+       my $ctypes = $6;
+       $class =~ s/_0005f/_/g;
+       if ($method ne $protos[$PROTO][0]) {
+           die "Method name mismatch: $method vs $protos[$PROTO][0]\n";
+       }
+       print "$class.$method($protos[$PROTO][1]) =>
+       $signature
+       $rettype $cname($ctypes)\n" if $DEBUG;
+
+       # Insert argument names into parameter list.
+
+       my $env = "env";
+       my $obj = "obj";
+       my @jargs = split(/\s*,\s*/, $protos[$PROTO][1]);
+       foreach my $arg (@jargs) {
+           $arg =~ s/^.*\b(\w+).*$/${1}/;
+       }
+       my @tmpargs = @jargs;
+       unshift(@tmpargs, $env, $obj);
+       print "\t@tmpargs\n" if $DEBUG;
+       $ctypes .= ",";
+       $ctypes =~ s/,/' ' . shift(@tmpargs) . '_,'/eg;
+       $ctypes =~ s/,$//;
+       $ctypes =~ s/env_/env/;
+       $ctypes =~ s/obj_/obj/;
+       print "\t$ctypes\n" if $DEBUG;
+
+       my $jlen = @jargs + 1;
+
+       (my $mangclass = $class) =~ s/_/_1/g;
+       (my $mangmethod = $method) =~ s/_/_1/g;
+       my $plname = $cname;
+       $plname =~ s/^Java_${mangclass}_${mangmethod}/JPL::${class}::${method}/;
+       $plname =~ s/Ljava_lang_String_2/s/g;
+
+       # Make glue code for each argument.
+
+       (my $sig = $signature) =~ s/^\(//;
+
+       my $decls = "";
+       my $glue = "";
+
+       foreach my $jarg (@jargs) {
+           if ($sig =~ s/^[ZBCSI]//) {
+               $glue .= <<"";
+!    /* $jarg */
+!    PUSHs(sv_2mortal(newSViv(${jarg}_)));
+!
+
+           }
+           elsif ($sig =~ s/^[JFD]//) {
+               $glue .= <<"";
+!    /* $jarg */
+!    PUSHs(sv_2mortal(newSVnv(${jarg}_)));
+!
+
+           }
+           elsif ($sig =~ s#^Ljava/lang/String;##) {
+               $glue .= <<"";
+!    /* $jarg */
+!    tmpjb = (jbyte*)(*env)->GetStringUTFChars(env,${jarg}_,0);
+!    PUSHs(sv_2mortal(newSVpv((char*)tmpjb,0)));
+!    (*env)->ReleaseStringUTFChars(env,${jarg}_,tmpjb);
+!
+
+           }
+           elsif ($sig =~ s/^L([^;]*);//) {
+               my $pclass = j2p_class($1);
+               $classseen{$pclass}++;
+               $glue .= <<"";
+!    /* $jarg */
+!    if (!${jarg}_stashhv_)
+!      ${jarg}_stashhv_ = gv_stashpv("$pclass", TRUE);
+! 
+!    PUSHs(sv_bless(
+!      sv_setref_iv(sv_newmortal(), Nullch, (IV)(void*)${jarg}_),
+!      ${jarg}_stashhv_));
+!    if (jpldebug)
+!      fprintf(stderr, "Done with $jarg\\n");
+!
+
+               $decls .= <<"";
+!    static HV* ${jarg}_stashhv_ = 0;
+
+
+           }
+           elsif ($sig =~ s/^\[+([ZBCSIJFD]|L[^;]*;)//) {
+               my $pclass = "jarray";
+               $classseen{$pclass}++;
+               $glue .= <<"";
+!    /* $jarg */
+!    if (!${jarg}_stashhv_)
+!      ${jarg}_stashhv_ = gv_stashpv("$pclass", TRUE);
+! 
+!    PUSHs(sv_bless(
+!      sv_setref_iv(sv_newmortal(), Nullch, (IV)(void*)${jarg}_),
+!      ${jarg}_stashhv_));
+!    if (jpldebug)
+!      fprintf(stderr, "Done with $jarg\\n");
+!
+
+               $decls .= <<"";
+!    static HV* ${jarg}_stashhv_ = 0;
+
+           }
+           else {
+               die "Short signature: $signature\n" if $sig eq "";
+               die "Unrecognized letter '" . substr($sig, 0, 1) . "' in signature $signature\n";
+           }
+       }
+
+       $sig =~ s/^\)// or die "Argument mismatch in signature: $method$signature\n";
+
+       my $void = $signature =~ /\)V$/;
+
+       $decls .= <<"" if $signature =~ m#java/lang/String#;
+!    jbyte* tmpjb;
+
+       $decls .= <<"" unless $void;
+!    SV* retsv;
+!    $rettype retval;
+!
+!    if (jpldebug)
+!      fprintf(stderr, "Got to $cname\\n");
+!    ENTER;
+!    SAVETMPS;
+
+       emit <<"";
+!JNIEXPORT $rettype JNICALL
+!$cname($ctypes)
+!{
+!    static SV* methodsv = 0;
+!    static HV* stashhv = 0;
+!    dSP;
+$decls
+!    PUSHMARK(sp);
+!    EXTEND(sp,$jlen);
+!
+!    sv_setiv(perl_get_sv("JPL::_env_", 1), (IV)(void*)env);
+!    jplcurenv = env;
+!
+!    if (jpldebug)
+!      fprintf(stderr, "env = %lx\\n", (long)$env);
+!
+!    if (!methodsv)
+!      methodsv = (SV*)perl_get_cv("$plname", TRUE);
+!    if (!stashhv)
+!      stashhv = gv_stashpv("JPL::$class", TRUE);
+! 
+!    if (jpldebug)
+!      fprintf(stderr, "blessing obj = %lx\\n", obj);
+!    PUSHs(sv_bless(
+!      sv_setref_iv(sv_newmortal(), Nullch, (IV)(void*)obj),
+!      stashhv));
+!
+$glue
+
+       # Finally, call the subroutine.
+
+       my $mod;
+       $mod = "|G_DISCARD" if $void;
+
+       if ($void) {
+           emit <<"";
+!    PUTBACK;
+!    perl_call_sv(methodsv, G_EVAL|G_KEEPERR|G_DISCARD);
+!
+
+       }
+       else {
+           emit <<"";
+!    PUTBACK;
+!    if (perl_call_sv(methodsv, G_EVAL|G_KEEPERR))
+!      retsv = *stack_sp--;
+!    else
+!      retsv = &sv_undef;
+!
+
+       }
+
+       emit <<"";
+!    if (SvTRUE(GvSV(errgv))) {
+!      jthrowable newExcCls;
+!
+!      (*env)->ExceptionDescribe(env);
+!      (*env)->ExceptionClear(env);
+!
+!      newExcCls = (*env)->FindClass(env, "java/lang/RuntimeException");
+!      if (newExcCls)
+!          (*env)->ThrowNew(env, newExcCls, SvPV(GvSV(errgv),na));
+!    }
+!
+
+       # Fix up the return value, if any.
+
+       if ($sig =~ s/^V//) {
+           emit <<"";
+!    return;
+
+       }
+       elsif ($sig =~ s/^[ZBCSI]//) {
+           emit <<"";
+!    retval = ($rettype)SvIV(retsv);
+!    FREETMPS;
+!    LEAVE;
+!    return retval;
+
+       }
+       elsif ($sig =~ s/^[JFD]//) {
+           emit <<"";
+!    retval = ($rettype)SvNV(retsv);
+!    FREETMPS;
+!    LEAVE;
+!    return retval;
+
+       }
+       elsif ($sig =~ s#^Ljava/lang/String;##) {
+           emit <<"";
+!    retval = (*env)->NewStringUTF(env, SvPV(retsv,na));
+!    FREETMPS;
+!    LEAVE;
+!    return retval;
+
+       }
+       elsif ($sig =~ s/^L[^;]*;//) {
+           emit <<"";
+!    if (SvROK(retsv)) {
+!      SV* rv = (SV*)SvRV(retsv);
+!      if (SvOBJECT(rv))
+!          retval = ($rettype)(void*)SvIV(rv);
+!      else
+!          retval = ($rettype)(void*)0;
+!    }
+!    else
+!      retval = ($rettype)(void*)0;
+!    FREETMPS;
+!    LEAVE;
+!    return retval;
+
+       }
+       elsif ($sig =~ s/^\[([ZBCSIJFD])//) {
+           my $elemtype = $1;
+           my $ptype = "\u$ptype{$elemtype}";
+           my $ntype = "j$ptype{$elemtype}";
+           my $in = $elemtype =~ /^[JFD]/ ? "N" : "I";
+           emit <<"";
+!    if (SvROK(retsv)) {
+!      SV* rv = (SV*)SvRV(retsv);
+!      if (SvOBJECT(rv))
+!          retval = ($rettype)(void*)SvIV(rv);
+!      else if (SvTYPE(rv) == SVt_PVAV) {
+!          jsize len = av_len((AV*)rv) + 1;
+!          $ntype* buf = ($ntype*)malloc(len * sizeof($ntype));
+!          int i;
+!          SV** esv;
+!
+!          ${ntype}Array ja = (*env)->New${ptype}Array(env, len);
+!          for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++)
+!              buf[i] = ($ntype)Sv${in}V(*esv);
+!          (*env)->Set${ptype}ArrayRegion(env, ja, 0, len, buf);
+!          free((void*)buf);
+!          retval = ($rettype)ja;
+!      }
+!      else
+!          retval = ($rettype)(void*)0;
+!    }
+!    else if (SvPOK(retsv)) {
+!      jsize len = sv_len(retsv) / sizeof($ntype);
+!
+!      ${ntype}Array ja = (*env)->New${ptype}Array(env, len);
+!      (*env)->Set${ptype}ArrayRegion(env, ja, 0, len, ($ntype*)SvPV(retsv,na));
+!      retval = ($rettype)ja;
+!    }
+!    else
+!      retval = ($rettype)(void*)0;
+!    FREETMPS;
+!    LEAVE;
+!    return retval;
+
+       }
+       elsif ($sig =~ s!^\[Ljava/lang/String;!!) {
+           emit <<"";
+!    if (SvROK(retsv)) {
+!      SV* rv = (SV*)SvRV(retsv);
+!      if (SvOBJECT(rv))
+!          retval = ($rettype)(void*)SvIV(rv);
+!      else if (SvTYPE(rv) == SVt_PVAV) {
+!          jsize len = av_len((AV*)rv) + 1;
+!          int i;
+!          SV** esv;
+!           static jclass jcl = 0;
+!          jarray ja;
+!
+!          if (!jcl)
+!              jcl = (*env)->FindClass(env, "java/lang/String");
+!          ja = (*env)->NewObjectArray(env, len, jcl, 0);
+!          for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) {
+!              jobject str = (jobject)(*env)->NewStringUTF(env, SvPV(*esv,na));
+!              (*env)->SetObjectArrayElement(env, ja, i, str);
+!          }
+!          retval = ($rettype)ja;
+!      }
+!      else
+!          retval = ($rettype)(void*)0;
+!    }
+!    else
+!      retval = ($rettype)(void*)0;
+!    FREETMPS;
+!    LEAVE;
+!    return retval;
+
+       }
+       elsif ($sig =~ s/^(\[+)([ZBCSIJFD]|L[^;]*;)//) {
+           my $arity = length $1;
+           my $elemtype = $2;
+           emit <<"";
+!    if (SvROK(retsv)) {
+!      SV* rv = (SV*)SvRV(retsv);
+!      if (SvOBJECT(rv))
+!          retval = ($rettype)(void*)SvIV(rv);
+!      else if (SvTYPE(rv) == SVt_PVAV) {
+!          jsize len = av_len((AV*)rv) + 1;
+!          int i;
+!          SV** esv;
+!           static jclass jcl = 0;
+!          jarray ja;
+!
+!          if (!jcl)
+!              jcl = (*env)->FindClass(env, "java/lang/Object");
+!          ja = (*env)->NewObjectArray(env, len, jcl, 0);
+!          for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) {
+!              if (SvROK(*esv) && (rv = SvRV(*esv)) && SvOBJECT(rv)) {
+!                  (*env)->SetObjectArrayElement(env, ja, i,
+!                      (jobject)(void*)SvIV(rv));
+!              }
+!              else {
+!                  jobject str = (jobject)(*env)->NewStringUTF(env,
+!                      SvPV(*esv,na));
+!                  (*env)->SetObjectArrayElement(env, ja, i, str);
+!              }
+!          }
+!          retval = ($rettype)ja;
+!      }
+!      else
+!          retval = ($rettype)(void*)0;
+!    }
+!    else
+!      retval = ($rettype)(void*)0;
+!    FREETMPS;
+!    LEAVE;
+!    return retval;
+
+       }
+       else {
+           die "No return type: $signature\n" if $sig eq "";
+           die "Unrecognized return type '" . substr($sig, 0, 1) . "' in signature $signature\n";
+       }
+
+       emit <<"";
+!}
+!
+
+       my $perl = "";
+
+       if ($class ne $LASTCLASS) {
+           $LASTCLASS = $class;
+           $perl .= <<"";
+package JPL::${class};
+use JNI;
+use JPL::AutoLoader;
+\@ISA = qw(jobject);
+\$clazz = JNI::FindClass("$file");\n
+
+           foreach my $field (sort keys %fieldsig) {
+               my $sig = $fieldsig{$field};
+               my $ptype = $ptype{$sig};
+               if ($ptype) {
+                   $ptype = "\u$ptype";
+                   if ($staticfield{$field}) {
+                       $perl .= <<"";
+\$${field}_FieldID = JNI::GetStaticFieldID(\$clazz, "$field", "$sig");
+sub $field (\$;\$) {
+    my \$self = shift;
+    if (\@_) {
+       JNI::SetStatic${ptype}Field(\$clazz, \$${field}_FieldID, \$_[0]);
+    }
+    else {
+       JNI::GetStatic${ptype}Field(\$clazz, \$${field}_FieldID);
+    }
+}\n
+
+                   }
+                   else {
+                       $perl .= <<"";
+\$${field}_FieldID = JNI::GetFieldID(\$clazz, "$field", "$sig");
+sub $field (\$;\$) {
+    my \$self = shift;
+    if (\@_) {
+       JNI::Set${ptype}Field(\$self, \$${field}_FieldID, \$_[0]);
+    }
+    else {
+       JNI::Get${ptype}Field(\$self, \$${field}_FieldID);
+    }
+}\n
+
+                   }
+               }
+               else {
+                   my $pltype = $sig;
+                   if ($pltype =~ s/^L(.*);/$1/) {
+                       $pltype =~ s!/!::!g;
+                   }
+                   else {
+                       $pltype = 'jarray';
+                   }
+                   if ($pltype eq "java::lang::String") {
+                       if ($staticfield{$field}) {
+                           $perl .= <<"";
+\$${field}_FieldID = JNI::GetStaticFieldID(\$clazz, "$field", "$sig");
+sub $field (\$;\$) {
+    my \$self = shift;
+    if (\@_) {
+       JNI::SetStaticObjectField(\$clazz, \$${field}_FieldID,
+           ref \$_[0] ? \$_[0] : JNI::NewStringUTF(\$_[0]));
+    }
+    else {
+       JNI::GetStringUTFChars(JNI::GetStaticObjectField(\$clazz, \$${field}_FieldID));
+    }
+}\n
+
+                       }
+                       else {
+                           $perl .= <<"";
+\$${field}_FieldID = JNI::GetFieldID(\$clazz, "$field", "$sig");
+sub $field (\$;\$) {
+    my \$self = shift;
+    if (\@_) {
+       JNI::SetObjectField(\$self, \$${field}_FieldID,
+           ref \$_[0] ? \$_[0] : JNI::NewStringUTF(\$_[0]));
+    }
+    else {
+       JNI::GetStringUTFChars(JNI::GetObjectField(\$self, \$${field}_FieldID));
+    }
+}\n
+
+                       }
+                   }
+                   else {
+                       if ($staticfield{$field}) {
+                           $perl .= <<"";
+\$${field}_FieldID = JNI::GetStaticFieldID(\$clazz, "$field", "$sig");
+sub $field (\$;\$) {
+    my \$self = shift;
+    if (\@_) {
+       JNI::SetStaticObjectField(\$clazz, \$${field}_FieldID, \$_[0]);
+    }
+    else {
+       bless JNI::GetStaticObjectField(\$clazz, \$${field}_FieldID), "$pltype";
+    }
+}\n
+
+                       }
+                       else {
+                           $perl .= <<"";
+\$${field}_FieldID = JNI::GetFieldID(\$clazz, "$field", "$sig");
+sub $field (\$;\$) {
+    my \$self = shift;
+    if (\@_) {
+       JNI::SetObjectField(\$self, \$${field}_FieldID, \$_[0]);
+    }
+    else {
+       bless JNI::GetObjectField(\$self, \$${field}_FieldID), "$pltype";
+    }
+}\n
+
+                       }
+                   }
+               }
+           }
+       }
+
+       $plname =~ s/^JPL::${class}:://;
+
+       my $proto = '$' x (@jargs + 1);
+       $perl .= "sub $plname ($proto) {\n";
+       $perl .= '    my ($self, ';
+       foreach my $jarg (@jargs) {
+           $perl .= "\$$jarg, ";
+       }
+       $perl =~ s/, $/) = \@_;\n/;
+       $perl .= <<"END";
+       warn "JPL::${class}::$plname(\@_)\\n" if \$JPL::DEBUG;
+#line $protos[$PROTO][3] "$jpfile"
+$protos[$PROTO][2]}
+
+END
+
+       $PERLLINE += $perl =~ tr/\n/\n/ + 2;
+       $perl .= <<"END";
+#line $PERLLINE ""
+END
+       $PERLLINE--;
+
+       $PERL .= $perl;
+    }
+    continue {
+       $PROTO++;
+       print "\n" if $DEBUG;
+    }
+
+    emit_c_footer();
+
+    rename $cfile, "$cfile.old";
+    rename "$cfile.new", $cfile;
+
+    open(PLFILE, ">$plfile") or die "Can't create $plfile: $!\n";
+    print PLFILE "BEGIN { \$JPL::_env_ ||= 1; }        # suppress bogus embedding\n\n";
+    if (%classseen) {
+       my @classes = sort keys %classseen;
+       print PLFILE "use JPL::Class qw(@classes);\n\n";
+    }
+    print PLFILE $PERL;
+    print PLFILE "1;\n";
+    close PLFILE;
+
+    print "perl -c $plfile\n";
+    system "perl -c $plfile" and die "jpl stopped\n";
+}
+
+sub emit_c_header {
+    open(CFILE, ">$cfile.new") or die "Can't create $cfile.new: $!\n";
+    emit <<"";
+!/* This file is automatically generated.  Do not modify! */
+!
+!#include "$hfile"
+! 
+!#ifdef __cplusplus
+!extern "C" {
+!#endif
+! 
+!#include "EXTERN.h"
+!#include "perl.h"
+! 
+!#ifdef __cplusplus
+!}
+!#  define EXTERN_C extern "C"
+!#else
+!#  define EXTERN_C extern
+!#endif
+!
+!extern int jpldebug;
+!extern JNIEnv* jplcurenv;
+!
+
+}
+
+
+sub emit_c_footer {
+    close CFILE;
+}
+
+sub emit {
+    my $string = shift;
+    $string =~ s/^!//mg;
+    print CFILE $string;
+}
+
+sub j2p_class {
+    my $jclass = shift;
+    $jclass =~ s#/#::#g;
+    $jclass;
+}
diff --git a/JPL/Makefile.PL b/JPL/Makefile.PL
new file mode 100644 (file)
index 0000000..efb606d
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+
+$JPL_SRC = "..";
+
+use Config;
+
+eval `$JPL_SRC/setvars -perl`;
+
+open(MAKEFILE, ">Makefile");
+
+print MAKEFILE <<"SUBS";
+PERL = perl$]
+ARCHNAME = $Config{archname}
+JAVA_HOME = $ENV{JAVA_HOME}
+JPL_HOME = $ENV{JPL_HOME}
+PERLARCHDIR = $Config{archlib}
+
+SUBS
+
+print MAKEFILE <<'NOSUBS';
+
+all:
+
+debug:
+
+test:
+
+install:
+       mkdir -p $(JPL_HOME)/perl/JPL
+       cp *.p[ml] $(JPL_HOME)/perl/JPL
+
+clean:
+
+NOSUBS
+
+close MAKEFILE;
diff --git a/JPL_Rolo/JPL_Rolo.jpl b/JPL_Rolo/JPL_Rolo.jpl
new file mode 100755 (executable)
index 0000000..3c77fb2
--- /dev/null
@@ -0,0 +1,553 @@
+import java.awt.*;
+import java.awt.event.*;
+import java.lang.*;
+import java.util.*;
+
+public class JPL_Rolo extends Frame {
+
+    // The primary key of the row that is current onscreen.
+    //
+    int current_row = 0;
+
+    // TextField objects for each column.
+    //
+    TextField fld_name, fld_address, fld_city, fld_state, fld_zip, fld_id;
+
+    // Add or Edit mode.
+    //
+    String edit_status; 
+
+    // a layout manager for the Frame
+    //
+    GridBagLayout gb = new GridBagLayout();
+
+    // Action buttons.
+    //
+    Button next, previous, quit, save, newrow, edit, cancel, delete;
+
+    // A Panel for the action buttons.
+    //
+    Panel actionbuttons;
+
+    /**
+     * Construct a new instance of JPL_Rolo.
+     */
+    public JPL_Rolo(String[] argv) {
+        CreateForm();
+        addWindowListener(new WinEventHandler() );
+    }
+
+    public void CreateForm() {
+
+        // set the layout for the frame
+        //
+        this.setLayout(gb);
+
+        // this is the offset within the GridBagLayout. If
+        // I want the next object on a different line, I 
+        // postincrement. If not, I don't.
+        //
+        int i = 0;
+
+        // Add a text field for the name.
+        // 
+        AddToFrame(new Label("Name:"), 0, i);
+        fld_name = new TextField(20);
+        fld_name.setEditable(false);
+        AddToFrame(fld_name, 1, i++);
+
+        // The address.
+        //
+        AddToFrame(new Label("Address:"), 0, i);
+        fld_address = new TextField(35);
+        fld_address.setEditable(false);
+        AddToFrame(fld_address, 1, i++);
+
+        // The City. I'm not going to increment i, so the
+        // next field will show up on the same line.
+        //
+        AddToFrame(new Label("City:"), 0, i);
+        fld_city = new TextField(20);
+        fld_city.setEditable(false);
+        AddToFrame(fld_city, 1, i);
+
+        // The State.
+        //
+        AddToFrame(new Label("State:"), 2, i);
+        fld_state = new TextField(2);
+        fld_state.setEditable(false);
+        AddToFrame(fld_state, 3, i++);
+
+        // The Zip Code.
+        //
+        AddToFrame(new Label("Zip:"), 0, i);
+        fld_zip = new TextField(11);
+        fld_zip.setEditable(false);
+        AddToFrame(fld_zip, 1, i++);
+
+        // The id - this is always read-only.
+        //
+        AddToFrame(new Label("Id:"), 0, i);
+        fld_id = new TextField(4);
+        fld_id.setEditable(false);
+        AddToFrame(fld_id, 1, i++);
+
+        // create the button panel and give it a FlowLayout
+        //
+        actionbuttons = new Panel();
+        actionbuttons.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
+    
+        // Add the button panel to the Frame. The AddToFrame
+        // method isn't really set up to handle this sort of
+        // panel, so we will go through the tedious process
+        // of managing the GridBagConstraints...
+        //
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = 3; c.gridheight = 1;
+        c.fill = GridBagConstraints.NONE;
+        c.anchor = GridBagConstraints.CENTER;
+        c.weightx = 0.0; c.weighty = 0.0;   
+        c.gridx = 0; c.gridy = i;
+        ((GridBagLayout)this.getLayout()).setConstraints(actionbuttons, c);   
+        this.add(actionbuttons);
+
+        // instantiate and add each of the buttons
+        //
+        previous = new Button("Previous");
+        actionbuttons.add(previous);
+        previous.addActionListener( new PrevRowHandler() );
+
+        next = new Button("Next");
+        actionbuttons.add(next);
+        next.addActionListener( new NextRowHandler() );
+
+        quit = new Button("Quit");
+        actionbuttons.add(quit);
+        quit.addActionListener( new QuitHandler() );
+
+        newrow = new Button("New");
+        actionbuttons.add(newrow);
+        newrow.addActionListener( new NewRowHandler() );
+
+        edit = new Button("Edit");
+        actionbuttons.add(edit);
+        edit.addActionListener( new EditRowHandler() );
+
+        delete = new Button("Delete");
+        actionbuttons.add(delete);
+        delete.addActionListener( new DeleteRowHandler() );
+
+        // save and cancel are disabled until the user
+        // is adding or editing.
+        //
+        save = new Button("Save");
+        actionbuttons.add(save);
+        save.setEnabled(false);
+        save.addActionListener( new SaveHandler() );
+
+        cancel = new Button("Cancel");
+        actionbuttons.add(cancel);
+        cancel.setEnabled(false);
+        cancel.addActionListener( new CancelHandler() );
+
+        // Invoke getRow() to display the first row in the table.
+        //
+        getRow(0);
+
+    }
+
+    /**
+     * Return the id of the current row.
+     */
+    public int getCurrentRowVal() {
+        return current_row;
+    }
+
+    public void setCols(String name, String address, String city, String state, String zip, String id) {
+
+        clearForm();
+
+        fld_name.setText(name);
+        fld_address.setText(address);
+        fld_city.setText(city);
+        fld_state.setText(state);
+        fld_zip.setText(zip);
+        fld_id.setText(id);
+        current_row = Integer.parseInt(id);
+          
+    }
+
+
+    public void setCurrentRow(int r) {
+        current_row = r;
+    }
+
+    public String getName()    { return fld_name.getText(); }
+    public String getAddress() { return fld_address.getText(); }
+    public String getCity()    { return fld_city.getText(); }
+    public String getState()   { return fld_state.getText(); }
+    public String getZip()     { return fld_zip.getText(); }
+    public String getId()      { return fld_id.getText(); }
+
+    /**
+     * This eventhandler will move to the previous row.
+     */
+    class PrevRowHandler implements ActionListener {
+        public void actionPerformed( ActionEvent e) {
+            getRow(-1);
+        }
+    }
+
+    /**
+     * This eventhandler will move to the next row.
+     */
+    class NextRowHandler implements ActionListener {
+        public void actionPerformed( ActionEvent e) {
+            getRow(1);
+        }
+    }
+
+    /**
+     * This eventhandler will terminate the application.
+     */
+    class QuitHandler implements ActionListener {
+        public void actionPerformed( ActionEvent e) {
+            System.exit(0);
+        }
+    }
+
+    /**
+     * This eventhandler will display a blank record and put
+     * this application in new record mode.
+     */
+    class NewRowHandler implements ActionListener {
+        public void actionPerformed( ActionEvent e) {
+                clearForm();
+                edit_status = "new";
+                setEdit();
+        }
+    }
+
+    /**
+     * This eventhandler will put the application in edit
+     * mode (for the current row).
+     */
+    class EditRowHandler implements ActionListener {
+        public void actionPerformed( ActionEvent e) {
+            edit_status = "edit";
+            setEdit();
+        }
+    }
+    /**
+     * This eventhandler will delete the current row.
+     */
+    class DeleteRowHandler implements ActionListener {
+        public void actionPerformed( ActionEvent e) {
+            delRow();
+        }
+    }
+
+    /**
+     * This eventhandler will save (update or insert) the
+     * current record.
+     */
+    class SaveHandler implements ActionListener {
+        public void actionPerformed( ActionEvent e) {
+
+            if (edit_status.equals("new")) {
+                saveIt();
+            }
+            if (edit_status.equals("edit")) {
+                updateRow();
+            }
+
+            // set the edit_status to "browse", and call setBrowse()
+            //
+            edit_status = "browse";
+            setBrowse();
+        }
+    }
+
+    /**
+     * This eventhandler cancels any pending edit.
+     */
+    class CancelHandler implements ActionListener {
+        public void actionPerformed( ActionEvent e) {
+            // if it was new, make sure that they can't edit the
+            // id field...
+
+            if (edit_status.equals("new")) {
+                fld_id.setEditable(false);
+            } 
+
+            // return the edit_status to browse, call getRow()
+            // to retrieve the row they were looking at
+            // before editing or adding, and call setBrowse()
+            //
+            edit_status = "browse";
+            getRow(0);
+            setBrowse();
+        }
+    }
+
+    // This is the event handler to deal with cases where
+    // the user closes the window with a window control.
+    //  
+    class WinEventHandler extends WindowAdapter {
+        public void windowClosing(WindowEvent e) {
+            System.exit(0);
+        }
+    }       
+
+    /**
+     * clearForm()
+     */
+    protected void clearForm () {
+        fld_name.setText("");
+        fld_address.setText("");
+        fld_city.setText("");
+        fld_state.setText("");
+        fld_zip.setText("");
+        fld_id.setText("");
+    }
+
+    /**
+     * AddToFrame()
+     * A convenience method to wrap the living hell
+     * that is GridBagConstraints()
+     */
+    protected void AddToFrame (Component item, int x, int y) {
+
+        // some sane layout defaults.
+        //
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridwidth = 1; c.gridheight = 1;
+        c.fill = GridBagConstraints.NONE;
+        c.anchor = GridBagConstraints.NORTHWEST;
+        c.weightx = 0.0; c.weighty = 0.0;        
+
+        // set the grid coordinates
+        //
+        c.gridx = x; c.gridy = y;
+
+        // set the constraints, and add the item to the layout
+        //
+
+        ((GridBagLayout)this.getLayout()).setConstraints(item, c);    
+        this.add(item);
+    }
+
+    /**
+     * setEdit()
+     *
+     * prepare the form for editing/adding
+     */
+    protected void setEdit () {
+    
+        // disable all these buttons
+        //
+        next.setEnabled(false);
+        previous.setEnabled(false);
+        newrow.setEnabled(false);
+        edit.setEnabled(false);
+        delete.setEnabled(false);
+
+        // set everything except the id to be editable
+        //
+        fld_name.setEditable(true);
+        fld_address.setEditable(true);
+        fld_city.setEditable(true);
+        fld_state.setEditable(true);
+        fld_zip.setEditable(true);
+
+        // enable these two buttons
+        //
+        save.setEnabled(true);
+        cancel.setEnabled(true);
+    }
+
+    /**
+     * setBrowse()
+     *
+     * prepare the form for viewing
+     *
+     */
+    protected void setBrowse() {
+
+        // enable all these buttons
+        //
+        next.setEnabled(true);
+        previous.setEnabled(true);
+        newrow.setEnabled(true);
+        edit.setEnabled(true);
+        delete.setEnabled(true);
+
+        // disable the fields
+        //
+        fld_name.setEditable(false);
+        fld_address.setEditable(false);
+        fld_city.setEditable(false);
+        fld_state.setEditable(false);
+        fld_zip.setEditable(false);
+        fld_id.setEditable(false);
+   
+        // disable these two buttons
+        //
+        save.setEnabled(false);
+        cancel.setEnabled(false);
+    }
+
+    perl void delRow() {{
+
+        my $id      = $self->getId____s();
+
+        $sql = qq[delete from cardfile ] .
+               qq[where (id = $id)];
+        
+        use Sprite;
+        my $rdb = new Sprite();
+        my @data = $rdb->sql($sql);
+        $rdb->close("cardfile");
+        my $status = shift @data;
+        if (!$status) {
+            print STDERR "Bummer - couldn't execute query!\n";
+            die;
+        }
+        $self->setCurrentRow__I(0);
+        $self->getRow__I(0);
+
+    }}
+
+    perl void updateRow() {{
+
+        my $name    = $self->getName____s();
+        my $address = $self->getAddress____s();
+        my $city    = $self->getCity____s();
+        my $state   = $self->getState____s();
+        my $zip     = $self->getZip____s();
+        my $id      = $self->getId____s();
+
+        $sql = qq[update cardfile ] .
+               qq[set name    = ('$name'), ] .
+               qq[set address = ('$address'), ] .
+               qq[set city    = ('$city'), ] .
+               qq[set state   = ('$state'), ] .
+               qq[set zip     = ('$zip') ] .
+               qq[where (id = $id)];
+        
+        use Sprite;
+        my $rdb = new Sprite();
+        my @data = $rdb->sql($sql);
+        $rdb->close("cardfile");
+        my $status = shift @data;
+        if (!$status) {
+            print STDERR "Bummer - couldn't execute query!\n";
+            die;
+        }
+
+    }}
+
+
+    /**
+     * getRow()
+     *
+     * This method is used to either fetch this current row,
+     * in which case it is given an argument of zero, or it
+     * can be used to move relative to the current row, in
+     * which case it must be given an argument of 1 or -1.
+     *
+     */
+
+
+    perl void getRow(int direction) {{
+
+        use Sprite;
+        my $rdb = new Sprite();
+
+        my $nextid = $self->getCurrentRowVal____I() + $direction;
+        my $op;
+        if ($direction == -1) {
+            $op = "<=";
+        } else {
+            $op = ">=";
+        }
+        my @data = $rdb->sql("select name, address, city, state, zip, id from cardfile where id $op $nextid");
+        $rdb->close("cardfile");
+
+        my $status = shift @data;
+        if (!$status) {
+            print STDERR "Bummer - couldn't execute query!\n";
+            die;
+        }
+
+        my $numrows = scalar(@data);
+
+        if (!$numrows) {
+            print STDERR "End of file reached.\n";
+            return;
+        }
+
+        my $index;
+        if ($direction == -1) {
+            $index = $#data;
+        } else {
+            $index = 0;
+        }
+        my($name, $address, $city, $state, $zip, $id) = split (/\0/, $data[$index], 6);
+        $self->setCols__ssssss($name, $address, $city, $state, $zip, $id);
+
+    }}
+
+    perl void saveIt() {{
+
+        use Sprite;
+        my $rdb = new Sprite();
+
+        my @data = $rdb->sql("select id, name from cardfile");
+
+        my $status = shift @data;
+        if (!$status) {
+            print STDERR "Bummer - couldn't execute query!\n";
+            die;
+        }
+
+        my @ids;
+        foreach $record (@data) {
+            my ($id, $name) = split (/\0/, $record, 2);
+            push @ids, $id;
+        }
+        @ids = sort @ids;
+        my $newid = $ids[$#ids] + 1;
+
+        my $name    = $self->getName____s();
+        my $address = $self->getAddress____s();
+        my $city    = $self->getCity____s();
+        my $state   = $self->getState____s();
+        my $zip     = $self->getZip____s();
+
+        my $sql = "insert into cardfile (name, address, city, state, zip, id) values ('$name', '$address', '$city', '$state', '$zip', $newid)";
+        @data = $rdb->sql($sql);
+        $rdb->close("cardfile");
+
+        $status = shift @data;
+        if (!$status) {
+            print STDERR "Bummer - couldn't execute insert!\n";
+            die;
+        }
+
+        $self->setCurrentRow__I($newid);
+
+    }}
+
+    public static void main(String[] args) {
+
+        // make a new JPL_Rolo, pack() it and show() it.
+        JPL_Rolo cardfile = new JPL_Rolo(args);
+        cardfile.pack();
+        cardfile.show();
+
+    }
+
+}
+
+
diff --git a/JPL_Rolo/Makefile.PL b/JPL_Rolo/Makefile.PL
new file mode 100644 (file)
index 0000000..3dd1f84
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+
+$JPL_HOME = $ENV{JPL_HOME}
+    or die "You have not run setvars to set your environment variables.\n" .
+           "See the JPL README file for more information.\n";
+
+use Config;
+
+eval `$JPL_HOME/setvars -perl`;
+
+chop($WHAT = `pwd`);
+$WHAT =~ s#.*/##;
+
+if ($^O eq 'linux') {
+    $flags = "-Dbool=char";    # avoid builtin bool altogether
+    $libs = "-lc -lm -ldl";
+}
+else {
+    $flags = "";
+    $libs = "-lc -lm -ldl";
+}
+chop($cwd = `pwd`);
+($jpldir = $cwd) =~ s#/[^/]*$##;
+
+open(MAKEFILE, ">Makefile");
+
+print MAKEFILE <<"SUBS";
+CC = $Config{cc}
+WHAT = $WHAT
+PERL = perl$]
+ARCHNAME = $Config{archname}
+JAVA_HOME = $ENV{JAVA_HOME}
+JPL_HOME = $ENV{JPL_HOME}
+PERLARCHDIR = $Config{archlib}
+FLAGS = $Config{cccdlflags} $Config{ccdlflags} $Config{lddlflags} $flags
+INCL  = -I\$(PERLARCHDIR)/CORE \\
+       -I\$(JAVA_HOME)/include \\
+       -I\$(JAVA_HOME)/include/$^O \\
+       -I\$(JAVA_HOME)/include/genunix
+LIBS = $libs
+
+SUBS
+
+print MAKEFILE <<'NOSUBS';
+.SUFFIXES: .jpl .class
+
+.jpl.class:
+       $(PERL) -MJPL::Compile -e "file('$*.jpl')"
+
+all: $(WHAT).class lib$(WHAT).so
+
+debug: $(WHAT)_g.class lib$(WHAT)_g.so
+
+lib$(WHAT).so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so
+       $(CC) $(FLAGS) $(INCL) $(WHAT).c \
+       $(PERLARCHDIR)/CORE/libperl.so \
+       $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so \
+       $(LIBS) \
+       -o lib$(WHAT).so
+
+lib$(WHAT)_g.so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so
+       $(CC) -g $(FLAGS) $(INCL) $(WHAT).c \
+       $(PERLARCHDIR)/CORE/libperl.so \
+       $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so \
+       $(LIBS) \
+       -o lib$(WHAT)_g.so
+
+test:
+
+install: all
+       cp $(WHAT).class        $(JPL_HOME)/lib
+       cp lib$(WHAT).so        $(JPL_HOME)/lib/$(ARCHNAME)
+       cp $(WHAT).pl           $(JPL_HOME)/perl
+
+clean:
+       rm -f $(WHAT).c $(WHAT).h \
+       $(WHAT)*.class $(WHAT)*.pl lib$(WHAT).so $(WHAT)*.java
+
+distclean: clean
+       rm -f Makefile
+
+NOSUBS
+
+close MAKEFILE;
diff --git a/JPL_Rolo/README b/JPL_Rolo/README
new file mode 100644 (file)
index 0000000..6d4b14b
--- /dev/null
@@ -0,0 +1,27 @@
+Welcome to the Sprite sample application for Larry Wall's JPL. This
+application showcases a merging of Java and Perl in which Java is employed
+to generate a user interface, and Perl is used for data access.
+Specifically, Perl is used with Shishir Gundavaram's Sprite module to offer
+permanent storage through SQL manipulation of text files. This application
+is a Rolodex(tm)-style address file, offering the ability to add, edit or
+delete names and addresses. You may also navigate through the address list.
+
+To use this example, you will need to install the Sprite module from CPAN.
+
+To install the sample, you must first have JPL installed and working.
+Please ensure that you have set environment variables as directed in the
+JPL README and that the JPL Sample program works. Once this has been
+accomplished, you can build the files in this directory with the following
+commmands:
+
+    perl Makefile.PL
+    make
+    make install
+
+You can run this by typing:
+
+    java JPL_Rolo
+
+The application should appear with some sample data, and you can mess
+around with it and put all your friends in the address book. Far out!
+
diff --git a/JPL_Rolo/cardfile b/JPL_Rolo/cardfile
new file mode 100755 (executable)
index 0000000..eecc806
--- /dev/null
@@ -0,0 +1,7 @@
+name,address,city,state,zip,id
+Brian Jepson,50 Hudson Street,Providence,RI,02909,100
+Elvis Presley,50 Hudson Street,Providence,RI,02909,101
+AS220,115 Empire Street,Providence,RI,02909,600
+Mr. Jones,100 Loudermilk Drive,Springfield,??,,602
+George Maciunas,Canal Street,New York,NY,????,603
+Emmett Williams,Broome Street,New York,NY,?????,605
diff --git a/PerlInterpreter/Makefile b/PerlInterpreter/Makefile
new file mode 100644 (file)
index 0000000..a615fe1
--- /dev/null
@@ -0,0 +1,43 @@
+WHAT = PerlInterpreter
+JAVA_HOME = /usr/local/java
+JPL_HOME = /usr/local/jpl
+ARCHNAME = sun4-solaris
+PERLARCHDIR = /usr/local/lib/perl5/sun4-solaris/5.00404
+CC = gcc
+FLAGS = -fPIC   -R /usr/local/lib/perl5/sun4-solaris/5.00404/CORE -G -L/usr/local/lib 
+INCL  = -I$(PERLARCHDIR)/CORE \
+       -I$(JAVA_HOME)/include \
+       -I$(JAVA_HOME)/include/solaris \
+       -I$(JAVA_HOME)/include/genunix
+LIBS = -lc -lm -ldl
+
+.SUFFIXES: .java .class
+
+.java.class:
+       javac $*.java
+
+.class.h:
+       javah -jni $*
+
+all: PerlInterpreter.class libPerlInterpreter.so
+
+PerlInterpreter.class: PerlInterpreter.java
+
+PerlInterpreter.h: PerlInterpreter.class
+
+libPerlInterpreter.so: PerlInterpreter.c PerlInterpreter.h
+       $(CC) $(FLAGS) $(INCL) PerlInterpreter.c \
+       $(PERLARCHDIR)/auto/DynaLoader/DynaLoader.a \
+       $(LIBS) \
+       -o libPerlInterpreter.so
+
+test:
+
+install: all
+       mkdir -p $(JPL_HOME)/lib/$(ARCHNAME)
+       cp libPerlInterpreter.so $(JPL_HOME)/lib/$(ARCHNAME)
+       cp $(WHAT).class $(JPL_HOME)/lib
+
+clean:
+       rm -f libPerlInterpreter.so
+       rm -f PerlInterpreter.class
diff --git a/PerlInterpreter/Makefile.PL b/PerlInterpreter/Makefile.PL
new file mode 100644 (file)
index 0000000..76852c6
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+
+$JPL_SRC = "..";
+
+use Config;
+
+eval `$JPL_SRC/setvars -perl`;
+
+if ($^O eq 'linux') {
+    $flags = "-Dbool=char";    # avoid builtin bool altogether
+    $libs = "-lc -lm -ldl";
+}
+else {
+    $flags = "";
+    $libs = "-lc -lm -ldl";
+}
+
+open(MAKEFILE, ">Makefile");
+
+print MAKEFILE <<"SUBS";
+WHAT = PerlInterpreter
+JAVA_HOME = $ENV{JAVA_HOME}
+JPL_HOME = $ENV{JPL_HOME}
+ARCHNAME = $Config{archname}
+PERLARCHDIR = $Config{archlib}
+CC = $Config{cc}
+FLAGS = $Config{cccdlflags} $Config{ccdlflags} $Config{lddlflags} $flags
+INCL  = -I\$(PERLARCHDIR)/CORE \\
+       -I\$(JAVA_HOME)/include \\
+       -I\$(JAVA_HOME)/include/$^O \\
+       -I\$(JAVA_HOME)/include/genunix
+LIBS = $libs
+
+SUBS
+
+
+print MAKEFILE <<'NOSUBS';
+.SUFFIXES: .java .class
+
+.java.class:
+       javac $*.java
+
+.class.h:
+       javah -jni $*
+
+all: PerlInterpreter.class libPerlInterpreter.so
+
+PerlInterpreter.class: PerlInterpreter.java
+
+PerlInterpreter.h: PerlInterpreter.class
+
+libPerlInterpreter.so: PerlInterpreter.c PerlInterpreter.h
+       $(CC) $(FLAGS) $(INCL) PerlInterpreter.c \
+       $(PERLARCHDIR)/auto/DynaLoader/DynaLoader.a \
+       $(LIBS) \
+       -o libPerlInterpreter.so
+
+test:
+
+install: all
+       mkdir -p $(JPL_HOME)/lib/$(ARCHNAME)
+       cp libPerlInterpreter.so $(JPL_HOME)/lib/$(ARCHNAME)
+       cp $(WHAT).class $(JPL_HOME)/lib
+
+clean:
+       rm -f libPerlInterpreter.so
+       rm -f PerlInterpreter.class
+NOSUBS
+
+close MAKEFILE;
diff --git a/PerlInterpreter/PerlInterpreter.c b/PerlInterpreter/PerlInterpreter.c
new file mode 100644 (file)
index 0000000..29a275e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * "The Road goes ever on and on, down from the door where it began."
+ */
+
+#include "PerlInterpreter.h"
+#include <dlfcn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "EXTERN.h"
+#include "perl.h"
+
+#ifdef __cplusplus
+}
+#  define EXTERN_C extern "C"
+#else
+#  define EXTERN_C extern
+#endif
+
+static void xs_init _((void));
+static PerlInterpreter *my_perl;
+
+int jpldebug = 0;
+JNIEnv *jplcurenv;
+
+JNIEXPORT void JNICALL
+Java_PerlInterpreter_init(JNIEnv *env, jobject obj, jstring js)
+{
+    int exitstatus;
+    int argc = 3;
+    SV* envsv;
+    SV* objsv;
+    static char *argv[] = {"perl", "-e", "1", 0};
+
+    if (getenv("JPLDEBUG"))
+       jpldebug = atoi(getenv("JPLDEBUG"));
+
+    if (jpldebug)
+       fprintf(stderr, "init\n");
+
+    if (!dlopen("libperl.so", RTLD_LAZY|RTLD_GLOBAL)) {
+       fprintf(stderr, "%s\n", dlerror());
+       exit(1);
+    }
+
+    if (curinterp)
+       return;
+
+    perl_init_i18nl10n(1);
+
+    if (!do_undump) {
+       my_perl = perl_alloc();
+       if (!my_perl)
+           exit(1);
+       perl_construct( my_perl );
+       perl_destruct_level = 0;
+    }
+
+    exitstatus = perl_parse( my_perl, xs_init, argc, argv, (char **) NULL );
+    
+    if (!exitstatus)
+       Java_PerlInterpreter_eval(env, obj, js);
+
+}
+
+JNIEXPORT void JNICALL
+Java_PerlInterpreter_eval(JNIEnv *env, jobject obj, jstring js)
+{
+    SV* envsv;
+    SV* objsv;
+    dSP;
+    jbyte* jb;
+
+    ENTER;
+    SAVETMPS;
+
+    jplcurenv = env;
+    envsv = perl_get_sv("JPL::_env_", 1);
+    sv_setiv(envsv, (IV)(void*)env);
+    objsv = perl_get_sv("JPL::_obj_", 1);
+    sv_setiv(objsv, (IV)(void*)obj);
+
+    jb = (jbyte*)(*env)->GetStringUTFChars(env,js,0);
+
+    if (jpldebug)
+       fprintf(stderr, "eval %s\n", (char*)jb);
+
+    perl_eval_pv( (char*)jb, 0 );
+
+    if (SvTRUE(GvSV(errgv))) {
+       jthrowable newExcCls;
+
+       (*env)->ExceptionDescribe(env);
+       (*env)->ExceptionClear(env);
+
+       newExcCls = (*env)->FindClass(env, "java/lang/RuntimeException");
+       if (newExcCls)
+           (*env)->ThrowNew(env, newExcCls, SvPV(GvSV(errgv),na));
+    }
+
+    (*env)->ReleaseStringUTFChars(env,js,jb);
+    FREETMPS;
+    LEAVE;
+
+}
+
+/*
+JNIEXPORT jint JNICALL
+Java_PerlInterpreter_eval(JNIEnv *env, jobject obj, jint ji)
+{
+    op = (OP*)(void*)ji;
+    op = (*op->op_ppaddr)();
+    return (jint)(void*)op;
+}
+*/
+
+/* Register any extra external extensions */
+
+/* Do not delete this line--writemain depends on it */
+EXTERN_C void boot_DynaLoader _((CV* cv));
+EXTERN_C void boot_JNI _((CV* cv));
+
+static void
+xs_init()
+{
+    char *file = __FILE__;
+    dXSUB_SYS;
+        newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
+}
diff --git a/PerlInterpreter/PerlInterpreter.h b/PerlInterpreter/PerlInterpreter.h
new file mode 100644 (file)
index 0000000..22fdf52
--- /dev/null
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class PerlInterpreter */
+
+#ifndef _Included_PerlInterpreter
+#define _Included_PerlInterpreter
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     PerlInterpreter
+ * Method:    init
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_PerlInterpreter_init
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     PerlInterpreter
+ * Method:    eval
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_PerlInterpreter_eval
+  (JNIEnv *, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/PerlInterpreter/PerlInterpreter.java b/PerlInterpreter/PerlInterpreter.java
new file mode 100644 (file)
index 0000000..c26a4f2
--- /dev/null
@@ -0,0 +1,21 @@
+class PerlInterpreter {
+    static boolean initted = false;
+
+    public native void init(String s);
+    public native void eval(String s);
+
+//    public native long op(long i);
+
+    public PerlInterpreter fetch () {
+       if (!initted) {
+           init("$JPL::DEBUG = $ENV{JPLDEBUG}");
+           initted = true;
+       }
+       return this;
+    }
+
+    static {
+       System.loadLibrary("PerlInterpreter");
+    }
+}
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..ae23b4b
--- /dev/null
+++ b/README
@@ -0,0 +1,77 @@
+Copyright 1998, O'Reilly & Associates, Inc.
+
+This package may be copied under the same terms as Perl itself.
+
+Disclaimers
+-----------
+This is a work in progress, and relies on bleeding-edge technology
+from the network.  Don't expect not to be surprised occasionally.
+
+Requirements
+------------
+Perl 5.004 (or later) must be compiled and installed as a shared library
+(libperl.so).  I had to use the system's malloc.  We've tested
+it most heavily with 5.004_04.
+
+You need JDK 1.1.  On Solaris 1.1.1 works.  On Linux you need 1.1.3 with
+the patches from
+
+  ftp://ftp.blackdown.org/pub/Linux/JDK/1.1.3/updates/libjava-1.1.3v2-1.tar.gz
+
+The get_jdk directory contains a script that will download JDK (but not
+the patch file above) off of the net for you.  (This presumes you've
+already installed the modules mentioned in ../README.)
+
+What the heck is JPL?
+---------------------
+JPL is a hybrid (to use the polite term) language.  It's basically Java
+in which the methods can optionally be implemented by Perl code.  A
+preprocessor called "JPL::Compile" looks at your .jpl file and spits
+out the appropriate .java, .c, .h, .pl, and .so files to accomplish the
+desired task.  Hopefully a lot of those files can go away in the future
+as jpl mutates into a Perl-to-Java compiler.  The long-term goal is for
+jpl to be able to take a pure Perl file and spit out a java .class
+file.  This initial version of JPL is an attempt to begin to mesh the
+semantics of Java and Perl.  Some people may find it useful in its
+current form, but you should know right up front that we've still got a
+ways to go with it.  A journey of a thousand miles continues with the
+second step...
+
+JPL Syntax
+----------
+JPL syntax is trivial, given that you know Java and Perl.  Pretend like
+you're writing a native Java method, but say "perl" instead of
+"native", and then instead of omitting the body of the method, put your
+Perl code in double curlies.  (See Sample.jpl for an example.)
+
+Calling back from Perl to Java is done through the JNI (Java Native
+Interface).  No weird transmogrifications are done by the preprocessor
+to your Perl code--it's all normal Perl.  The preprocessor just wraps
+it up into funny subroutines you don't see unless you peek at the .pl
+file it generates.
+
+Installation
+------------
+Run "install-jpl".  You have to tell it whether you want to use the
+current directory for JPL_HOME or some other directory.  Everything
+else should take care of itself, except that after install-jpl
+write the setvars program, you are responsible to invoke it properly
+before any JPL applications can be compiled under the current shell.
+
+    sh:   eval `setvars -sh`
+    csh:  eval `setvars -csh`
+    perl: eval `setvars -perl`;
+
+More Info
+---------
+
+You can look at the Sample and Test directories, as well as the ../eg
+directory for examples.
+
+Perhaps the most important bit of advice we can give you is to watch
+
+    http://perl.oreilly.com
+
+for further information on how to get further information.
+
+Have the appropriate amount of fun.
diff --git a/Sample/Makefile.PL b/Sample/Makefile.PL
new file mode 100644 (file)
index 0000000..944c7e1
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+
+$JPL_HOME = $ENV{JPL_HOME}
+    or die "You have not run setvars to set your environment variables.\n" .
+           "See the JPL README file for more information.\n";
+
+use Config;
+
+eval `$JPL_HOME/setvars -perl`;
+
+chop($WHAT = `pwd`);
+$WHAT =~ s#.*/##;
+
+if ($^O eq 'linux') {
+    $flags = "-Dbool=char";    # avoid builtin bool altogether
+    $libs = "-lc -lm -ldl";
+}
+else {
+    $flags = "";
+    $libs = "-lc -lm -ldl";
+}
+chop($cwd = `pwd`);
+($jpldir = $cwd) =~ s#/[^/]*$##;
+
+open(MAKEFILE, ">Makefile");
+
+print MAKEFILE <<"SUBS";
+CC = $Config{cc}
+WHAT = $WHAT
+PERL = perl$]
+ARCHNAME = $Config{archname}
+JAVA_HOME = $ENV{JAVA_HOME}
+JPL_HOME = $ENV{JPL_HOME}
+PERLARCHDIR = $Config{archlib}
+FLAGS = $Config{cccdlflags} $Config{ccdlflags} $Config{lddlflags} $flags
+INCL  = -I\$(PERLARCHDIR)/CORE \\
+       -I\$(JAVA_HOME)/include \\
+       -I\$(JAVA_HOME)/include/$^O \\
+       -I\$(JAVA_HOME)/include/genunix
+LIBS = $libs
+
+SUBS
+
+print MAKEFILE <<'NOSUBS';
+.SUFFIXES: .jpl .class
+
+.jpl.class:
+       $(PERL) -MJPL::Compile -e "file('$*.jpl')"
+
+all: $(WHAT).class lib$(WHAT).so
+
+debug: $(WHAT)_g.class lib$(WHAT)_g.so
+
+lib$(WHAT).so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so
+       $(CC) $(FLAGS) $(INCL) $(WHAT).c \
+       $(PERLARCHDIR)/CORE/libperl.so \
+       $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so \
+       $(LIBS) \
+       -o lib$(WHAT).so
+
+lib$(WHAT)_g.so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so
+       $(CC) -g $(FLAGS) $(INCL) $(WHAT).c \
+       $(PERLARCHDIR)/CORE/libperl.so \
+       $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so \
+       $(LIBS) \
+       -o lib$(WHAT)_g.so
+
+test:
+
+install: all
+       cp *.class              $(JPL_HOME)/lib
+       cp lib$(WHAT).so        $(JPL_HOME)/lib/$(ARCHNAME)
+       cp $(WHAT).pl           $(JPL_HOME)/perl
+
+clean:
+       rm -f $(WHAT).c $(WHAT).h \
+       $(WHAT)*.class $(WHAT)*.pl lib$(WHAT).so $(WHAT)*.java
+
+distclean: clean
+       rm -f Makefile
+
+NOSUBS
+
+close MAKEFILE;
diff --git a/Sample/Sample.jpl b/Sample/Sample.jpl
new file mode 100644 (file)
index 0000000..a095201
--- /dev/null
@@ -0,0 +1,48 @@
+class Sample {
+    public static void main(String[] args) {
+       Sample sam = new Sample();
+       System.out.println(sam.foo("manny","moe","jack"));
+       System.out.println(sam.foo(1));
+       System.out.println(sam.foo(3.0));
+       sam.foo();
+    }
+
+    public static int thrice(int i) {
+       return i * 3;
+    }
+
+    perl void foo() {{
+       use POSIX;
+       print "TZ = ", POSIX::tzname(), "\n";
+       print "Got to ${self}->foo() method\n";
+       print "foo__I(2) = ", $self->foo__I__I(2),"\n";
+       print "thrice(123) = ", JPL::Sample->thrice__I__I(123), "\n";
+       print "thrice(12) = ", JPL::Sample->thrice__I__I(12), "\n";
+       print $self->foo__sss__s("MANNY", "MOE", "JACK"), "\n";
+       print 41 + $self->foo__sss__s("1", "2", "3"), "\n";
+       print "Perl version is $]\n";
+    }}
+
+    perl int foo(int a) {{
+       $a + $a;
+    }}
+
+    perl double foo(double a) {{
+       use JPL::Class 'java::util::Random';
+       $rng = java::util::Random->new();
+       print "RNG = $rng\n";
+       print $rng->nextDouble____D(), "\n";
+       print $rng->nextDouble____D(), "\n";
+       print $rng->nextDouble____D(), "\n";
+       print $rng->nextDouble____D(), "\n";
+       return $a * $a;
+    }}
+
+    perl String foo( String a,
+                    String b,
+                    String c ) {{
+       print "a = $a, b = $b, c = $c\n";
+       join "+", $a, $b, $c;
+    }}
+
+}
diff --git a/Test/Makefile.PL b/Test/Makefile.PL
new file mode 100644 (file)
index 0000000..3dd1f84
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+
+$JPL_HOME = $ENV{JPL_HOME}
+    or die "You have not run setvars to set your environment variables.\n" .
+           "See the JPL README file for more information.\n";
+
+use Config;
+
+eval `$JPL_HOME/setvars -perl`;
+
+chop($WHAT = `pwd`);
+$WHAT =~ s#.*/##;
+
+if ($^O eq 'linux') {
+    $flags = "-Dbool=char";    # avoid builtin bool altogether
+    $libs = "-lc -lm -ldl";
+}
+else {
+    $flags = "";
+    $libs = "-lc -lm -ldl";
+}
+chop($cwd = `pwd`);
+($jpldir = $cwd) =~ s#/[^/]*$##;
+
+open(MAKEFILE, ">Makefile");
+
+print MAKEFILE <<"SUBS";
+CC = $Config{cc}
+WHAT = $WHAT
+PERL = perl$]
+ARCHNAME = $Config{archname}
+JAVA_HOME = $ENV{JAVA_HOME}
+JPL_HOME = $ENV{JPL_HOME}
+PERLARCHDIR = $Config{archlib}
+FLAGS = $Config{cccdlflags} $Config{ccdlflags} $Config{lddlflags} $flags
+INCL  = -I\$(PERLARCHDIR)/CORE \\
+       -I\$(JAVA_HOME)/include \\
+       -I\$(JAVA_HOME)/include/$^O \\
+       -I\$(JAVA_HOME)/include/genunix
+LIBS = $libs
+
+SUBS
+
+print MAKEFILE <<'NOSUBS';
+.SUFFIXES: .jpl .class
+
+.jpl.class:
+       $(PERL) -MJPL::Compile -e "file('$*.jpl')"
+
+all: $(WHAT).class lib$(WHAT).so
+
+debug: $(WHAT)_g.class lib$(WHAT)_g.so
+
+lib$(WHAT).so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so
+       $(CC) $(FLAGS) $(INCL) $(WHAT).c \
+       $(PERLARCHDIR)/CORE/libperl.so \
+       $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so \
+       $(LIBS) \
+       -o lib$(WHAT).so
+
+lib$(WHAT)_g.so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so
+       $(CC) -g $(FLAGS) $(INCL) $(WHAT).c \
+       $(PERLARCHDIR)/CORE/libperl.so \
+       $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so \
+       $(LIBS) \
+       -o lib$(WHAT)_g.so
+
+test:
+
+install: all
+       cp $(WHAT).class        $(JPL_HOME)/lib
+       cp lib$(WHAT).so        $(JPL_HOME)/lib/$(ARCHNAME)
+       cp $(WHAT).pl           $(JPL_HOME)/perl
+
+clean:
+       rm -f $(WHAT).c $(WHAT).h \
+       $(WHAT)*.class $(WHAT)*.pl lib$(WHAT).so $(WHAT)*.java
+
+distclean: clean
+       rm -f Makefile
+
+NOSUBS
+
+close MAKEFILE;
diff --git a/Test/Test.jpl b/Test/Test.jpl
new file mode 100644 (file)
index 0000000..ab6a1ce
--- /dev/null
@@ -0,0 +1,122 @@
+import java.util.*;
+public class Test {
+    int myint = 123;
+    double mydouble = 3.14159265;
+    String mystring = "my string";
+    static String ourstring = "our string";
+    static boolean embedded = false;
+    int array[] = {1,2,3};
+    Vector v;
+
+    public Test() {
+
+       v = new Vector();
+       v.addElement("Hello");
+       printfields();
+       Vector x = perlTryVec(v);
+       x.addElement("World");
+       Vector y = perlTryVec(x);
+       if (!embedded) System.err.println("Thank you, perlTryVec!");
+
+       if (!embedded) System.err.println(retchars());
+       if (!embedded) System.err.println("Thank you, retchars!");
+
+       String[] s = retstrings();
+       if (!embedded) System.err.println(s[0] + s[1] + s[2] + s[3]);
+       if (!embedded) System.err.println("Thank you, retstrings!");
+
+       Object[] o = retobjects(v, x, y);
+       if (!embedded) System.err.println(o[1]);
+       if (!embedded) System.err.println(o[3]);
+       if (!embedded) System.err.println(o[4]);
+       if (!embedded) System.err.println("Thank you, retobjects!");
+
+       passarray(s);
+
+       if (!embedded) System.err.println(s[0] + s[1] + s[2] + s[3]);
+       if (!embedded) System.err.println("Thank you, passarray!");
+
+       printfields();
+       if (!embedded) System.err.println("Thank you, printfields!");
+       setfields();
+       if (!embedded) System.err.println("Thank you, setfields!");
+       printfields();
+       if (!embedded) System.err.println("Thank you, printfields!");
+    }
+    perl Vector perlTryVec(Vector v) throws RuntimeException {{
+       print "v is: $v\n";
+       print "v isa: ", ref $v,"\n";
+
+       print "In perlTryVec() - Vector size is: ", $v->size([],['int']), "\n";
+       @foo = times;
+       $size ||= getmeth('size', [], ['int']);
+       for ($i = 10000; $i; --$i) {
+           $x = $v->$size();
+       }
+       @bar = times;
+       printf "%5.2fu %5.2fs\n", $bar[0] - $foo[0], $bar[1] - $foo[1];
+       return $v;
+    }}
+
+    perl char[] retchars() {{
+       print "In retchars()\n";
+       return [65,66,67];
+    }}
+
+    perl String[] retstrings() {{
+       print "In retstrings()\n";
+       return [1,2,3,"many"];
+    }}
+    perl Object[] retobjects(Vector v, Vector x, Vector y) {{
+       print "In retstrings()\n";
+       return [$v, $x, $y, "this is only a test", 123];
+    }}
+
+    perl void passarray(String[] s) {{
+       print "In passarray()\n";
+       print "s = $s\n";
+       $t = GetObjectArrayElement($s,3);
+       print "t = $t\n";
+       $x = GetStringUTFChars($t);
+       print "$x\n";
+       $t = SetObjectArrayElement($s,3,NewStringUTF("infinity"));
+    }}
+    perl void printfields() {{
+
+       $| = 1;
+       eval {print $self->v->toString____s(), "\n";};
+       print $@ if $@;
+
+       print $self->myint, "\n";
+       print $self->mydouble, "\n";
+       print $self->mystring, "\n";
+       print JPL::Test->ourstring, "\n";
+
+       @nums = GetIntArrayElements($self->array());
+       print "@nums\n";
+
+       @nums = unpack("i*", scalar GetIntArrayElements($self->array()));
+       print "@nums\n";
+    }}
+
+    perl void setfields() {{
+       $self->myint(321);
+       $self->mydouble(2.7182918);
+       $self->mystring("MY STRING!!!");
+       JPL::Test->ourstring("OUR STRING!!!");
+    }}
+
+    public static void main(String[] argv) {
+       if (java.lang.reflect.Array.getLength(argv) > 0 &&
+         argv[0].equals("-nothanks"))
+           embedded = true;
+       Test f = new Test();
+       if (!embedded) System.err.println("Thank you, Test!");
+    }
+}
diff --git a/bin/jpl b/bin/jpl
new file mode 120000 (symlink)
index 0000000..b52049e
--- /dev/null
+++ b/bin/jpl
@@ -0,0 +1 @@
+../JPL/Compile.pm
\ No newline at end of file
diff --git a/get_jdk/README b/get_jdk/README
new file mode 100644 (file)
index 0000000..0c38ccf
--- /dev/null
@@ -0,0 +1,74 @@
+
+This archive contains the following files:
+README - the README file which explains how to use this program (this file)
+get_jdk.pl - the program to download JDK
+jdk_hosts - the descriptor file required by the program
+
+Nate Patwardhan (nvp@oreilly.com) wrote get_jdk.pl to automate the
+download of JDK (Java Development Kit) from a distribution site based
+on your Unix flavor.  This program is based on some of the examples
+found in the LWP cookbook that was included with your LWP distribution.
+
+Current Unix flavors that appear in the descriptor file (more
+suggestions from Beta testers will be welcomed):
+       Solaris
+       Linux
+       FreeBSD
+
+To use get_jdk.pl properly, you *must* have LWP (libwww) and its
+dependencies installed.  Once you've installed LWP, you should be able
+to use this module without any problems on any Unix flavor.
+
+By default, get_jdk.pl uses #!/usr/local/bin/perl in its shebang path,
+so you may have to execute get_jdk.pl like:
+
+       perl get_jdk.pl
+
+-OR-
+
+       perl5 get_jdk.pl
+
+based on your site's Perl installation.
+
+get_jdk.pl reads the $^O to determine what Unix flavor you're using,
+and compares the value of $^O to the first field shown in the
+descriptor file, jdk_hosts.  For example, $^O for Solaris versions of
+Perl is: 'solaris'; Solaris is represented in the descriptor file
+like:
+
+       solaris=>ftp://ftp.javasoft.com/pub/jdk1.1/jdk1.1.3-solaris2-sparc.bin
+
+When get_jdk.pl reads the descriptor file, it splits the fields on
+'=>', and reads them into a hash, %HOSTS.  get_jdk.pl then compares
+the value of $^O to $HOSTS{'osname'}, and returns the address of the
+JDK distribution site if $^O eq $HOSTS{'osname'}.  If there is not a
+match, get_jdk.pl fails.
+
+get_jdk.pl represents the hostname of distribution sites in URL
+format: protocol://hostname.some.com/path/filename.extension  
+When a URL is found, get_jdk.pl parses out the filename; this is
+significant, because the output from the remote host is directed to
+the file parsed from the URL.
+
+When you execute get_jdk.pl, you'll know it's working correctly if it
+outputs something like:
+
+       A JDK port for your OS has been found.
+       Contacting:
+       ftp://ftp.javasoft.com/pub/jdk1.1/jdk1.1.3-solaris2-sparc.bin
+       Attempting to download: jdk1.1.3-solaris2-sparc.bin
+       0% - 1460 bytes received
+       0% - 4380 bytes received
+       0% - 7300 bytes received
+       0% - 8192 bytes received
+       [etc etc etc until you reach 100%]
+
+Future (PRK release) versions of get_jdk.pl will allow the user to
+update the descriptor file from the ora.com (oreilly.com) FTP/WWW
+site.  This version does not support the -update flag.
+
+Happy JDK'ing!  :-)
+
+--
+Nate Patwardhan
+nvp@oreilly.com
diff --git a/get_jdk/get_jdk.pl b/get_jdk/get_jdk.pl
new file mode 100755 (executable)
index 0000000..d6d399d
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/bin/perl -w
+
+# Based on an ftp client found in the LWP Cookbook and
+# revised by Nathan V. Patwardhan <nvp@ora.com>.
+
+# Copyright 1997 O'Reilly and Associates
+# This package may be copied under the same terms as Perl itself.
+#
+# Code appears in the Unix version of the Perl Resource Kit
+
+use LWP::UserAgent;
+use URI::URL;
+
+my $ua = new LWP::UserAgent;
+
+# check to see if a JDK port exists for the OS.  i'd say
+# that we should use solaris by default, but a 9meg tarfile
+# is a hard pill to swallow if it won't work for somebody.  :-)
+my $os_type = $^O; my $URL = lookup_jdk_port($os_type);
+die("No JDK port found.  Contact your vendor for details.  Exiting.\n")
+    if $URL eq '';
+
+print "A JDK port for your OS has been found.\nContacting: ".$URL."\n";
+
+# Now, parse the URL using URI::URL
+my($jdk_file) = (url($URL)->crack)[5]; 
+$jdk_file =~ /(.+)\/(.+)/; $jdk_file = $2;
+
+print "Attempting to download: $jdk_file\n";
+
+my $expected_length;
+my $bytes_received = 0;
+
+open(OUT, ">".$jdk_file) or die("Can't open $jdk_file: $!");
+$ua->request(HTTP::Request->new('GET', $URL),
+            sub {
+                my($chunk, $res) = @_;
+
+                $bytes_received += length($chunk);
+                unless (defined $expected_length) {
+                    $expected_length = $res->content_length || 0;
+                }
+                if ($expected_length) {
+                    printf STDERR "%d%% - ",
+                    100 * $bytes_received / $expected_length;
+                }
+                print STDERR "$bytes_received bytes received\n";
+
+                print OUT $chunk;
+            }
+);
+close(OUT);
+
+sub lookup_jdk_port {
+    my($port_os) = @_;
+    my $jdk_hosts = 'jdk_hosts';
+    my %HOSTS = ();
+
+    open(CFG, $jdk_hosts) or die("hosts error: $!");
+    while(<CFG>) {
+       chop;
+       ($os, $host) = split(/\s*=>\s*/, $_);
+       next unless $os eq $port_os;
+       push(@HOSTS, $host);
+    }
+    close(CFG);
+
+    return "" unless @HOSTS;
+    return $HOSTS[rand @HOSTS];                # Pick one at random.
+}
+
diff --git a/get_jdk/jdk_hosts b/get_jdk/jdk_hosts
new file mode 100644 (file)
index 0000000..fa50b51
--- /dev/null
@@ -0,0 +1,4 @@
+solaris => ftp://ftp.javasoft.com/pub/jdk1.1/jdk1.1.3-solaris2-sparc.bin
+linux  => ftp://ftp.infomagic.com/pub/mirrors/linux/Java/JDK-1.1.3/linux-jdk.1.1.3-v2.tar.gz
+linux  => ftp://ftp.connectnet.com/pub/java/JDK-1.1.3/linux-jdk.1.1.3-v2.tar.gz
+freebsd        => http://www.csi.uottawa.ca/~kwhite/jdkbinaries/jdk1.1-FreeBSD.tar.gz
diff --git a/install-jpl b/install-jpl
new file mode 100755 (executable)
index 0000000..546ae91
--- /dev/null
@@ -0,0 +1,229 @@
+#!/usr/bin/perl
+
+print <<'END' if $>;
+NOTE: Since you're not running as root, the installation will su at
+the appropriate time later.  You will need to supply the root password
+for the su program.
+
+END
+
+# Gather data.
+
+# JPL_SRC
+
+chop($JPL_SRC = `pwd`);
+print "JPL_SRC = $JPL_SRC\n";
+
+# JAVA_HOME
+
+foreach $dir (
+    $ENV{JAVA_HOME},
+    "/usr/java",
+    "/usr/local/java",
+    "/usr/lib/java",
+    "/usr/local/lib/java",
+) {
+    $JAVA_HOME = $dir, last if $dir and -d "$dir/bin";
+}
+die "You must set the \$JAVA_HOME environment variable first.\n"
+       unless $JAVA_HOME;
+print "JAVA_HOME = $JAVA_HOME\n";
+
+# JPL_HOME
+
+($likelyjpl = $JAVA_HOME) =~ s#(.*)/.*#$1/jpl#;
+
+print <<"END";
+
+You need to decide which directory JPL files are to be installed in.
+Applications will look in subdirectories of this directory for any JPL
+related files.
+
+You may use the current directory ($JPL_SRC)
+or you may use a directory such as $likelyjpl.
+
+END
+
+$| = 1;
+until (-d $JPL_HOME) {
+    print "Install JPL files where: [$JPL_SRC] ";
+    chop($JPL_HOME = <STDIN>);
+    $JPL_HOME ||= $JPL_SRC;
+    unless (-d $JPL_HOME) {
+       print "Warning: $JPL_HOME doesn't exist yet!\n\n";
+       print "Do you want to create it? [y] ";
+       chop($ans = <STDIN>);
+       $ans ||= 'y';
+       next unless $ans =~ /^y/i;
+
+       system "mkdir -p $JPL_HOME";
+       if ($> and not -d $JPL_HOME) {
+           warn "Couldn't create $JPL_HOME!\nTrying again as root...running su...\n";
+           system "set -x
+su root -c 'mkdir -p $JPL_HOME && chown $> $JPL_HOME && chmod 0755 $JPL_HOME'";
+           warn "Couldn't create $JPL_HOME!\n" unless -d $JPL_HOME;
+       }
+    }
+}
+print "JPL_HOME = $JPL_HOME\n";
+
+#########################################################################
+# Spit out setvars.
+
+print "Writing setvars...\n";
+
+unlink "$JPL_SRC/setvars";
+open(SETVARS, ">$JPL_HOME/setvars") or die "Can't create setvars: $!\n";
+while (<DATA>) {
+    s/^JPL_SRC=.*/JPL_SRC='$JPL_SRC'/;
+    s/^JAVA_HOME=.*/JAVA_HOME='$JAVA_HOME'/;
+    s/^JPL_HOME=.*/JPL_HOME='$JPL_HOME'/;
+    print SETVARS $_;
+}
+close SETVARS;
+chmod 0755, "$JPL_HOME/setvars";
+symlink "$JPL_HOME/setvars", "$JPL_SRC/setvars" if $JPL_HOME ne $JPL_SRC;
+
+#########################################################################
+# Pretend we're make.
+
+eval `./setvars -perl`;                # Take our own medicine.
+
+print "\n\nStarting install...\n";
+
+system <<'END' and die "Couldn't install JPL\n";
+set -x
+cd JPL
+perl Makefile.PL
+make clean
+perl Makefile.PL
+make install
+END
+
+print "\nInstalling PerlInterpreter class\n";
+
+system <<'END' and die "Couldn't install PerlInterpreter\n";
+set -x
+cd PerlInterpreter
+perl Makefile.PL
+make clean
+perl Makefile.PL
+make install
+END
+
+print "\nInstalling JNI module\n";
+
+system <<'END' and die "Couldn't install JNI\n";
+set -x
+cd JNI
+perl Makefile.PL
+make clean
+perl Makefile.PL
+make
+echo 'Attempting to install JNI as root'
+su root -c "make install"
+END
+
+#touch Makefile
+#make -f makefile.jv
+## These should be executed as root
+#rm -rf /usr/lib/perl5/site_perl/i586-linux/auto/JNI
+#rm -rf /usr/lib/perl5/site_perl/auto/JNI
+#rm -f  /usr/lib/perl5/site_perl/JNI.pm
+#make -f makefile.jv install UNINST=1 
+
+print "\nInstalling Sample JPL program\n";
+
+system <<'END' and die "Couldn't install Sample\n";
+set -x
+cd Sample
+perl Makefile.PL
+make clean
+perl Makefile.PL
+make install
+END
+
+# Test
+print "\n\nTesting Sample...\n";
+system <<'END' and die "Couldn't run Sample\n";
+set -x
+cd Sample
+JPLDEBUG=1
+export JPLDEBUG
+java Sample
+END
+
+__END__
+#!/bin/sh
+
+# You can edit this, but your changes will only last until the next
+# time you run install-jpl.
+
+# Where jpl is currently installed
+
+cd `dirname $0`
+JPL_SRC=`pwd`
+
+# Where java is installed
+
+JAVA_HOME=/usr/local/java
+export JAVA_HOME
+
+# Where jpl will be installed
+
+JPL_HOME="$JPL_SRC"
+export JPL_HOME
+
+# Which perl to run
+
+JPLPERL=perl`perl -e "print $]"`
+#JPLPERL=perl5.00404
+export JPLPERL
+
+# Some derivative variables
+archname=`$JPLPERL -MConfig -e 'print $Config{archname}'`
+ archlib=`$JPLPERL -MConfig -e 'print $Config{archlib}'`
+
+CLASSPATH=".:$JPL_HOME/lib${CLASSPATH:+:$CLASSPATH}"
+export CLASSPATH
+
+LD_LIBRARY_PATH=".:$JPL_HOME/lib/$archname:$archlib/CORE${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
+export LD_LIBRARY_PATH
+
+PERL5LIB="$JPL_HOME/perl${PERL5LIB:+:$PERL5LIB}"
+export PERL5LIB
+
+# Make sure the right java programs are selected.
+PATH="$JAVA_HOME/bin:$PATH"
+export PATH
+
+case "$1" in
+-perl)
+    cat <<END
+\$ENV{PATH} = '$PATH';
+\$ENV{JAVA_HOME} = '$JAVA_HOME';
+\$ENV{JPL_HOME} = '$JPL_HOME';
+\$ENV{JPLPERL} = '$JPLPERL';
+\$ENV{CLASSPATH} = '$CLASSPATH';
+\$ENV{LD_LIBRARY_PATH} = '$LD_LIBRARY_PATH';
+\$ENV{PERL5LIB} = '$PERL5LIB';
+END
+    ;;
+-sh)
+    cat <<END
+ PATH='$PATH';export PATH;JAVA_HOME='$JAVA_HOME';export JAVA_HOME;JPL_HOME='$JPL_HOME';export JPL_HOME;JPLPERL='$JPLPERL';export JPLPERL;CLASSPATH='$CLASSPATH';export CLASSPATH;LD_LIBRARY_PATH='$LD_LIBRARY_PATH';export LD_LIBRARY_PATH;PERL5LIB='$PERL5LIB';export PERL5LIB
+END
+    ;;
+-csh)
+    cat <<END
+setenv PATH '$PATH';
+setenv JAVA_HOME '$JAVA_HOME';
+setenv JPL_HOME '$JPL_HOME';
+setenv JPLPERL '$JPLPERL';
+setenv CLASSPATH '$CLASSPATH';
+setenv LD_LIBRARY_PATH '$LD_LIBRARY_PATH';
+setenv PERL5LIB '$PERL5LIB';
+END
+    ;;
+esac
+