[kaffe] Using Kaffe with remote debugging via Eclipse

Derek Davies ddavies at ddavies.net
Thu Aug 19 22:11:45 PDT 2004


Hi,

There's bad news and good news.  The bad news is that my most recent
backup of kaffe JVMDI work (~2001) gets I/O errors when I try to read
it.  It's shrimp toast.  The good news is that at least I was able to
read the second most recent backup I have (~2000) and that has some
stuff done against 1.0.5 .

I don't think I have the 1.0.6 stuff I did anywhere.  I do remember
that I had run into problems that made me redo a lot of stuff...

Best of luck and thanks for trying to revive this.  It brings back
good memories!

Derek

diff -Nru kaffe-1.0.5/kaffe/kaffe/main.c kaffe-1.0.5-hacks/kaffe/kaffe/main.c
--- kaffe-1.0.5/kaffe/kaffe/main.c	1999-10-18 01:23:54.000000000 -0400
+++ kaffe-1.0.5-hacks/kaffe/kaffe/main.c	2000-01-02 17:47:57.000000000 -0500
@@ -9,6 +9,16 @@
  * of this file. 
  */
 
+/* +++ DLD Tue Oct 19 21:02:26 1999 */
+#include <jvmdi.h>
+#include <jvmdiEvents.h>
+/* --- DLD */
+
+/* +++ DLD Thu Oct 14 19:04:54 1999 */
+/* FIXME: I know this isn't right...use the accepted abstractions */
+#include <dlfcn.h>
+/* --- DLD */
+
 #include "config.h"
 #include "config-std.h"
 #include "config-mem.h"
@@ -36,11 +46,19 @@
 JNIEnv* env;
 JavaVM* vm;
 static int isJar = 0;
+/* +++ DLD Thu Oct 14 16:47:51 1999 */
+static void* dlHdl = NULL;
+static char* jvmdiClientLibraryName = NULL;
+static char* jvmdiClientLibraryOnLoadArgs = NULL;
+/* --- DLD */
 
 static int options(char**);
 static void usage(void);
 static size_t parseSize(char*);
 static void handleErrors(void);
+/* +++ DLD Thu Oct 14 16:22:01 1999 */
+static int registerJVMDIClient(void);
+/* --- DLD */
 static int main2(JNIEnv* env, char *argv[], int farg, int argc);
 
 #define	KAFFEHOME	"KAFFEHOME"
@@ -109,6 +127,19 @@
 		exit(1);
 	}
 
+	/* +++ DLD Thu Oct 14 16:17:18 1999 */
+	
+	/* Load the JVMDI client library, if it was given.
+	*/
+	if (jvmdiClientLibraryName)
+	{
+		if (registerJVMDIClient()) {
+			exit(2);
+		}
+	}
+
+	/* --- DLD */
+
 	/* Initialise */
 	JNI_CreateJavaVM(&vm, &env, &vmargs);
 
@@ -190,11 +221,34 @@
 		(*env)->SetObjectArrayElement(env, args, i, str);
 		handleErrors();
 	}
+	
+	/* +++ DLD Thu Oct 21 19:01:56 1999 */
+	fireVMInitEvent();
+	handleErrors();
+	/* --- DLD */
 
 	/* Call method, check for errors and then exit */
 	(*env)->CallStaticVoidMethod(env, mcls, mmth, args);
 	handleErrors();
 
+	/* +++ DLD Sun Oct 17 13:57:22 1999 */
+	/* FIXME: Is this really the right time/place to fire this event?  The
+	   spec is, um, a little sparse regarding this detail. */
+	fireVMDeathEvent();
+	handleErrors();
+	/* --- DLD */
+	
+	/* +++ DLD Thu Oct 14 16:49:38 1999 */
+	/* FIXME: make this portable */
+	if (dlHdl)
+	{
+		(void)dlclose(dlHdl);
+		dlHdl = NULL;
+		
+		fprintf(stderr, "Unloaded JVMDI client library\n");
+	}
+	/* --- DLD */
+	
 	(*vm)->DetachCurrentThread(vm);
 	return (0);
 }
@@ -403,6 +457,28 @@
 			prop->key = &argv[i][2];
 			prop->value = &argv[i][sz];
 		}
+		/* +++ DLD Thu Oct 14 15:27:37 1999 */
+		/* eXtension?  I don't know, Sun came up with this. */
+		else if (argv[i][1] ==  'X') {
+			if (strcmp(&(argv[i][2]), "debug") == 0) {
+				/* FIXME */
+			}
+			else if (strcmp(&(argv[i][2]), "noagent") == 0) {
+				/* FIXME */
+			}
+			else if (strncmp(&(argv[i][2]), "run", 3) == 0) {
+				for (sz = 5; argv[i][sz] != 0; sz++) {
+					if (argv[i][sz] == ':') {
+						argv[i][sz] = 0;
+						sz++;
+						break;
+					}
+				}
+				jvmdiClientLibraryName = &argv[i][5];
+				jvmdiClientLibraryOnLoadArgs = &argv[i][sz];
+			}
+		}
+		/* --- DLD */
 		/* The following options are not supported and will be
 		 * ignored for compatibility purposes.
 		 */
@@ -462,6 +538,11 @@
 #ifdef KAFFE_STATS
         fprintf(stderr, "	-vmstats <flag{,flag}>	Print VM statistics.  Set flag=all for all\n");                     
 #endif
+	/* +++ DLD Fri Oct 15 10:25:42 1999 */
+	fprintf(stderr, "	-Xdebug *			Turn on debugger mode\n");
+	fprintf(stderr, "	-Xnoagent *			Don't load default debug agent\n");
+	fprintf(stderr, "	-Xrun<lib>:<args>	JVMDI client library and args\n");
+	/* --- DLD */
 	fprintf(stderr, "  * Option currently ignored.\n");
 }
 
@@ -488,3 +569,44 @@
 
 	return (sz);
 }
+
+/* +++ DLD Thu Oct 14 16:22:47 1999 */
+
+static jint registerJVMDIClient()
+{
+	/* FIXME: Make this portable */
+	/*JNIEXPORT*/ jint /*JNICALL*/ (*JVM_OnLoad)(JavaVM*, char*, void*);
+	
+	if (!(dlHdl = dlopen(jvmdiClientLibraryName, RTLD_LAZY)))
+	{
+		fprintf(stderr,
+				"Error loading JVMDI client library:\n%s\n", dlerror());
+		return 1;
+	}
+
+	/* This is part of JVMDI protocol.
+	*/
+	JVM_OnLoad = dlsym(dlHdl, "JVM_OnLoad");
+	{
+		char* e = dlerror();
+		if (e)
+		{
+			(void)dlclose(dlHdl);
+			dlHdl = NULL;
+			fprintf(
+				stderr,
+				"Can't find JVMDI client library JVM_OnLoad routine:\n%s\n",
+				e);
+			return 1;
+		}
+	}
+
+	/* FIXME: Do I have to increment the ref count on VM here or what?
+	   What's the right way to hand this out?  Is it under GC?
+	*/
+	(*JVM_OnLoad)(vm, jvmdiClientLibraryOnLoadArgs, (void*)NULL);
+
+	return 0;
+}
+
+/* --- DLD */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/Makefile.am kaffe-1.0.5-hacks/kaffe/kaffevm/Makefile.am
--- kaffe-1.0.5/kaffe/kaffevm/Makefile.am	1999-10-18 01:23:57.000000000 -0400
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/Makefile.am	2000-01-11 18:57:40.000000000 -0500
@@ -61,6 +61,7 @@
 	itypes.c \
 	jar.c \
 	jni.c \
+	jvmdi.c \
 	locks.c \
 	lookup.c \
 	object.c \
@@ -99,6 +100,8 @@
 	itypes.h \
 	jar.h \
 	jnirefs.h \
+	jvmdiEvents.h \
+	jvmdiRawMonitor.h \
 	lerrno.h \
 	locks.h \
 	lookup.h \
diff -Nru kaffe-1.0.5/kaffe/kaffevm/Makefile.in kaffe-1.0.5-hacks/kaffe/kaffevm/Makefile.in
--- kaffe-1.0.5/kaffe/kaffevm/Makefile.in	1999-10-18 01:23:57.000000000 -0400
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/Makefile.in	2000-01-11 18:58:11.000000000 -0500
@@ -184,6 +184,7 @@
 	itypes.c \
 	jar.c \
 	jni.c \
+	jvmdi.c \
 	locks.c \
 	lookup.c \
 	object.c \
@@ -223,6 +224,8 @@
 	itypes.h \
 	jar.h \
 	jnirefs.h \
+	jvmdiEvents.h \
+	jvmdiRawMonitor.h \
 	lerrno.h \
 	locks.h \
 	lookup.h \
@@ -259,7 +262,7 @@
 am_libkaffevm_la_OBJECTS =  gc-mem.lo md.lo baseClasses.lo \
 classMethod.lo classPool.lo methodCache.lo code-analyse.lo code.lo \
 constants.lo debug.lo exception.lo external.lo findInJar.lo fp.lo gc.lo \
-hashtab.lo inflate.lo itypes.lo jar.lo jni.lo locks.lo lookup.lo \
+hashtab.lo inflate.lo itypes.lo jar.lo jni.lo jvmdi.lo locks.lo lookup.lo \
 object.lo readClass.lo sha-1.lo soft.lo stackTrace.lo stats.lo \
 string.lo support.lo thread.lo utf8const.lo gcFuncs.lo gcRefs.lo \
 verify.lo
diff -Nru kaffe-1.0.5/kaffe/kaffevm/intrp/machine.c kaffe-1.0.5-hacks/kaffe/kaffevm/intrp/machine.c
--- kaffe-1.0.5/kaffe/kaffevm/intrp/machine.c	1999-10-18 01:24:00.000000000 -0400
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/intrp/machine.c	1999-12-07 20:52:45.000000000 -0500
@@ -44,6 +44,11 @@
 #include "errors.h"
 #include "md.h"
 
+/* +++ DLD Thu Oct 21 20:29:43 1999 */
+#include "jvmdi.h"
+#include "jvmdiEvents.h"
+/* --- DLD */
+
 /*
  * Define information about this engine.
  */
@@ -241,6 +246,28 @@
 		mjbuf->pc = pc;
 		npc = pc + insnLen[code[pc]];
 
+		/* +++ DLD Thu Oct 21 20:02:14 1999 */
+/*
+#ifdef JVMDI
+*/
+		if (strncmp(meth->class->name->data,
+					"HiChico",
+					sizeof("HiChico")) == 0)
+		{
+			printf("in HiChico.%s:{pc=%d, npc=%d, code=0x%x}\n",
+				   meth->name->data, pc, npc, code[pc]);
+			
+			fireSingleStepEvent(
+				*(jthread_current()),
+				(jclass)meth->class,
+				(jmethodID)meth->idx,
+				(jlocation)pc);
+		}
+/*
+#endif
+*/
+		/* --- DLD */
+	
 		switch (code[pc]) {
 		default:
 			fprintf(stderr, "Unknown bytecode %d\n", code[pc]);
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/HiChico.class and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/HiChico.class differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/HiChico.java kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/HiChico.java
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/HiChico.java	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/HiChico.java	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,24 @@
+
+class HiChico
+{
+	public void sayHiAgain()
+	{
+		System.out.println("Mia! Mia!");
+	}
+	
+	HiChico()
+	{
+		System.out.println("Anichka Maya!");
+		sayHiAgain();
+		System.out.println("Hi Chico!");
+	}
+	
+	public static void main(String args[])
+	{
+		System.out.println("Bilky");
+		new HiChico();
+		System.out.println("smaltcoat");
+	}
+}
+
+// End of HiChico.java
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/Makefile kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/Makefile
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/Makefile	2000-01-02 18:43:39.000000000 -0500
@@ -0,0 +1,16 @@
+
+# FIXME: Do this the Right Way.
+
+CFLAGS=-I../../../include -I../../../config -I../systems/unix-jthreads -I../ -DKVER -I/usr/include/readline
+
+.PHONY:	all
+all:	jpdaBackend.so
+
+jpdaBackend.so:	jpdaBackend.o
+	gcc -shared $^ -Wl,--whole-archive ../systems/unix-jthreads/.libs/libkthread.al -Wl,--no-whole-archive -ldl -lm -lc -lreadline -Wl,-soname -Wl,-llibkaffevm-1.0b4.so -o ./libjpdaBackend.so
+
+.PHONY:	check
+check:
+	test.sh
+
+# End of Makefile
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/Makefile-cli-serv kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/Makefile-cli-serv
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/Makefile-cli-serv	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/Makefile-cli-serv	1999-12-27 13:38:41.000000000 -0500
@@ -0,0 +1,19 @@
+
+LOADLIBES=-lsocket -lnsl
+CFLAGS=-Wall
+CC=gcc
+
+.PHONY:	all
+all:		cmd-client cmd-server
+
+cmd-client:	cmd-client.o sockhelp.o
+
+cmd-server:	cmd-server.o sockhelp.o
+
+sockhelp.o:	sockhelp.c
+
+.PHONY:	clean
+clean:
+	rm -f *.o cmd-client cmd-server
+
+# End of Makefile
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/README.RUN kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/README.RUN
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/README.RUN	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/README.RUN	2000-01-02 18:46:43.000000000 -0500
@@ -0,0 +1,166 @@
+
+<READ Example run:>
+
+V.:/home/ddavies/src/kaffe-1.0.5>export LD_LIBRARY_PATH=.:/usr/local/lib:/usr/lib:/lib
+V.:/home/ddavies/src/kaffe-1.0.5>kaffe -XrunlibjpdaBackend.so:hi,chico HiChico
+Error loading JVMDI client library:
+libjpdaBackend.so: cannot open shared object file: No such file or directory
+V.:/home/ddavies/src/kaffe-1.0.5>cd kaffe/kaffevm/jpdaBackend/
+V.:/home/ddavies/src/kaffe-1.0.5/kaffe/kaffevm/jpdaBackend>kaffe -XrunlibjpdaBackend.so:hi,chico HiChico
+jvmdb: Kaffe JVMDI Debugger Client
+jvmdb: Hack! Hack!
+jvmdb: VM initialization event received.
+jvmdb> b
+Internal error: caught an unexpected exception.
+Please check your CLASSPATH and your installation.
+java/lang/NullPointerException
+Aborted (core dumped)
+V.:/home/ddavies/src/kaffe-1.0.5/kaffe/kaffevm/jpdaBackend>kaffe -XrunlibjpdaBackend.so:hi,chico HiChico
+jvmdb: Kaffe JVMDI Debugger Client
+jvmdb: Hack! Hack!
+jvmdb: VM initialization event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=0, npc=3, code=0xb2}
+SingleStepEvent!! pc is 0
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=3, npc=5, code=0x12}
+SingleStepEvent!! pc is 3
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=5, npc=8, code=0xb6}
+SingleStepEvent!! pc is 5
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+Bilky
+in HiChico.main:{pc=8, npc=11, code=0xbb}
+SingleStepEvent!! pc is 8
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=11, npc=12, code=0x59}
+SingleStepEvent!! pc is b
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=12, npc=15, code=0xb7}
+SingleStepEvent!! pc is c
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=0, npc=1, code=0x2a}
+SingleStepEvent!! pc is 0
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=1, npc=4, code=0xb7}
+SingleStepEvent!! pc is 1
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=4, npc=7, code=0xb2}
+SingleStepEvent!! pc is 4
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=7, npc=9, code=0x12}
+SingleStepEvent!! pc is 7
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=9, npc=12, code=0xb6}
+SingleStepEvent!! pc is 9
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+Anichka Maya!
+in HiChico.<init>:{pc=12, npc=13, code=0x2a}
+SingleStepEvent!! pc is c
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=13, npc=16, code=0xb6}
+SingleStepEvent!! pc is d
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.sayHiAgain:{pc=0, npc=3, code=0xb2}
+SingleStepEvent!! pc is 0
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.sayHiAgain:{pc=3, npc=5, code=0x12}
+SingleStepEvent!! pc is 3
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.sayHiAgain:{pc=5, npc=8, code=0xb6}
+SingleStepEvent!! pc is 5
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+Mia! Mia!
+in HiChico.sayHiAgain:{pc=8, npc=9, code=0xb1}
+SingleStepEvent!! pc is 8
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=16, npc=19, code=0xb2}
+SingleStepEvent!! pc is 10
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=19, npc=21, code=0x12}
+SingleStepEvent!! pc is 13
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.<init>:{pc=21, npc=24, code=0xb6}
+SingleStepEvent!! pc is 15
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+Hi Chico!
+in HiChico.<init>:{pc=24, npc=25, code=0xb1}
+SingleStepEvent!! pc is 18
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=15, npc=16, code=0x57}
+SingleStepEvent!! pc is f
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=16, npc=19, code=0xb2}
+SingleStepEvent!! pc is 10
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=19, npc=21, code=0x12}
+SingleStepEvent!! pc is 13
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+in HiChico.main:{pc=21, npc=24, code=0xb6}
+SingleStepEvent!! pc is 15
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+smaltcoat
+in HiChico.main:{pc=24, npc=25, code=0xb1}
+SingleStepEvent!! pc is 18
+jvmdb: Single step event received.
+jvmdb> c
+jvmdb: Continuing.
+jvmdb: VM death event received.
+jvmdb> c
+jvmdb: Error.  Unrecognized command.
+jvmdb> q
+jvmdb: Quiting.
+
+
+</READ thats all for now, add to me! >
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/breakpoints.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/breakpoints.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/breakpoints.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/breakpoints.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,16 @@
+
+#include "jvmdi.h"
+
+jvmdiError SetBreakpoint(jclass clazz, jmethodID method, jlocation location)
+{
+}
+
+jvmdiError ClearBreakpoint(jclass class, jmethodID method, jlocalion location)
+{
+}
+
+jvmdierror ClearAllBreakpoints()
+{
+}
+
+/* End of breakpoints.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/class_info.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/class_info.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/class_info.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/class_info.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,47 @@
+
+#include "jvmdi.h"
+
+jvmdiError GetClassSignature(jclass clazz, char** sigPtr)
+{
+}
+
+jvmdiError GetClassStatus(jclass clazz, char* statusPtr)
+{
+}
+
+jvmdiError GetSourceFileName(jclass clazz, char** sourceNamePtr)
+{
+}
+
+jvmdiError GetClassModifiers(jclass clazz, jint* modifiersPtr)
+{
+}
+
+jvmdiError GetClassMethods(jclass clazz, jint* methodCountPtr,
+						   methodID** methodsPtr)
+{
+}
+
+jvmdiError GetClassFields(jclass clazz, jint* fieldCountPtr,
+						  jfieldID** fieldsPtr)
+{
+}
+
+jvmdiError GetImplementedInterfaces(jclass clazz, jint* interfaceCountPtr,
+									jclass** interfacesPtr)
+{
+}
+
+jvmdiError IsInterface(jclass clazz, jboolean* isInterfacePtr)
+{
+}
+
+jvmdiError IsArrayclass(jclass clazz, jboolean* isArrayClassPyr)
+{
+}
+
+jvmdiError GetClassLoader(jclass clazz, jobject* classloaderPtr)
+{
+}
+
+/* End of class_info.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/cmd-client.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/cmd-client.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/cmd-client.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/cmd-client.c	1999-12-27 13:32:46.000000000 -0500
@@ -0,0 +1,67 @@
+/*
+ *  This file is provided for use with the unix-socket-faq.  It is public
+ *  domain, and may be copied freely.  There is no copyright on it.  The
+ *  original work was by Vic Metcalfe (vic at brutus.tlug.org), and any
+ *  modifications made to that work were made with the understanding that
+ *  the finished work would be in the public domain.
+ *
+ *  If you have found a bug, please pass it on to me at the above address
+ *  acknowledging that there will be no copyright on your work.
+ *
+ *  The most recent version of this file, and the unix-socket-faq can be
+ *  found at http://www.interlog.com/~vic/sock-faq/.
+ */
+
+#include "sockhelp.h"
+#include <stdio.h>
+#include <unistd.h>
+
+int read_line_from_server_and_print(int sock)
+{
+	static char buffer[1024];
+	
+	if (sock_gets(sock, buffer, sizeof(buffer) - 1) < 0)
+	{
+		fprintf(stderr, "sock_gets() call failed, aborting\n");
+		return -1;
+	}
+	else
+	{
+		printf("%s\n", buffer);
+	}
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int sock;
+
+	if (argc != 3)
+	{
+		fprintf(stderr,"Usage:  hostname-client host port\n");
+		fprintf(stderr,"where host is the machine which is running the\n");
+		fprintf(stderr,"hostname-server program, and port is the port\n");
+		fprintf(stderr,"on which it's listening.\n");
+		exit(EXIT_FAILURE);
+	}
+	
+	ignore_pipe();
+	sock = make_connection(argv[2], SOCK_STREAM, argv[1]);
+	if (sock == -1)
+	{
+		fprintf(stderr,"make_connection failed.\n");
+		return -1;
+	}
+
+	if (read_line_from_server_and_print(sock) >= 0)
+	{
+		(void)read_line_from_server_and_print(sock);
+	}
+	
+	close(sock);
+	
+	return 0;
+}
+
+/* End of hostname-client.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/cmd-server.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/cmd-server.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/cmd-server.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/cmd-server.c	1999-12-27 13:49:50.000000000 -0500
@@ -0,0 +1,79 @@
+
+/*
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <sys/utsname.h>
+#include <sys/resource.h>
+*/
+#include "sockhelp.h"
+
+/* Waits for all children so that they don't become zombies.
+*/
+void sig_chld(int signal_type)
+{
+    int pid;
+    int status;
+
+    while ((pid = wait3(&status, WNOHANG, NULL)) > 0);
+}
+
+int main(int argc, char* argv[])
+{
+    int sock;
+    int port = -1;
+    char buffer[1024];
+    struct sigaction act;
+    struct sigaction oldact;
+    struct utsname system_info;
+
+    if (argc != 2)
+    {
+	fprintf(stderr, "Usage:  cmd-server <port>\n");
+	fprintf(stderr, "Where:\n");
+	fprintf(stderr, "\t<port> is a port number or service name.\n");
+	exit(EXIT_FAILURE);
+    }
+	
+    ignore_pipe();
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = 0;
+    act.sa_handler = sig_chld;
+    sigaction(SIGCHLD, &act, &oldact);
+
+    port = atoport(argv[1], "tcp");
+    if (port == -1)
+    {
+	fprintf(stderr, "Unable to find service: %s\n", argv[1]);
+	exit(EXIT_FAILURE);
+    }
+
+    sock = get_connection(SOCK_STREAM, port, NULL);
+
+    sock_puts(sock, "Welcome to the cmd-server!\n");
+
+    if (uname(&system_info) < 0)
+    {
+	sprintf(buffer,
+		"Couldn't get hostname [uname() call failed, errno is %d]\n",
+		errno);
+	sock_puts(sock, buffer);
+    }
+    else
+    {
+	sprintf(buffer,
+		"This server is running on host %s\n",
+		system_info.nodename);
+	sock_puts(sock, buffer);
+    }
+    
+    close(sock);
+    
+    return 0;
+}
+
+/* End of cmd-server.c */
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/cmd.tar and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/cmd.tar differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpClass.pl kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpClass.pl
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpClass.pl	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpClass.pl	1999-12-07 20:57:42.000000000 -0500
@@ -0,0 +1,44 @@
+#!/usr/bin/perl -w
+#
+# Dump a java .class file to stdout
+#
+
+#
+# Copyright (c) 1999 University of Utah CSL.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# Written by Patrick Tullmann <tullmann at cs.utah.edu>
+#
+
+use JavaClass;
+
+# Control the verbosity of &printClass()
+$JavaClass::detailedFields = 0;
+$JavaClass::detailedMethods = 0;
+
+## Parse the command line
+my $classFile = shift  || &usage();
+
+## Read/parse the class file
+my $class = &JavaClass::readClass($classFile);
+
+## Print the class filea
+&JavaClass::printClass($class);
+
+###
+###
+###
+
+sub usage() {
+  print STDOUT "Usage:\n";
+  print STDOUT "    dumpClass.pl <ClassFile>\n\n";
+  print STDOUT "    Note that '.class' will be appended if it is not specified in the file name.\n";
+
+  exit 11;
+}
+
+#eof
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/HiChico.class and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/HiChico.class differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.DPD kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.DPD
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.DPD	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.DPD	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,19 @@
+# Symantec IDDE generated .dpd file. V: 7200
+util\attributeinfo.class: \
+	util\attributeinfo.java \
+	util\ConstantPoolInfo.java 
+util\constantpoolinfo.class: \
+	util\constantpoolinfo.java 
+util\classfile.class: \
+	util\classfile.java \
+	util\FieldInfo.java 
+util\fieldinfo.class: \
+	util\fieldinfo.java \
+	util\MethodInfo.java 
+util\methodinfo.class: \
+	util\methodinfo.java \
+	util\ConstantPoolInfo.java \
+	util\AttributeInfo.java 
+dumpclass.class: \
+	dumpclass.java \
+	util\ClassFile.java 
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.MAK kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.MAK
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.MAK	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.MAK	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,90 @@
+ORIGIN		= Symantec Café
+ORIGIN_VER	= Version 7.22
+VERSION		= DEBUG
+
+!IFDEF SUB_DEBUG
+DEBUG		= $(SUB_DEBUG)
+NDEBUG		= !$(SUB_DEBUG)
+!ELSE
+DEBUG		= 1
+NDEBUG		= 0
+!ENDIF
+
+PROJ		= dumpclass
+APPTYPE		= JAVA CONSOLE
+PROJTYPE	= class
+
+JAVAC		= sj
+MAKE		= SMAKE
+LNK		= LINK
+
+
+HEADERS		= 
+!IF $(DEBUG)
+OUTPUTDIR	= .
+CREATEOUTPUTDIR	=
+TARGETDIR	= .
+CREATETARGETDIR	=
+
+CFLAGS		=  -g 
+DEFINES		= 
+!ELSE
+OUTPUTDIR	= .
+CREATEOUTPUTDIR	=
+TARGETDIR	= .
+CREATETARGETDIR	=
+
+CFLAGS		=  -O 
+DEFINES		= 
+!ENDIF
+
+MFLAGS		= MASTERPROJ=$(PROJ) 
+DEBUGGERFLAGS	=  
+PAR		= PROJS BATS OBJS
+
+INCLUDES	= -classpath .;C:\Cafe\JAVA\LIB\CLASSES.ZIP;d:\temp
+
+
+
+OBJS		= util\AttributeInfo.class util\ClassFile.class util\ConstantPoolInfo.class  \
+		util\FieldInfo.class util\MethodInfo.class dumpclass.class 
+
+BATS		= 
+
+.SUFFIXES: .JAVA .CLASS 
+
+.JAVA.CLASS:
+	$(JAVAC) $(CFLAGS) $(INCLUDES) $*.java
+
+
+
+all:	noteout createdir $(PRECOMPILE) $(OBJS) $(POSTCOMPILE) _done
+
+
+all2:	createdir $(PRECOMPILE) $(OBJS) $(POSTCOMPILE) _done
+
+noteout:
+	REM Output to $(OUTPUTDIR)
+
+createdir:
+	$(CREATEOUTPUTDIR)
+	$(CREATETARGETDIR)
+	
+_done:
+		REM  Project is up to date
+
+buildall:	clean	all
+
+
+clean:
+		-del $(TARGETDIR)\$$SCW$$.$(PROJTYPE)
+		-del $(TARGETDIR)\$(PROJ).CLE
+		-del dumpclass.dpd
+		-del $(OBJS)
+
+
+
+!IF EXIST (dumpclass.dpd)
+!INCLUDE dumpclass.dpd
+!ENDIF
+
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.OPN and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.OPN differ
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.class and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.class differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.java kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.java
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.java	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.java	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * dumpclass.java
+ *
+ * Uses the class file decoders in util to dump out a
+ * class file.
+ * Written : 22 - May - 1996 by Chuck McManis
+ */
+
+import util.*;
+import java.io.*;
+
+public class dumpclass {
+    public static void main(String args[]) {
+        FileInputStream fis;
+        ClassFile cf = new ClassFile();
+        cf.debug = true;
+
+
+	/* Try to open arg[0] as the name of a .class file */
+        try { fis = new FileInputStream(args[0]); }
+        catch (IOException e) { fis = null; }
+
+        try {
+	    /* Read in the .class file (can throw various things) */
+            if (! cf.read(fis)) {
+                System.out.println("Couldn't load "+args[0]+", press a key.");
+		int c = System.in.read(); /* this is for Symantec */
+		throw new Exception("File not parsed.");
+            }
+
+            cf.display(System.out);
+	    int c = System.in.read(); /* Keep screen open */
+        } catch (Exception e) { }
+    }
+}
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.prj kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.prj
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.prj	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.prj	1999-12-07 20:57:42.000000000 -0500
@@ -0,0 +1,13 @@
+82570
+D:\TEMP\dumpclass.prj
+dumpclass.OPN
+novcs
+dumpclass.DEF
+24
+0
+0 0 0 0 0 "util\AttributeInfo.java" "util\AttributeInfo.class"
+0 0 0 0 0 "util\ClassFile.java" "util\ClassFile.class"
+0 0 0 0 0 "util\ConstantPoolInfo.java" "util\ConstantPoolInfo.class"
+0 0 0 0 0 "util\FieldInfo.java" "util\FieldInfo.class"
+0 0 0 0 0 "util\MethodInfo.java" "util\MethodInfo.class"
+0 0 0 0 0 "dumpclass.java" ""
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.tar and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/dumpclass.tar differ
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/AttributeInfo.class and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/AttributeInfo.class differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/AttributeInfo.java kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/AttributeInfo.java
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/AttributeInfo.java	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/AttributeInfo.java	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,100 @@
+/*
+ * @(#)AttributeInfo.java	1.4 95/08/16 Chuck McManis
+ *
+ * Copyright (c) 1996 Chuck McManis, All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies.
+ *
+ * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
+ * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
+ * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+package util;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * This class defines the generic Attribute type for Java class files.
+ * It is a little bit smart in that for some Attributes it can display
+ * them intelligently if it also has access to the constant pool of the
+ * current class.
+ *
+ * @version 	1.4, 16 Aug 1995
+ * @author	Chuck McManis
+ * @see		ClassFile
+ */
+public class AttributeInfo {
+    ConstantPoolInfo	name;	// attribute name
+    byte		data[]; // attribute's contents
+
+    public AttributeInfo(ConstantPoolInfo newName, byte newData[]) {
+	name = name;
+	data = newData;
+    }
+
+    public AttributeInfo() {
+    }
+
+    public boolean read(DataInputStream di, ConstantPoolInfo pool[])
+	throws IOException {
+	int len;
+
+	name = pool[di.readShort()];
+	len = di.readInt();
+	data = new byte[len];
+	len  = di.read(data);
+	if (len != data.length)
+	    return (false);
+	return (true);
+    }
+
+    public void write(DataOutputStream dos, ConstantPoolInfo pool[])
+	throws IOException, Exception {
+	dos.writeShort(ConstantPoolInfo.indexOf(name, pool));
+	dos.writeInt(data.length);
+	dos.write(data, 0, data.length);
+    }
+
+    short indexFromBytes(byte a[]) {
+	return (short)(((a[0] << 8) & (0xff << 8)) |
+		       ((a[1] << 0) & (0xff << 0)));
+    }
+
+    public String toString(ConstantPoolInfo pool[]) {
+	StringBuffer x = new StringBuffer();
+	String type = name.toString();
+	ConstantPoolInfo item;
+
+	if (type.compareTo("ConstantValue") == 0) {
+	    item = pool[indexFromBytes(data)];
+	    return (item.toString());
+	} else if (type.compareTo("SourceFile") == 0) {
+	    item = pool[indexFromBytes(data)];
+	    return (item.toString());
+	} else {
+	    x.append(type+"<"+data.length+" bytes>");
+	}
+	return (x.toString());
+    }
+
+    public String toBoolean(ConstantPoolInfo pool[]) {
+	ConstantPoolInfo item = pool[indexFromBytes(data)];
+
+	if (item.intValue == 0)
+	    return ("= false");
+	return ("= true");
+    }
+
+    public String toString() {
+	return (name.toString()+" <"+data.length+" bytes>");
+    }
+}
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/ClassFile.class and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/ClassFile.class differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/ClassFile.java kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/ClassFile.java
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/ClassFile.java	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/ClassFile.java	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,787 @@
+/*
+ * ClassFile.java	Chuck McManis
+ *
+ * Copyright (c) 1996 Chuck McManis, All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies.
+ *
+ * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
+ * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
+ * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+package util;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * This class is used to manipulate Java class files in strange and
+ * mysterious ways.
+ *
+ * Usage it typically to feed it an array of bytes that are a class
+ * file, manipulate the class, then convert the class back into bytes,
+ * and feed the final result to <TT>defineClass()</TT>.
+ *
+ * @version 	1.6, 19 Aug 1995
+ * @author	Chuck McManis
+ * @see		AttributeInfo
+ * @see		ConstantPoolInfo
+ * @see		MethodInfo
+ * @see		FieldInfo
+ */
+
+public class ClassFile {
+    int			        magic;
+    short	        	majorVersion;
+    short       		minorVersion;
+    ConstantPoolInfo	constantPool[];
+    short		        accessFlags;
+    ConstantPoolInfo	thisClass;
+    ConstantPoolInfo	superClass;
+    ConstantPoolInfo	interfaces[];
+    FieldInfo		    fields[];
+    MethodInfo		    methods[];
+    AttributeInfo	    attributes[];
+    boolean		        isValidClass = false;
+
+    public static final int ACC_PUBLIC 		= 0x1;
+    public static final int ACC_PRIVATE 	= 0x2;
+    public static final int ACC_PROTECTED 	= 0x4;
+    public static final int ACC_STATIC 		= 0x8;
+    public static final int ACC_FINAL 		= 0x10;
+    public static final int ACC_SYNCHRONIZED 	= 0x20;
+    public static final int ACC_THREADSAFE 	= 0x40;
+    public static final int ACC_TRANSIENT 	= 0x80;
+    public static final int ACC_NATIVE 		= 0x100;
+    public static final int ACC_INTERFACE 	= 0x200;
+    public static final int ACC_ABSTRACT 	= 0x400;
+
+    public boolean debug = false;
+    public boolean dumpConstants = false;
+    /**
+     * Read a class from InputStream <i>in</i>.
+     */
+    public boolean read(InputStream in)
+	throws IOException {
+	    DataInputStream di = new DataInputStream(in);
+    	int	count;
+
+	    magic = di.readInt();
+	    if (magic != (int) 0xCAFEBABE) {
+	        return (false);
+	    }
+
+	    majorVersion = di.readShort();
+	    minorVersion = di.readShort();
+	    count = di.readShort();
+	    constantPool = new ConstantPoolInfo[count];
+	    if (debug)
+	        System.out.println("read(): Read header...");
+	    constantPool[0] = new ConstantPoolInfo();
+	    for (int i = 1; i < constantPool.length; i++) {
+	        constantPool[i] = new ConstantPoolInfo();
+	        if (! constantPool[i].read(di)) {
+		        return (false);
+	        }
+	        // These two types take up "two" spots in the table
+	        if ((constantPool[i].type == ConstantPoolInfo.LONG) ||
+	    	    (constantPool[i].type == ConstantPoolInfo.DOUBLE))
+		        i++;
+	    }
+
+	    /*
+	     * Update pointers in the constant table. This turns the
+ 	     * table into a real datastructure.
+ 	     *
+	     * TODO: Have it verify that the right arguments are present
+ 	     */
+	    for (int i = 1; i < constantPool.length; i++) {
+	        if (constantPool[i] == null)
+		        continue;
+	        if (constantPool[i].index1 > 0)
+	        	constantPool[i].arg1 = constantPool[constantPool[i].index1];
+	        if (constantPool[i].index2 > 0)
+		        constantPool[i].arg2 = constantPool[constantPool[i].index2];
+	    }
+
+	    if (dumpConstants) {
+	        for (int i = 1; i < constantPool.length; i++) {
+		        System.out.println("C"+i+" - "+constantPool[i]);
+	        }
+  	    }
+	    accessFlags = di.readShort();
+
+	    thisClass = constantPool[di.readShort()];
+	    superClass = constantPool[di.readShort()];
+	    if (debug)
+	        System.out.println("read(): Read class info...");
+
+    	/*
+ 	     * Identify all of the interfaces implemented by this class
+ 	     */
+	    count = di.readShort();
+	    if (count != 0) {
+	        if (debug)
+	            System.out.println("Class implements "+count+" interfaces.");
+	        interfaces = new ConstantPoolInfo[count];
+	        for (int i = 0; i < count; i++) {
+		        int iindex = di.readShort();
+		        if ((iindex < 1) || (iindex > constantPool.length - 1))
+		            return (false);
+		        interfaces[i] = constantPool[iindex];
+		        if (debug)
+		            System.out.println("I"+i+": "+interfaces[i]);
+	        }
+	    }
+	    if (debug)
+	        System.out.println("read(): Read interface info...");
+
+    	/*
+    	 * Identify all fields in this class.
+    	 */
+    	count = di.readShort();
+    	if (debug)
+    	    System.out.println("This class has "+count+" fields.");
+    	if (count != 0) {
+	        fields = new FieldInfo[count];
+	        for (int i = 0; i < count; i++) {
+        		fields[i] = new FieldInfo();
+	        	if (! fields[i].read(di, constantPool)) {
+		           return (false);
+        		}
+	        	if (debug)
+        		    System.out.println("F"+i+": "+
+			    		fields[i].toString(constantPool));
+	        }
+	    }
+	    if (debug)
+	        System.out.println("read(): Read field info...");
+
+	    /*
+      	 * Identify all the methods in this class.
+	     */
+	    count = di.readShort();
+	    if (count != 0) {
+	        methods = new MethodInfo[count];
+	        for (int i = 0; i < count; i++) {
+		        methods[i] = new MethodInfo();
+		        if (! methods[i].read(di, constantPool)) {
+		            return (false);
+	    	    }
+	    	    if (debug)
+	    	        System.out.println("M"+i+": "+methods[i].toString());
+	        }
+    	}
+	    if (debug)
+	        System.out.println("read(): Read method info...");
+
+
+    	/*
+    	 * Identify all of the attributes in this class
+    	 */
+    	count = di.readShort();
+    	if (count != 0) {
+    	    attributes = new AttributeInfo[count];
+    	    for (int i = 0; i < count; i++) {
+    		    attributes[i] = new AttributeInfo();
+    		    if (! attributes[i].read(di, constantPool)) {
+    		        return (false);
+    		    }
+    	    }
+    	}
+	    if (debug) {
+	        System.out.println("read(): Read attribute info...");
+	        System.out.println("done.");
+	    }
+	    isValidClass = true;
+	    return(true);
+    }
+
+    /**
+     * Write the class out as a stream of bytes to the output
+     * stream.
+     *
+     * Generally you will read a class file, manipulate
+     * it in some way, and then write it out again before passing
+     * it to <TT>defineClass</TT> in some class loader.
+     */
+    public void write(OutputStream out)
+	throws IOException, Exception {
+	    DataOutputStream dos = new DataOutputStream(out);
+
+	    if (! isValidClass) {
+	        throw new Exception("ClassFile::write() - Invalid Class");
+	    }
+
+	    dos.writeInt(magic);
+	    dos.writeShort(majorVersion);
+	    dos.writeShort(minorVersion);
+	    dos.writeShort(constantPool.length);
+	    for (int i = 1; i < constantPool.length; i++) {
+	        if (constantPool[i] != null)
+	            constantPool[i].write(dos, constantPool);
+	    }
+	    dos.writeShort(accessFlags);
+	    dos.writeShort(ConstantPoolInfo.indexOf(thisClass, constantPool));
+	    dos.writeShort(ConstantPoolInfo.indexOf(superClass, constantPool));
+
+	    if (interfaces == null) {
+	        dos.writeShort(0);
+	    } else {
+	        dos.writeShort(interfaces.length);
+	        for (int i = 0; i < interfaces.length; i++) {
+	            dos.writeShort(ConstantPoolInfo.indexOf(interfaces[i],
+							constantPool));
+	        }
+	    }
+
+	    if (fields == null) {
+	        dos.writeShort(0);
+	    } else {
+	        dos.writeShort(fields.length);
+	        for (int i = 0; i < fields.length; i++) {
+	            fields[i].write(dos, constantPool);
+	        }
+	    }
+
+	    if (methods == null) {
+	        dos.writeShort(0);
+	    } else {
+	        dos.writeShort(methods.length);
+	        for (int i = 0; i < methods.length; i++) {
+	            methods[i].write(dos, constantPool);
+	        }
+	    }
+
+	    if (attributes == null) {
+	        dos.writeShort(0);
+	    } else {
+	        dos.writeShort(attributes.length);
+	        for (int i = 0; i < attributes.length; i++) {
+	            attributes[i].write(dos, constantPool);
+	        }
+	    }
+    }
+
+    /**
+     * Returns a string that represents what the access flags
+     * are set for. So 0x14 returns "public final "
+     */
+    public static String accessString(short flags) {
+	    StringBuffer x = new StringBuffer();
+
+	    if ((flags & ACC_PUBLIC) != 0) {
+	        x.append("public ");
+	    }
+
+	    if ((flags & ACC_PRIVATE) != 0) {
+	        x.append("private ");
+	    }
+
+	    if ((flags & ACC_PROTECTED) != 0) {
+	        x.append("protected ");
+	    }
+
+	    if ((flags & ACC_STATIC) != 0) {
+	        x.append("static ");
+	    }
+
+	    if ((flags & ACC_FINAL) != 0) {
+	        x.append("final ");
+	    }
+
+	    if ((flags & ACC_SYNCHRONIZED) != 0) {
+	        x.append("synchronized ");
+	    }
+
+	    if ((flags & ACC_THREADSAFE) != 0) {
+	        x.append("threadsafe ");
+	    }
+
+	    if ((flags & ACC_TRANSIENT) != 0) {
+	        x.append("transient ");
+	    }
+
+	    if ((flags & ACC_NATIVE) != 0) {
+	        x.append("native ");
+	    }
+
+	    if ((flags & ACC_INTERFACE) != 0) {
+	        x.append("interface ");
+	    }
+
+	    if ((flags & ACC_ABSTRACT) != 0) {
+	        x.append("abstract ");
+	    }
+
+	    return (x.toString());
+    }
+
+    /**
+     * Takes a type signature and a string representing a variable name
+     * and returns a declaration for that variable name.
+     *
+     * For example, passing this the strings "[B" and "myArray" will
+     * return the string "byte myArray[]"
+     */
+    public static String typeString(String typeString, String varName) {
+	    int isArray = 0;
+	    int	ndx = 0;
+	    StringBuffer x = new StringBuffer();
+
+	    while (typeString.charAt(ndx) == '[') {
+	        isArray++;
+	        ndx++;
+	    }
+
+	    switch (typeString.charAt(ndx)) {
+	        case 'B' :
+		        x.append("byte ");
+		        break;
+	        case 'C' :
+		        x.append("char ");
+		        break;
+	        case 'D' :
+		        x.append("double ");
+		        break;
+	        case 'F' :
+		        x.append("float ");
+		        break;
+	        case 'I' :
+		        x.append("int ");
+		        break;
+	        case 'J' :
+		        x.append("long ");
+		        break;
+	        case 'L' :
+		        for (int i = ndx+1; i < typeString.indexOf(';'); i++) {
+		            if (typeString.charAt(i) != '/')
+			            x.append(typeString.charAt(i));
+		            else
+			        x.append('.');
+		        }
+		        x.append(" ");
+		        break;
+	        case 'V':
+		        x.append("void ");
+		        break;
+	        case 'S' :
+		        x.append("short ");
+		        break;
+	        case 'Z' :
+		        x.append("boolean ");
+		        break;
+	    }
+	    x.append(varName);
+	    while (isArray > 0) {
+	        x.append("[]");
+	        isArray--;
+	    }
+	    return (x.toString());
+    }
+
+    /**
+     * Returns the next signature from a string of concatenated signatures.
+     * For example if the signature was "[BII", this method would return
+     * "II"
+     */
+    public static String nextSig(String sig) {
+	    int	ndx = 0;
+	    String 	x;
+
+	    while (sig.charAt(ndx) == '[')
+	        ndx++;
+
+	    if (sig.charAt(ndx) == 'L') {
+	        while (sig.charAt(ndx) != ';')
+		        ndx++;
+	    }
+	    ndx++;
+	    x =  (sig.substring(ndx));
+	    return (x);
+    }
+
+    /**
+     * Print the name of a class in "canonical form"
+     */
+    private String printClassName(String s) {
+	    StringBuffer x;
+
+	    if (s.charAt(0) == '[') {
+	        return(typeString(s, ""));
+	    }
+
+	    x = new StringBuffer();
+	    for (int j = 0; j < s.length(); j++) {
+	        if (s.charAt(j) == '/')
+	    	    x.append('.');
+	        else
+	    	    x.append(s.charAt(j));
+	    }
+	    return (x.toString());
+
+    }
+
+    public String getClassName() {
+    	return printClassName(thisClass.arg1.strValue);
+    }
+
+    /**
+     * The boring version of display().
+     */
+    public String toString() {
+	    return("Class File (Version "+majorVersion+"."+minorVersion+
+	        ") for class "+thisClass.arg1);
+    }
+
+    /**
+     * Write out a text version of this class.
+     */
+    public void display(PrintStream ps)
+	throws Exception {
+	    int i;
+	    String myClassName;
+	    String mySuperClassName;
+	    String packageName = null;
+
+	    if (! isValidClass) {
+	        ps.println("Not a valid class");
+	    }
+
+	    myClassName = printClassName(thisClass.arg1.strValue);
+	    mySuperClassName = printClassName(superClass.arg1.strValue);
+	    if (myClassName.indexOf('.') > 0) {
+	        packageName =
+		        myClassName.substring(0, myClassName.lastIndexOf('.'));
+	        myClassName = myClassName.substring(myClassName.lastIndexOf('.')+1);
+	        ps.println("package "+packageName+"\n");
+	    }
+
+	    for (i = 1; i < constantPool.length; i++) {
+	        if (constantPool[i] == null)
+		        continue;
+	        if ((constantPool[i] == thisClass) ||
+		        (constantPool[i] == superClass))
+		        continue;
+	        if (constantPool[i].type == ConstantPoolInfo.CLASS) {
+		        String s = constantPool[i].arg1.strValue;
+		            if (s.charAt(0) == '[')
+		                continue;
+		        s = printClassName(constantPool[i].arg1.strValue);
+		        if ((packageName != null) && (s.startsWith(packageName)))
+		            continue;
+		        ps.println("import "+printClassName(s)+";");
+	        }
+	    }
+	    ps.println();
+	    ps.println("/*");
+	    DataInputStream dis;
+	    ConstantPoolInfo cpi;
+
+	    if (attributes != null) {
+	        ps.println(" * This class has "+attributes.length+
+					" optional class attributes.");
+	        ps.println(" * These attributes are: ");
+	        for (i = 0; i < attributes.length; i++) {
+	            String attrName = attributes[i].name.strValue;
+	            dis = new DataInputStream(new ByteArrayInputStream(attributes[i].data));
+
+	            ps.println(" * Attribute "+(i+1)+" is of type "+attributes[i].name);
+	            if (attrName.compareTo("SourceFile") == 0) {
+		            cpi = null;
+		            try {
+		                cpi = constantPool[dis.readShort()];
+		            } catch (IOException e) { }
+		            ps.println(" *	SourceFile : "+cpi);
+	            } else {
+		            ps.println(" *	TYPE ("+attrName+")");
+	            }
+            }
+	    } else {
+	        ps.println(" * This class has NO optional class attributes.");
+	    }
+	    ps.println(" */\n");
+	    ps.print(accessString(accessFlags)+"class "+myClassName+" extends "+
+		    mySuperClassName);
+	    if (interfaces != null) {
+	        ps.print(" implements ");
+	        for (i = 0; i < interfaces.length - 1; i++) {
+	    	    ps.print(interfaces[i].arg1.strValue+", ");
+	        }
+	        ps.print(interfaces[interfaces.length-1].arg1.strValue);
+	    }
+	    ps.println(" {\n");
+	    if (fields != null) {
+	        ps.println("/* Instance Variables */");
+	        for (i = 0; i < fields.length; i++) {
+	            ps.println("    "+fields[i].toString(constantPool)+";");
+	        }
+	    }
+
+	    if (methods != null) {
+	        ps.println("\n/* Methods */");
+	        for (i = 0; i < methods.length; i++) {
+	            ps.println("    "+methods[i].toString(myClassName));
+	        }
+	    }
+	    ps.println("\n}");
+    }
+
+    public ConstantPoolInfo getConstantRef(short index) {
+	    return (constantPool[index]);
+    }
+
+    /**
+     * Add a single constant pool item and return its index.
+     * If the item is already in the pool then the index of
+     * the <i>preexisting</i> item is returned. Thus you cannot
+     * assume that a pointer to your item will be useful.
+     */
+    public short addConstantPoolItem(ConstantPoolInfo item)
+	throws Exception {
+	    ConstantPoolInfo newConstantPool[];
+	    ConstantPoolInfo cp;
+
+	    cp = item.inPool(constantPool);
+	    if (cp != null)
+	        return ConstantPoolInfo.indexOf(cp, constantPool);
+
+	    newConstantPool = new ConstantPoolInfo[constantPool.length+1];
+	    for (int i = 1; i < constantPool.length; i++) {
+	        newConstantPool[i] = constantPool[i];
+	    }
+	    newConstantPool[constantPool.length] = item;
+	    constantPool = newConstantPool;
+	    return ConstantPoolInfo.indexOf(item, constantPool);
+    }
+
+    /**
+     * Add some items to the constant pool. This is used to add new
+     * items to the constant pool. The items references in arg1 and
+     * arg2 are expected to be valid pointers (if necessary). Pruning
+     * is done to prevent adding redundant items to the list and to
+     * preserve string space.
+     *
+     * The algorithm is simple, first identify pool items containing
+     * constants in the list of items to be added that are already
+     * in the constant pool. If any are found to already exist, change
+     * the pointers in the non-constant items to point to the ones in
+     * the pool rather than the ones in the list. Next check to see
+     * if any of the non-constant items are already in the pool and
+     * if so fix up the others in the list to point to the ones in
+     * the pool. Finally, add any items (there must be at least one)
+     * from the item list that aren't already in the pool, all of
+     * the pointers will already be fixed.
+     *
+     * NOTE: Since constants in the constant pool may be referenced
+     * <i>inside</i> the opaque portion of attributes the constant
+     * table cannot be re-ordered, only extended.
+     */
+    public void addConstantPoolItems(ConstantPoolInfo items[]) {
+	    ConstantPoolInfo newArg;
+	    ConstantPoolInfo newConstantPool[];
+	    boolean delete[] = new boolean[items.length];
+
+	    /* Step one, look for matching constants */
+	    for (int j = 0; j < items.length; j++) {
+	        if ( (items[j].type == ConstantPoolInfo.ASCIZ) ||
+	             (items[j].type == ConstantPoolInfo.UNICODE) ||
+	             (items[j].type == ConstantPoolInfo.INTEGER) ||
+	             (items[j].type == ConstantPoolInfo.LONG) ||
+	             (items[j].type == ConstantPoolInfo.FLOAT) ||
+	             (items[j].type == ConstantPoolInfo.DOUBLE)) {
+
+		    // Look for this item in the constant pool
+		    delete[j] = false;
+		    newArg = items[j].inPool(constantPool);
+		    if (newArg != null) {
+		        // replace the references in our list.
+		        delete[j] = true;	// mark it for deletion
+		        for (int i = 0; i < items.length; i++) {
+			        if (items[i].arg1 == items[j])
+			            items[i].arg1 = newArg;
+			            if (items[i].arg2 == items[j])
+			                items[i].arg2 = newArg;
+		            }
+		        }
+	        }
+	    }
+
+    	/* Step two : now match everything else */
+    	for (int j = 0; j < items.length; j++) {
+    	    if ( (items[j].type == ConstantPoolInfo.CLASS) ||
+	             (items[j].type == ConstantPoolInfo.FIELDREF) ||
+	             (items[j].type == ConstantPoolInfo.METHODREF) ||
+	             (items[j].type == ConstantPoolInfo.STRING) ||
+	             (items[j].type == ConstantPoolInfo.INTERFACE) ||
+	             (items[j].type == ConstantPoolInfo.NAMEANDTYPE)) {
+
+		    // Look for this item in the constant pool
+		    delete[j] = false;
+		    newArg = items[j].inPool(constantPool);
+		    if (newArg != null) {
+		        // replace the references in our list.
+		        delete[j] = true;	// mark it for deletion
+		        for (int i = 0; i < items.length; i++) {
+			        if (items[i].arg1 == items[j])
+			            items[i].arg1 = newArg;
+			            if (items[i].arg2 == items[j])
+			                items[i].arg2 = newArg;
+		            }
+		        }
+	        }
+	    }
+
+    	/* Step three: Add the surviving items to the pool */
+    	int count = 0;
+    	for (int i = 0; i < items.length; i++) {
+    	    if (! delete[i])
+        		count++;
+	    }
+    	// count == # of survivors
+    	newConstantPool = new ConstantPoolInfo[constantPool.length + count];
+    	for (int i = 1; i < constantPool.length; i++) {
+	        newConstantPool[i] = constantPool[i];
+	    }
+    	// newConstantPool == existing constantPool
+
+    	int ndx = 0;
+    	for (int i = constantPool.length; i < newConstantPool.length; i++) {
+	        while (delete[ndx])
+        		ndx++;
+    	    newConstantPool[i] = items[ndx];
+	        ndx++;
+	    }
+    	// newConstantPool == existing + new
+	    constantPool = newConstantPool;
+	    // all done.
+    }
+
+    /**
+     * Add a new optional class Attribute.
+     *
+     * Items is an array of constant pool items that are first added
+     * to the constant pool. At a minimum items[0] must be an ASCIZ
+     * item with the name of the attribute. If the body of the attribute
+     * references constant pool items these should be in the item list
+     * as well.
+     */
+    public void addAttribute(AttributeInfo newAttribute) {
+
+	    if (attributes == null) {
+	        attributes = new AttributeInfo[1];
+	        attributes[0] = newAttribute;
+	    } else {
+	        AttributeInfo newAttrList[] = new AttributeInfo[1+attributes.length];
+	        for (int i = 0; i < attributes.length; i++) {
+		        newAttrList[i] = attributes[i];
+	        }
+	        newAttrList[attributes.length] = newAttribute;
+	        attributes = newAttrList;
+	    }
+    }
+
+    /**
+     * Return the attribute named 'name' from the class file.
+     */
+    public AttributeInfo getAttribute(String name) {
+	    if (attributes == null)
+	        return null;
+	    for (int i = 0; i < attributes.length; i++) {
+	        if (name.compareTo(attributes[i].name.toString()) == 0)
+		    return attributes[i];
+	    }
+	    return (null);
+    }
+
+    /**
+     * Return a constant pool item from this class. (note does fixup
+     * of indexes to facilitate extracting nested or linked items.
+     */
+    public ConstantPoolInfo getConstantPoolItem(short index)
+	throws Exception {
+	    ConstantPoolInfo cp;
+
+	    if ((index <= 0) || (index > (constantPool.length - 1)))
+	        return (null);
+	    cp = constantPool[index];
+	    if (cp.arg1 != null)
+	        cp.index1 = ConstantPoolInfo.indexOf(cp.arg1, constantPool);
+	    if (cp.arg2 != null)
+	        cp.index2 = ConstantPoolInfo.indexOf(cp.arg2, constantPool);
+	    return cp;
+    }
+
+    /* Examples of mysterious things you can do to a class file before
+     * writing it back out. These methods are not currently functional.
+     * (that would be too easy :-)
+     */
+
+    /**
+     * Map occurences of class <i>oldClass</i> to occurrences of
+     * class <i>newClass</i>. This method is used to retarget
+     * accesses to one class, seamlessly to another.
+     *
+     * The format for the class name is slash (/) separated so
+     * the class <tt>util.ClassFile</tt> would be represented as
+     * <tt>util/ClassFile</tt>
+     */
+    public void mapClass(String oldClass, String newClass) {
+	    if (debug)
+	        System.out.println("Mapping class name "+oldClass+" ==> "+
+			    newClass+" for class "+thisClass.arg1);
+	    for (int i = 0; i < constantPool.length; i++) {
+	        if (constantPool[i].type == ConstantPoolInfo.CLASS) {
+		        String cname = constantPool[i].arg1.strValue;
+		        if (cname.compareTo(oldClass) == 0) {
+		            if (debug) {
+		                System.out.println("REPLACING "+cname+" with "+newClass);
+		            }
+		            constantPool[i].arg1.strValue = newClass;
+		        }
+	        }
+	    }
+    }
+
+    /**
+     * Map occurences of package <i>oldPackage</i> to package
+     * <i>newPackage</i>.
+     *
+     * The format for the package name is slash (/) separated so
+     * the package <tt>java.util</tt> would be represented as
+     * <tt>java/util</tt>
+     */
+     public void mapPackage(String oldPackage, String newPackage) {
+	    for (int i = 0; i < constantPool.length; i++) {
+	        if (constantPool[i].type == ConstantPoolInfo.CLASS) {
+		        String cname = constantPool[i].arg1.strValue;
+		        if (cname.startsWith(oldPackage)) {
+		            constantPool[i].arg1.strValue = newPackage +
+			        cname.substring(cname.lastIndexOf('/'));
+		        }
+	        }
+	    }
+    }
+
+    /**
+     * Delete a named method from this class. This method is used
+     * to excise specific methods from the loaded class. The actual
+     * method code remains, however the method signature is deleted
+     * from the constant pool. If this method is called by a class
+     * the exception IncompatibleClassChangeException is generated
+     * by the runtime.
+     */
+    public void deleteMethod(String name, String signature) {
+	    for (int i = 0; i < constantPool.length; i++) {
+	        if (constantPool[i].type == ConstantPoolInfo.CLASS) {
+	        }
+	    }
+    }
+}
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/ConstantPoolInfo.class and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/ConstantPoolInfo.class differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/ConstantPoolInfo.java kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/ConstantPoolInfo.java
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/ConstantPoolInfo.java	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/ConstantPoolInfo.java	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,344 @@
+/*
+ * @(#)ConstantPoolInfo.java	1.5 95/08/16 Chuck McManis
+ *
+ * Copyright (c) 1996 Chuck McManis, All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies.
+ *
+ * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
+ * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
+ * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+package util;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * This class defines an entry in the constant pool for a Java class.
+ * The class file is primarily composed of ConstantPool entries and
+ * manipulation is done by modifying those entries.
+ *
+ * @version 	1.5, 16 Aug 1995
+ * @author	Chuck McManis
+ * @see		ClassFile
+ */
+
+public class ConstantPoolInfo{
+    int	type;			// type of this item
+    String name; 		// String for the type
+    ConstantPoolInfo  arg1;	// index to first argument
+    ConstantPoolInfo  arg2;	// index to second argument
+    short index1, index2;
+    String 	strValue; 		// ASCIZ String value
+    int		intValue;
+    long	longValue;
+    float	floatValue;
+    double	doubleValue;
+
+    public static final int CLASS = 7;
+    public static final int FIELDREF = 9;
+    public static final int METHODREF = 10;
+    public static final int STRING = 8;
+    public static final int INTEGER = 3;
+    public static final int FLOAT = 4;
+    public static final int LONG = 5;
+    public static final int DOUBLE = 6;
+    public static final int INTERFACE = 11;
+    public static final int NAMEANDTYPE = 12;
+    public static final int ASCIZ = 1;
+    public static final int UNICODE = 2;
+
+
+    /**
+     * Construct a new ConstantPoolInfo object that is of type ASCIZ
+     */
+    public ConstantPoolInfo(String value) {
+	index1 = -1;
+	index2 = -1;
+	arg1 = null;
+	arg2 = null;
+	type = ASCIZ;
+	strValue = value;
+    }
+
+    /**
+     * Construct a new ConstantPoolInfo object that is of type INTEGER
+     */
+    public ConstantPoolInfo(int value) {
+	index1 = -1;
+	index2 = -1;
+	arg1 = null;
+	arg2 = null;
+	type = INTEGER;
+	intValue = value;
+    }
+
+    /**
+     * Construct a new ConstantPoolInfo object that is of type FLOAT
+     */
+    public ConstantPoolInfo(float value) {
+	index1 = -1;
+	index2 = -1;
+	arg1 = null;
+	arg2 = null;
+	type = FLOAT;
+	floatValue = value;
+    }
+
+    /**
+     * Construct a new ConstantPoolInfo object that is of type LONG
+     */
+    public ConstantPoolInfo(long value) {
+	index1 = -1;
+	index2 = -1;
+	arg1 = null;
+	arg2 = null;
+	type = LONG;
+	longValue = value;
+    }
+
+    /**
+     * Construct a new ConstantPoolInfo object that is of type DOUBLE
+     */
+    public ConstantPoolInfo(double value) {
+	index1 = -1;
+	index2 = -1;
+	arg1 = null;
+	arg2 = null;
+	type = DOUBLE;
+	doubleValue = value;
+    }
+
+    /**
+     * Generic constructor
+     */
+    public ConstantPoolInfo() {
+	index1 = -1;
+	index2 = -1;
+	arg1 = null;
+	arg2 = null;
+	type = -1;
+    }
+
+    /**
+     * return the type of this constant pool item.
+     */
+    public int isType() {
+	return (type);
+    }
+
+    public boolean read(DataInputStream dis)
+	throws IOException {
+	int	len;
+	char	c;
+
+	type = dis.readByte();
+	switch (type) {
+	    case CLASS:
+		name = "Class";
+		index1 = dis.readShort();
+		index2 = -1;
+		break;
+	    case FIELDREF:
+		name = "Field Reference";
+		index1 = dis.readShort();
+		index2 = dis.readShort();
+		break;
+	    case METHODREF:
+		name = "Method Reference";
+		index1 = dis.readShort();
+		index2 = dis.readShort();
+		break;
+	    case INTERFACE:
+		name = "Interface Method Reference";
+		index1 = dis.readShort();
+		index2 = dis.readShort();
+		break;
+	    case NAMEANDTYPE:
+		name = "Name and Type";
+		index1 = dis.readShort();
+		index2 = dis.readShort();
+		break;
+	    case STRING:
+		name = "String";
+		index1 = dis.readShort();
+		index2 = -1;
+		break;
+	    case INTEGER:
+		name = "Integer";
+		intValue = dis.readInt();
+		break;
+	    case FLOAT:
+		name = "Float";
+		floatValue = dis.readFloat();
+		break;
+	    case LONG:
+		name = "Long";
+		longValue = dis.readLong();
+		break;
+	    case DOUBLE:
+		name = "Double";
+		doubleValue = dis.readDouble();
+		break;
+	    case ASCIZ:
+	    case UNICODE:
+		if (type == ASCIZ)
+		    name = "ASCIZ";
+		else
+		    name = "UNICODE";
+
+		StringBuffer xxBuf = new StringBuffer();
+
+		len = dis.readShort();
+		while (len > 0) {
+		    c = (char) (dis.readByte());
+		    xxBuf.append(c);
+		    len--;
+		}
+		strValue = xxBuf.toString();
+		break;
+	    default:
+		System.out.println("Warning bad type.");
+	}
+	return (true);
+    }
+
+    public void write(DataOutputStream dos, ConstantPoolInfo pool[])
+	throws IOException, Exception {
+	dos.write(type);
+	switch (type) {
+	    case CLASS:
+	    case STRING:
+		dos.writeShort(indexOf(arg1, pool));
+		break;
+	    case FIELDREF:
+	    case METHODREF:
+	    case INTERFACE:
+	    case NAMEANDTYPE:
+		dos.writeShort(indexOf(arg1, pool));
+		dos.writeShort(indexOf(arg2, pool));
+		break;
+	    case INTEGER:
+		dos.writeInt(intValue);
+		break;
+	    case FLOAT:
+		dos.writeFloat(floatValue);
+		break;
+	    case LONG:
+		dos.writeLong(longValue);
+		break;
+	    case DOUBLE:
+		dos.writeDouble(doubleValue);
+		break;
+	    case ASCIZ:
+	    case UNICODE:
+		dos.writeShort(strValue.length());
+		dos.writeBytes(strValue);
+		break;
+	    default:
+		throw new Exception("ConstantPoolInfo::write() - bad type.");
+	}
+    }
+
+    public String toString() {
+	StringBuffer s;
+
+	if (type == ASCIZ) {
+	    return(strValue);
+	}
+
+	if (type == INTEGER) {
+	    return("= "+intValue);
+	}
+
+	if (type == LONG) {
+	    return("= "+longValue);
+	}
+
+	if (type == FLOAT) {
+	    return("= "+floatValue);
+	}
+
+	if (type == DOUBLE) {
+	    return("= "+doubleValue);
+	}
+
+	s = new StringBuffer();
+	s.append(name);
+	s.append(":");
+	if (arg1 != null)
+	    s.append(arg1.toString());
+	else if (index1 != -1)
+	    s.append("I1["+index1+"], ");
+	if (arg2 != null)
+	    s.append(arg2.toString());
+	else if (index2 != -1)
+	    s.append("I2["+index2+"], ");
+	return (s.toString());
+    }
+
+    public static short indexOf(ConstantPoolInfo item,
+					ConstantPoolInfo pool[])
+	throws Exception {
+	for (int i = 0; i < pool.length; i++) {
+	    if (item == pool[i])
+		return (short) i;
+	}
+	throw new Exception("ConstantPoolInfo:: indexOf() - item not in pool.");
+    }
+
+    /**
+     * Returns true if these constant pool items are identical.
+     */
+    public boolean isEqual(ConstantPoolInfo cp) {
+	if (cp == null)
+	    return false;
+
+	if (cp.type != type)
+	    return (false);
+	switch (cp.type) {
+	    case CLASS:
+	    case STRING:
+		return (arg1 == cp.arg1);
+	    case FIELDREF:
+	    case METHODREF:
+	    case INTERFACE:
+	    case NAMEANDTYPE:
+		return ((arg1 == cp.arg1) && (arg2 == cp.arg2));
+	    case INTEGER:
+		return (cp.intValue == intValue);
+	    case FLOAT:
+		return (cp.floatValue == floatValue);
+	    case LONG:
+		return (cp.longValue == longValue);
+	    case DOUBLE:
+		return (cp.doubleValue == doubleValue);
+	    case ASCIZ:
+	    case UNICODE:
+		return (cp.strValue.compareTo(strValue) == 0);
+	}
+	return (false);
+    }
+
+    /**
+     * Returns the reference to the constant pool item that is
+     * already in pool, that matches this one.
+     */
+    public ConstantPoolInfo inPool(ConstantPoolInfo pool[]) {
+	for (int i = 1; i < pool.length; i++) {
+	    if (isEqual(pool[i]))
+		return (pool[i]);
+	}
+	return null;
+    }
+
+}
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/FieldInfo.class and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/FieldInfo.class differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/FieldInfo.java kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/FieldInfo.java
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/FieldInfo.java	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/FieldInfo.java	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,104 @@
+/*
+ * @(#)FieldInfo.java	1.3 95/08/16 Chuck McManis
+ *
+ * Copyright (c) 1996 Chuck McManis, All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies.
+ *
+ * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
+ * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
+ * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+package util;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * This class defines a FieldInfo in the class file. Fields are used to
+ * describe instance variables in a class. The toString() method is
+ * augmented by a version that takes an array of ConstantPoolInfo
+ * objects (a constant pool). When a constant pool is available the
+ * toString() method generates a declaration for the field as it would
+ * appear in Java source.
+ *
+ * @version 	1.3, 16 Aug 1995
+ * @author	Chuck McManis
+ * @see		ClassFile
+ */
+
+public class FieldInfo {
+    short		accessFlags;
+    ConstantPoolInfo	name;
+    ConstantPoolInfo	signature;
+    AttributeInfo	attributes[];
+
+    public boolean read(DataInputStream di, ConstantPoolInfo pool[])
+	throws IOException {
+	int	count;
+
+	accessFlags = di.readShort();
+	name = pool[di.readShort()];
+	signature = pool[di.readShort()];
+	count = di.readShort();
+	if (count != 0) {
+	    attributes = new AttributeInfo[count];
+	    for (int i = 0; i < count; i++) {
+		attributes[i] = new AttributeInfo();
+		if (! attributes[i].read(di, pool))
+		    return (false);
+	    }
+	}
+	return (true);
+    }
+
+    public void write(DataOutputStream dos, ConstantPoolInfo pool[])
+	throws IOException, Exception {
+	dos.writeShort(accessFlags);
+	dos.writeShort(ConstantPoolInfo.indexOf(name, pool));
+	dos.writeShort(ConstantPoolInfo.indexOf(signature, pool));
+	if (attributes == null) {
+	    dos.writeShort(0);
+	} else {
+	    dos.writeShort(attributes.length);
+	    for (int i = 0; i < attributes.length; i++) {
+	    	attributes[i].write(dos, pool);
+	    }
+	}
+    }
+
+    public String toString() {
+	StringBuffer x = new StringBuffer();
+
+	x.append(ClassFile.accessString(accessFlags));
+	x.append(ClassFile.typeString(signature.toString(), name.toString()));
+	if (attributes != null) {
+	    x.append(" = "+attributes[0].toString());
+	}
+	return (x.toString());
+    }
+
+    public String toString(ConstantPoolInfo pool[]) {
+	StringBuffer x = new StringBuffer();
+	String	mytype;
+
+	x.append(ClassFile.accessString(accessFlags));
+	mytype = ClassFile.typeString(signature.toString(), name.toString());
+	x.append(mytype);
+	if (attributes != null) {
+	    if (mytype.startsWith("boolean")) {
+		x.append(" "+attributes[0].toBoolean(pool));
+	    } else
+	        x.append(" "+attributes[0].toString(pool));
+	}
+	return (x.toString());
+    }
+}
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/MethodInfo.class and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/MethodInfo.class differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/MethodInfo.java kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/MethodInfo.java
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/dumpclass/util/MethodInfo.java	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/dumpclass/util/MethodInfo.java	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,137 @@
+/*
+ * @(#)MethodInfo.java	1.4 95/08/16 Chuck McManis
+ *
+ * Copyright (c) 1996 Chuck McManis, All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies.
+ *
+ * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
+ * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
+ * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+package util;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * This class describes a Method as it is stored in the class file.
+ * The attribute associated with method is the code that actually implements
+ * the method. Since we don't need to manipulate the byte codes directly
+ * we leave them as an opaque chunk in the attributes[] array. References
+ * in the code are all references into the constant table so when we are
+ * modifing a class to use a different object we needn't get into the code
+ * level.
+ *
+ * @version 	1.4, 16 Aug 1995
+ * @author	Chuck McManis
+ * @see		ClassFile
+ */
+
+public class MethodInfo {
+    short 		accessFlags;
+    ConstantPoolInfo 	name;
+    ConstantPoolInfo 	signature;
+    AttributeInfo	attributes[];
+
+    /**
+     * Read a method_info from the data stream.
+     */
+    public boolean read(DataInputStream di, ConstantPoolInfo pool[])
+	throws IOException {
+	int	count;
+
+	accessFlags = di.readShort();
+	name = pool[di.readShort()];
+	signature = pool[di.readShort()];
+	count = di.readShort();
+	if (count != 0) {
+	    attributes = new AttributeInfo[count];
+	    for (int i = 0; i < count; i++) {
+		attributes[i] = new AttributeInfo(); // "code"
+		if (! attributes[i].read(di, pool)) {
+		    return (false);
+		}
+	    }
+	}
+	return (true);
+    }
+
+    /**
+     * Write out a method_info, do constant table fixups on the write.
+     */
+    public void write(DataOutputStream dos, ConstantPoolInfo pool[])
+	throws IOException, Exception {
+	dos.writeShort(accessFlags);
+	dos.writeShort(ConstantPoolInfo.indexOf(name, pool));
+	dos.writeShort(ConstantPoolInfo.indexOf(signature, pool));
+	if (attributes == null) {
+	    dos.writeShort(0);
+	} else {
+	    dos.writeShort(attributes.length);
+	    for (int i = 0; i < attributes.length; i++)
+		attributes[i].write(dos, pool);
+	}
+    }
+
+    /**
+     * print out the method, much as you would see it in the source
+     * file. The string ClassName is substituted for &LTinit&GT when
+     * printing.
+     */
+    public String toString(String className) {
+	StringBuffer x = new StringBuffer();
+	boolean isArray = false;
+	String paramSig;
+	String returnSig;
+	int ndx = 0;
+	StringBuffer parameterList = new StringBuffer();
+	char	initialParameter = 'a';
+	StringBuffer varName = new StringBuffer();
+
+
+	String s = signature.strValue;
+	paramSig = s.substring(s.indexOf('(')+1, s.indexOf(')'));
+	returnSig = s.substring(s.indexOf(')')+1);
+
+	x.append(ClassFile.accessString(accessFlags));
+	/* catch constructors */
+	if ((className != null) && (name.toString().startsWith("<init>")))
+	    parameterList.append(className);
+	else
+	    parameterList.append(name.toString());
+	parameterList.append("(");
+	if ((paramSig.length() > 0) && paramSig.charAt(0) != 'V') {
+	    while (paramSig.length() > 0) {
+		varName.setLength(0);
+		varName.append(initialParameter);
+		initialParameter++;
+		parameterList.append(
+			ClassFile.typeString(paramSig, varName.toString()));
+		paramSig = ClassFile.nextSig(paramSig);
+		if (paramSig.length() > 0)
+		    parameterList.append(", ");
+	    }
+
+        }
+	parameterList.append(")");
+	x.append(ClassFile.typeString(returnSig, parameterList.toString()));
+	x.append(";");
+	return (x.toString());
+    }
+
+    /**
+     * Generic toString method, init method is unchanged.
+     */
+    public String toString() {
+	return (toString((String)null));
+    }
+}
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/fieldInfo.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/fieldInfo.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/fieldInfo.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/fieldInfo.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,23 @@
+
+#include "jvmdi.h"
+
+jvmdiError GetFieldName(jclass clazz, jfieldID field, char** namePtr,
+						char** signaturePtr)
+{
+}
+
+jvmdiError GetFieldDeclaringClass(jclass clazz, jfieldID field,
+								  jclass* declaringClassPtr)
+{
+}
+
+jvmdiError GetFieldModifiers(jclass clazz, jfieldID field, jint* modifiersPtr)
+{
+}
+
+jvmdiError IsFieldSynthetic(jclass clazz, jfieldID field,
+							jboolean* isSyntheticPtr)
+{
+}
+
+/* End of field_info.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/frameAccess.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/frameAccess.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/frameAccess.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/frameAccess.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,25 @@
+
+#include "jvmdi.h"
+
+jvmdiError GetFrameCount(jthread thread, jint* countPtr)
+{
+}
+
+jvmdiError GetCurrentFrame(jthread thread, jframeID* framePtr)
+{
+}
+
+jvmdiError GetCallerFrame(jframeID called, jframeID* framePtr)
+{
+}
+
+jvmdiError GetFrameLocation(jframeID frame, jclass* classPtr,
+							jlocation* locationPtr)
+{
+}
+
+jvmdiError NotifyFramePop(jframeID frame)
+{
+}
+
+/* End of frame_access.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jdwp.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jdwp.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jdwp.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jdwp.c	1999-12-22 19:33:00.000000000 -0500
@@ -0,0 +1,2 @@
+
+/* End of jdwp.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jdwp.h kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jdwp.h
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jdwp.h	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jdwp.h	2000-01-02 18:36:13.000000000 -0500
@@ -0,0 +1,377 @@
+
+#ifndef JDWP_H
+
+#define JDWP_H
+
+/* Created: Sun Dec 19 18:23:30 1999 DLD
+  
+   FYI: JDWP canonical form is big-endian (i.e. Java format).
+*/
+
+#define JDWP_SOCKET_TRANSPORT 1
+#define JDWP_SERIAL_LINE_TRANSPORT 2
+#define JDWP_SHARED_MEMORY_TRANSPORT 3
+
+/* +++
+   
+   JDWP data types:  Object IDs, referenct IDs, Field IDs, method IDs, and
+   frame IDs may be sized differently in different VM implementations.  Max
+   size is 8 bytes.  The "idSizes" Command in the "VirtualMachine" command set
+   relates the sizes.
+*/
+
+/* Here's a byte.  This is definatly some kind of axiom, but what the hell:
+*/
+typedef char jdwpByte[1];
+
+/* Zero is false and non-zero is true.
+*/
+typedef jdwpByte jdwpBoolean[1];
+
+/* Signed unless explicitly unsigned.
+*/
+typedef jdwpByte jdwpInt[4];
+
+/* Signed unless explicitly unsigned.
+*/
+typedef jdwpByte jdwpLong[8];
+
+/* VM specific object ID over lifetime of VM object (The spec then
+   goes on to say that 0 is the null object, seemingly in violation of
+   this being VM specific).  May be up to 8-bytes long.
+
+   This ID is valid until _explicitly_disposed_, regardless of whether the
+   object has been GC'd.
+
+   Existance of an object ID does not prevent object GC.  Access to GC'd
+   objects results in INVALID_OBJECT error code.  GC can be disabled with the
+   "DisableCollection" command (this usage is rare).
+*/
+typedef jdwpByte jdwpObjectID[8];
+
+/* Also known as a "Typed-Object", this is the jdwpObjectID preceeded by an
+   object's "Type".  <<FIXME: JDWP.Tag (whatever that is) >> enumerates
+   values.
+*/
+typedef jdwpByte jdwpTaggedObjectID[sizeof(jdwpObjectID)+1];
+
+/* ID's a VM specific thread object.  Up to 8 bytes long.
+*/
+typedef jdwpByte jdwpThreadID[sizeof(jdwpObjectID)];
+
+/* ID's a VM specific thread group object.  Up to 8 bytes long.
+*/
+typedef jdwpByte jdwpThreadGroupID[sizeof(jdwpObjectID)];
+
+/* ID's a VM specific string object.  Up to 8 bytes long.
+*/
+typedef jdwpByte jdwpStringID[sizeof(jdwpObjectID)];
+
+/* ID's a VM specific class loader object.  Up to 8 bytes long.
+*/
+typedef jdwpByte jdwpClassLoaderID[sizeof(jdwpObjectID)];
+
+/* ID's a VM specific class object.  Up to 8 bytes long.
+*/
+typedef jdwpByte jdwpClassObjectID[sizeof(jdwpObjectID)];
+
+/* ID's a VM unique, specific, reference object.  Up to 8 bytes long.  It's
+   noted that a class object may have a diffent class object ID from it's
+   reference type ID.
+
+   Reference types are unique for commands and replies throught the lifetime
+   of the debugging session, regardless of whether the referenced class has
+   been unloaded.
+*/
+typedef jdwpByte jdwpReferenceTypeID[sizeof(jdwpObjectID)];
+
+/* ID's a VM specific class object.
+*/
+typedef jdwpByte jdwpClassID[sizeof(jdwpReferenceTypeID)];
+
+/* ID's a VM specific interface object.
+*/
+typedef jdwpByte jdwpInterfaceID[sizeof(jdwpReferenceTypeID)];
+
+/* ID's a VM specific array object.
+*/
+typedef jdwpByte jdwpArrayID[sizeof(jdwpReferenceTypeID)];
+
+/* ID's a VM specific method within a VM specific class ID.
+   This uniquely identifies the method within it's class as well as
+   in all extenders and implementers.
+*/
+typedef jdwpByte jdwpMethodID[8];
+
+/* ID's a VM specific field within a VM specific class ID.
+   This uniquely identifies the field within it's class as well as
+   in all extenders and implementers.
+
+   The ID may be relative to the declaring type or the
+   extender's or implementer's type, so there's the potential of
+   some late binding.
+
+   This is VM specific, up to eight bytes long.
+*/
+typedef jdwpByte jdwpFieldID[8];
+
+/* ID's a VM specific frame.
+
+   A frame ID is unique to an entire VM rather than unique to a
+   specific thread.
+
+   A frame ID need only be valid during the time in which a thread is
+   suspended.
+*/
+typedef jdwpByte jdwpFrameID[8];
+
+/* This is the Program Counter.  There are some exceedingly sensible
+   constraints [it does what you'd think] placed upon this value in the spec.
+
+   Here's the crazy part: the spec seems to say that each location is ID'd by
+   a type tag (1 byte), followed by a class ID, followed by a method ID,
+   followed by an unsigned 8 byte, within-method, location index.
+*/
+typedef jdwpByte jdwpLocation[8];
+
+/* These are counted stings.  Four byte lenth, no termination, followed by
+   UTF-8 data.
+*/
+typedef jdwpByte jdwpString[0];
+
+/* First byte is a signature according to JDWP.TAG.  VM specific value follows.
+   May be an object ID or a primitive value (1 to 8 bytes).  See the commands
+   for more specific information.
+*/
+typedef jdwpByte jdwpValue[0];
+
+/* Same as a value except that the type can be deduced from context and is
+   omitted.
+*/
+typedef jdwpByte jdwpUntaggedValue[0];
+
+/* Sequence of values for some array operations.  For primatives, elements
+   are of type jdwpUntaggedValue.  For objects, elements are fo type
+   jdwpValues.
+*/
+typedef jdwpByte jdwpTypedSequence[8];
+
+/* --- */
+
+/* +++ +++
+
+   JDWP commands within their command sets.
+*/
+
+/* +++ Virtual machine command set.
+*/
+
+#define JDWP_VIRTUAL_MACHINE 1
+
+/* Returns JDWP version info.
+*/
+#define JDWP_VIRUTAL_MACHINE__VERSION 1
+struct jdwpVirtualMachine_Version_ReplyData
+{
+	/* VM dependant description of version.
+	*/
+	jdwpString description;
+
+	/* Major version number.
+	*/
+	jdwpInt jdwpMajor;
+	
+	/* Minor version number.
+	*/
+	jdwpInt jdwpMinor;
+
+	/* JRE version, as per java.version property.
+	*/
+	jdwpString vmVersion;
+
+	/* VM name as per java.vm.name property.
+	*/
+	jdwpString vmName;
+};
+
+/* Returns references to loaded classes that match a signature.  Multiple
+   references will be returned if two or more class loaders have loaded a
+   class of the same name.  The search is confined to loaded classes only;
+   no attmpt is made to load a class of the given signature.
+
+   Command argument:
+   
+   jdwpString signature;
+
+   This is the JNI signature of the class to find (ie "Ljava/lang/String;").
+
+   The reply data consists of a jdwpInt value, count, followed by count
+   jdwpVirtualMachineClassesBySignatureReplyDataItem type data structures.
+*/
+#define JDWP_VIRTUAL_MACHINE__CLASSES_BY_SIGNATURE 2
+struct jdwpVirtualMachine_ClassesBySignature_ReplyDataItem
+{
+	/* This is the reference type's <i>kind</i>.
+	*/
+	jdwpByte refTypeTag;
+
+	/* A reference to a class that matched the search.
+	*/
+	jdwpReferenceTypeID typeID;
+
+	/* The class status (FIXME: whatever that is).
+	*/
+	jdwpInt status;
+};
+
+/* Returns references to all currently loaded classes.
+*/
+#define JDWP_VIRTUAL_MACHINE__ALL_CLASSES 3
+struct jdwpVirtualMachine_AllClasses_ReplyDataItem
+{
+	/* This is the reference type's <i>kind</i>.
+	*/
+	jdwpByte refTypeTag;
+	
+	/* A reference to a currently loaded class.
+	*/
+	jdwpReferenceTypeID typeID;
+
+	/* This reference's JNI signature.
+	*/
+	jdwpString signature;
+
+	/* The class status (FIXME: whatever that is).
+	*/
+	jdwpInt status;
+};
+
+#define JDWP_VIRTUAL_MACHINE__ALL_THREADS 4
+
+#define JDWP_VIRTUAL_MACHINE__TOP_LEVEL_THEAD_GROUPS 5
+
+#define JDWP_VIRTUAL_MACHINE__DISPOSE 6
+
+#define JDWP_VIRTUAL_MACHINE__ID_SIZES 7
+
+#define JDWP_VIRTUAL_MACHINE__SUSPEND 8
+
+#define JDWP_VIRTUAL_MACHINE__RESUME 9
+
+#define JDWP_VIRTUAL_MACHINE__EXIT 10
+
+#define JDWP_VIRTUAL_MACHINE__CREATE_STRING 11
+
+#define JDWP_VIRTUAL_MACHINE__CAPABILITIES 12
+
+#define JDWP_VIRTUAL_MACHINE__CLASS_PATHS 13
+
+#define JDWP_VIRTUAL_MACHINE__DISPOSE_OBJECTS 14
+
+#define JDWP_VIRTUAL_MACHINE__HOLD_EVENTS 15
+
+#define JDWP_VIRTUAL_MACHINE__RELEASE_EVENTS 16
+
+/* --- */
+
+/* +++ reference type command set.
+*/
+
+#define JDWP_REFERENCE_TYPE 2
+
+/* --- */
+
+#define JDWP_CLASS_TYPE 3
+
+#define JDWP_ARRAY_TYPE 4
+
+#define JDWP_INTERFACE_TYPE 5
+
+#define JDWP_METHOD 6
+
+/* FIXME: where's seven?? */
+
+#define JDWP_FIELD 8
+
+#define JDWP_OBJECT_REFERENCE 9
+
+#define JDWP_STRING_REFERENCE 10
+
+#define JDWP_THREAD_REFERENCE 11
+
+#define JDWP_THREAD_GROUP_REFERENCE 12
+
+#define JDWP_ARRAY_REFERENCE 13
+
+#define JDWP_CLASS_LOADER_REFERENCE 14
+
+#define JDWP_EVENT_REQUEST 15
+
+#define JDWP_STACK_FRAME 16
+
+#define JDWP_CLASS_OBJECT_REFERENCE 17
+
+#define JDWP_EVENT 64
+
+/* --- --- */
+
+/* JDWP command / reply shared header.
+*/
+struct commandReplySharedHeader
+{
+	/* This is the size of the header and the data.  So the emtpy
+	   message has length 11, the length of the shared header, 9, and the
+	   fixed length of the private part, 2.
+	*/
+	jdwpByte length[4];
+	
+	/* Unique packet command/reply-pair ID.  << A reply packet has the same
+	   ID as the command packet to which it replies. [FIXME attrib to SUN
+	   JDWP spec] >>
+	*/
+	jdwpByte id[4];
+
+	/* There's only one flag bit currently defined, 0x80, which denotes a
+	   replay, rather than a command, packet.
+	*/
+	jdwpByte flags[1];
+};
+
+/* JDWP Command
+*/
+struct commandPacket
+{
+	struct commandReplySharedHeader sharedHeader;
+
+	/* These group commands.  0 to 63 are commands sent to the target VM,
+	   while 64 to 127 are sent to the debugger.  128 to 256 are reserved for
+	   vendors.  These are [somehow] bound closely to the JDI spec.
+	*/
+	jdwpByte commandSet[1];
+
+	/* This, and commandSet, is the way for the reciever to know what to do.
+	*/
+	jdwpByte command[1];
+
+	/* This is unique to each command AND reply.
+    */
+	jdwpByte* data[0];
+};
+
+/* JDWP Reply
+*/
+struct replyPacket
+{
+	struct commandReplySharedHeader sharedHeader;
+
+	/* 0 is success otherwise it's an error.  May be mapped to a JVMDI error
+	   code or may be command/reply specific.
+	*/
+	jdwpByte errorCode[2];
+	
+	/* This is unique to each command AND reply.
+    */
+	jdwpByte* data[0];
+};
+
+#endif
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jdwpServer.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jdwpServer.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jdwpServer.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jdwpServer.c	2000-01-02 17:49:55.000000000 -0500
@@ -0,0 +1,462 @@
+
+/*  The networking code comes from the unix-socket-faq.  It is public
+    domain, and may be copied freely.  There is no copyright on it.  The
+    original work was by Vic Metcalfe (vic at brutus.tlug.org), and any
+    modifications made to that work were made with the understanding that
+    the finished work would be in the public domain.
+  
+    If you have found a bug, please pass it on to me at the above address
+    acknowledging that there will be no copyright on your work.
+  
+    The most recent version of this file, and the unix-socket-faq can be
+    found at http://www.interlog.com/~vic/sock-faq/.
+*/
+
+#include "jdwpSockHelp.h"
+
+static int startSocketServer(int);
+
+/* Take a service name, and a service type, and return a port number.  If the
+   service name is not found, it tries it as a decimal number.  The number
+   returned is byte ordered for the network.
+*/
+int atoport(char* service, char* proto)
+{
+	int port;
+	long int lport;
+	struct servent* serv;
+	char* errpos;
+
+	/* First try to read it from /etc/services
+	*/
+	serv = getservbyname(service, proto);
+	if (serv != NULL)
+	{
+		port = serv->s_port;
+	}
+	else
+	{
+		/* Not in services, maybe a number?
+		*/
+		lport = strtol(service,&errpos,0);
+		if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) )
+		{
+			/* Invalid port address
+			*/
+			return -1;
+		}
+		port = htons(lport);
+	}
+	return port;
+}
+
+/* Converts ascii text to in_addr struct.  NULL is returned if the address
+   can not be found.
+*/
+struct in_addr* atoaddr(char* address)
+{
+	struct hostent* host;
+	static struct in_addr saddr;
+
+	/* First try it as aaa.bbb.ccc.ddd.
+	*/
+	saddr.s_addr = inet_addr(address);
+	if (saddr.s_addr != -1)
+	{
+		return &saddr;
+	}
+	host = gethostbyname(address);
+	if (host != NULL)
+	{
+		return (struct in_addr*)*host->h_addr_list;
+	}
+	return NULL;
+}
+
+/* This function listens on a port, and returns connections.  It forks
+   returns off internally, so your main function doesn't have to worry
+   about that.  This can be confusing if you don't know what is going on.
+   The function will create a new process for every incoming connection,
+   so in the listening process, it will never return.  Only when a connection
+   comes in, and we create a new process for it will the function return.
+   This means that your code that calls it should _not_ loop.
+
+   The parameters are as follows:
+   
+     socket_type: SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets)
+	 
+     port: The port to listen on.  Remember that ports < 1024 are
+       reserved for the root user.  Must be passed in network byte
+       order (see "man htons").
+	   
+     listener: This is a pointer to a variable for holding the file
+       descriptor of the socket which is being used to listen.  It
+       is provided so that you can write a signal handler to close
+       it in the event of program termination.  If you aren't interested,
+       just pass NULL.  Note that all modern unixes will close file
+       descriptors for you on exit, so this is not required.
+*/
+int get_connection(int socket_type, u_short port, int* listener)
+{
+	struct sockaddr_in address;
+	int listening_socket;
+	int connected_socket = -1;
+	int new_process;
+	int reuse_addr = 1;
+	
+	/* Setup internet address information.  
+	   This is used with the bind() call
+	*/
+	memset((char*)&address, 0, sizeof(address));
+	address.sin_family = AF_INET;
+	address.sin_port = port;
+	address.sin_addr.s_addr = htonl(INADDR_ANY);
+
+	listening_socket = socket(AF_INET, socket_type, 0);
+	if (listening_socket < 0)
+	{
+		perror("socket");
+		exit(EXIT_FAILURE);
+	}
+
+	if (listener != NULL)
+	{
+		*listener = listening_socket;
+	}
+
+	setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR,
+			   (char*)&reuse_addr, sizeof(reuse_addr));
+
+	if (bind(listening_socket,
+			 (struct sockaddr*)&address, 
+			 sizeof(address)) < 0)
+	{
+		perror("bind");
+		close(listening_socket);
+		exit(EXIT_FAILURE);
+	}
+
+	if (socket_type == SOCK_STREAM)
+	{
+		/* Queue up to five connections before
+		   having them automatically rejected.
+		*/		
+		listen(listening_socket, 5);
+
+		while(connected_socket < 0)
+		{
+			connected_socket = accept(listening_socket, NULL, NULL);
+			if (connected_socket < 0)
+			{
+				/* Either a real error occured, or blocking was interrupted for
+				   some reason.  Only abort execution if a real error occured.
+				*/
+				if (errno != EINTR)
+				{
+					perror("accept");
+					close(listening_socket);
+					exit(EXIT_FAILURE);
+				}
+				else
+				{
+					/* don't fork - do the accept again
+					*/
+					continue;
+				}
+			}
+
+			new_process = fork();
+			if (new_process < 0)
+			{
+				perror("fork");
+				close(connected_socket);
+				connected_socket = -1;
+			}
+			else
+			{
+				/* We have a new process...
+				*/
+				if (new_process == 0)
+				{
+					/* This is the new process.  Close our copy of this
+					   socket.
+					*/
+					close(listening_socket);
+					if (listener != NULL)
+					{
+						/* Closed in this process.  We are not 
+						   responsible for it.
+						*/						
+						*listener = -1;
+					}
+				}
+				else
+				{
+					/* This is the main loop.  Close copy of connected socket,
+					   and continue loop.
+					*/
+					close(connected_socket);
+					connected_socket = -1;
+				}
+			}
+		}
+		
+		return connected_socket;
+	}
+	else
+	{
+		return listening_socket;
+	}
+}
+
+/* This is just like the read() system call, accept that it will make
+   sure that all your data goes through the socket.
+*/
+int sock_read(int sockfd, char* buf, size_t count)
+{
+	size_t bytes_read = 0;
+	int this_read;
+
+	while (bytes_read < count)
+	{
+		do
+		{
+			this_read = read(sockfd, buf, count - bytes_read);
+		}
+		while ( (this_read < 0) && (errno == EINTR) );
+		
+		if (this_read < 0)
+		{
+			return this_read;
+		}
+		else if (this_read == 0)
+		{
+			return bytes_read;
+		}
+		
+		bytes_read += this_read;
+		buf += this_read;
+	}
+	return count;
+}
+
+/* This is just like the write() system call, accept that it will
+   make sure that all data is transmitted.
+*/
+int sock_write(int sockfd, const char* buf, size_t count)
+{
+	size_t bytes_sent = 0;
+	int this_write;
+
+	while (bytes_sent < count)
+	{
+		do
+		{
+			this_write = write(sockfd, buf, count - bytes_sent);
+		}
+		while ( (this_write < 0) && (errno == EINTR) );
+		
+		if (this_write <= 0)
+		{
+			return this_write;
+		}
+		
+		bytes_sent += this_write;
+		buf += this_write;
+	}
+	return count;
+}
+
+/* This function reads from a socket, until it recieves a linefeed
+   character.  It fills the buffer "str" up to the maximum size "count".
+
+   This function will return -1 if the socket is closed during the read
+   operation.
+
+   Note that if a single line exceeds the length of count, the extra data
+   will be read and discarded!  You have been warned.
+*/
+int sock_gets(int sockfd, char* str, size_t count)
+{
+	int bytes_read;
+	int total_count = 0;
+	char* current_position;
+	char last_read = 0;
+
+	current_position = str;
+	while (last_read != 10)
+	{
+		bytes_read = read(sockfd, &last_read, 1);
+		
+		if (bytes_read <= 0)
+		{
+			/* The other side may have closed unexpectedly.  Is this
+               effective on other platforms than linux?
+			*/
+			return -1;
+		}
+		
+		if ( (total_count < count) && (last_read != 10) && (last_read !=13) )
+		{
+			current_position[0] = last_read;
+			current_position++;
+			total_count++;
+		}
+	}
+	
+	if (count > 0)
+	{
+		current_position[0] = 0;
+	}
+	
+	return total_count;
+}
+
+/* This function writes a character string out to a socket.  It will 
+   return -1 if the connection is closed while it is trying to write.
+*/
+int sock_puts(int sockfd, char* str)
+{
+	return sock_write(sockfd, str, strlen(str));
+}
+
+/* This ignores the SIGPIPE signal.  This is usually a good idea, since
+   the default behaviour is to terminate the application.  SIGPIPE is
+   sent when you try to write to an unconnected socket.  You should
+   check your return codes to make sure you catch this error!
+*/
+void ignore_pipe(void)
+{
+	struct sigaction sig;
+
+	sig.sa_handler = SIG_IGN;
+	sig.sa_flags = 0;
+	sigemptyset(&sig.sa_mask);
+	sigaction(SIGPIPE,&sig,NULL);
+}
+
+int jdwpStartServer(int argc, char* argv[])
+{
+	int transport = JDWP_SOCKET_TRANSPORT;
+	
+	/* FIXME: A better design can probably eliminate this switch statement.
+	*/
+	switch (transport)
+	{
+	case JDWP_SOCKET_TRANSPORT:
+		
+		/* Create socket transport.
+		*/
+		(void)startSocketServer(6969);
+		break;
+		
+	case JDWP_SERIAL_LINE_TRANSPORT:
+		
+		/* Create serial line transport.
+		*/
+		/*(void)startSerialLineServer();*/
+		break;
+		
+	case JDWP_SHARED_MEMORY_TRANSPORT:
+		
+		/* Create shared memory transport.
+		*/
+		/*(void)startSharedMemoryServer();*/
+		break;        
+	}
+
+	(void)serve();
+
+	return 0;
+}
+
+/* This is NOT high performance.   There's no intention of doing multi-client
+   debugging (yet).  The most basic single concurrent client use cases are
+   supported, but otherwise is intentionally ignored.
+*/
+static int startSocketServer(int port)
+{
+	struct servent *sp;
+	struct sockaddr_in sin, from;
+
+	if ((sp = getservbyname(service, "jdwp")) == NULL)
+	{
+		/* FIXME: Error...
+		*/
+		return 9995;
+	}
+
+	/* sin.sin_family= <etc...> */
+
+	if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+	{
+		/* FIXME: Error ...
+		*/
+		return 9996;
+	}
+
+	if (bind(s, &sin, sizeof(sin)) < 0)
+	{
+		/* FIXME: Error ...
+		*/
+		return 9997;
+	}
+	
+	if (listen(s, QUELEN) < 0)
+	{
+		/* FIXME: Error ...
+		*/
+		return 9998;
+	}
+
+	return 0;
+}
+
+static int serve()
+{
+	/* Allow successive (non-simultaneous) debugging sessions ...
+	*/
+	for (;;)
+	{
+		if ((g = accept(f, &from, &len)) < 0)
+		{
+			/* FIXME: Error ...
+			*/
+			return 9999;
+		}
+
+		/* Do it!
+		*/
+		(void)jdwpDebugSession();
+
+		/* Done
+		*/
+		close(g);
+	}
+}
+
+static int jdwpDebugSession()
+{
+	for ( ; doJDWPCommand(); ) {}
+}
+
+static int doJDWPCommand(commandSet, command)
+{
+	switch (commandSet)
+	{
+		case VIRTUAL_MACHINE:
+
+			switch (command)
+			{
+			case ():
+				break;
+			case ():
+				break;
+			case ():
+				break;
+			}
+			break;
+	}
+}
+
+/* End of jdwpServer.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jdwpSockHelp.h kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jdwpSockHelp.h
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jdwpSockHelp.h	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jdwpSockHelp.h	1999-12-27 13:36:54.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ *  This file is provided for use with the unix-socket-faq.  It is public
+ *  domain, and may be copied freely.  There is no copyright on it.  The
+ *  original work was by Vic Metcalfe (vic at brutus.tlug.org), and any
+ *  modifications made to that work were made with the understanding that
+ *  the finished work would be in the public domain.
+ *
+ *  If you have found a bug, please pass it on to me at the above address
+ *  acknowledging that there will be no copyright on your work.
+ *
+ *  The most recent version of this file, and the unix-socket-faq can be
+ *  found at http://www.interlog.com/~vic/sock-faq/.
+ */
+
+#ifndef _SOCKHELP_H_
+#define _SOCKHELP_H_
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <limits.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+int atoport(char*, char*);
+struct in_addr* atoaddr(char*);
+
+int get_connection(int, u_short, int*);
+int make_connection(char*, int, char*);
+
+int sock_read(int, char*, size_t);
+int sock_write(int, const char*, size_t);
+int sock_gets(int, char*, size_t);
+int sock_puts(int, const char*);
+void ignore_pipe(void);
+
+#endif
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jpdaBackend.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jpdaBackend.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/jpdaBackend.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/jpdaBackend.c	2000-01-11 11:52:33.000000000 -0500
@@ -0,0 +1,653 @@
+
+#include <jni.h>
+#include <jvmdi.h>
+#include <string.h>
+#include <readline.h>
+#include "jdwp.h"
+
+static int handleVMInitEvent(void);
+static int handleSingleStepEvent(JNIEnv*, JVMDI_Event*);
+static int handleVMDeathEvent(void);
+
+static int setBreakpoint(char*);
+static int doContinue(char*);
+static int doQuit(char*);
+static int doStep(char*);
+
+static int readAndParseCommand(char**, char**);
+static int checkAndDispatchCommand(char*, char*, char*[], int,
+								   int (*[])(char*));
+static int safelySkipWhitespace(char**, int);
+static int safelySkipNonWhitespace(char**, int);
+	
+static const char* const prompt = "jvmdb> ";
+
+/* FIXME: What the return value supposed to be?  The spec doesn't say!
+   What should happen with vm?  Is it GC'd?  Do I have to fuck with it's
+   reference count?  Who free's it (me?) ?
+*/
+JNIEXPORT jint JNICALL JVM_OnLoad(JavaVM* vm, char* options, void* reserved)
+{
+	{
+		/* Wait for a JDWP client to connect.
+		*/
+		int jdwpTransport = JDWP_SOCKET_TRANSPORT;
+		switch (jdwpTransport)
+		{
+		case JDWP_SOCKET_TRANSPORT:
+			
+			(void)getSocketConnection(6969);
+			break;
+		
+		case JDWP_SERIAL_LINE_TRANSPORT:
+			
+			(void)getSerialLineConnection();
+			break;
+		
+		case JDWP_SHARED_MEMORY_TRANSPORT:
+
+			(void)getSharedMemoryConnection();
+			break;        
+		}
+	}
+
+	{
+		/* Set the event hook
+		*/
+		JVMDI_Interface_1* jvmdiEnv;
+		jint r;
+		if ((r = (*vm)->GetEnv(vm, &jvmdiEnv, JVMDI_VERSION_1)) != JNI_OK)
+		{
+			if (r == JNI_EDETACHED)
+			{
+				/* Current thread is not attached to the VM given in vm .
+				*/
+				return 1;
+			}
+			else if (r == JNI_EVERSION)
+			{
+				/* Interface version is not supported.
+				*/
+				return 2;
+			}
+			else
+			{
+				/* Shouldn't happen...
+				*/
+				return 3;
+			}
+		}
+	
+		if ((*jvmdiEnv)->SetEventHook((JVMDI_EventHook)eventHook))
+		{
+			return 4;
+		}
+	}
+	
+	return 0;
+}
+
+void eventHook(JNIEnv* env, JVMDI_Event* e)
+{
+	switch(e->kind)
+	{
+	case JVMDI_EVENT_VM_INIT:
+		if (!handleVMInitEvent())
+		{
+			/* FIXME: handle error */
+		}
+		break;
+		
+	case JVMDI_EVENT_SINGLE_STEP:
+
+		if (!handleSingleStepEvent(env, e))
+		{
+			/* FIXME: handle error */
+		}
+		break;
+		
+	case JVMDI_EVENT_BREAKPOINT:
+		break;
+		
+	case JVMDI_EVENT_FRAME_POP:
+		break;
+		
+	case JVMDI_EVENT_METHOD_ENTRY:
+		break;
+		
+	case JVMDI_EVENT_METHOD_EXIT:
+		break;
+		
+	case JVMDI_EVENT_FIELD_ACCESS:
+		break;
+		
+	case JVMDI_EVENT_FIELD_MODIFICATION:
+		break;
+		
+	case JVMDI_EVENT_EXCEPTION:
+		break;
+		
+	case JVMDI_EVENT_EXCEPTION_CATCH:
+		break;
+		
+	case JVMDI_EVENT_USER_DEFINED:
+		break;
+		
+	case JVMDI_EVENT_THREAD_END:
+		break;
+		
+	case JVMDI_EVENT_THREAD_START:
+		break;
+		
+	case JVMDI_EVENT_CLASS_LOAD:
+		break;
+		
+	case JVMDI_EVENT_CLASS_UNLOAD:
+		break;
+		
+	case JVMDI_EVENT_CLASS_PREPARE:
+		break;
+				
+	case JVMDI_EVENT_VM_DEATH:
+		if (!handleVMDeathEvent())
+		{
+			/* FIXME: handle error */
+		}
+		break;
+	}
+}
+
+/* FIXME: This will go away when we speak JDWP.
+*/
+static void displayBanner()
+{
+	printf("jvmdb: Kaffe JVMDI Debugger Client\n");
+	printf("jvmdb: Hack! Hack!\n");
+	return;
+}
+
+static int handleVMInitEvent()
+{
+	char* cmd;
+	char* args;
+	int i;
+
+	/* These are sorted by length, ties are not significant.  The elements
+	   correspond to the cmdHandlers array.
+	*/
+	char* validCmds[] =
+	{
+		"breakpoint",
+		"continue",
+		"quit",
+		"step"
+	};
+	int (*cmdHandlers[])(char*) =
+	{
+		setBreakpoint,
+		doContinue,
+		doQuit,
+		doStep
+	};
+
+	displayBanner();
+
+	fprintf(stdout, "jvmdb: VM initialization event received.\n");
+
+	do
+	{
+		if (!readAndParseCommand(&cmd, &args))
+		{
+			if (cmd != NULL) free(cmd);
+			if (args != NULL) free(args);
+			continue;
+		}
+
+		if (!(i = checkAndDispatchCommand(cmd,
+										  args,
+										  validCmds,
+										  sizeof(validCmds) / sizeof(char*),
+										  cmdHandlers)))
+		{
+			if (cmd != NULL) free(cmd);
+			if (args != NULL) free(args);
+			continue;
+		}
+		else
+		{
+			if (i == 1)
+			{
+				if (cmd != NULL) free(cmd);
+				if (args != NULL) free(args);
+				break;
+			}
+		}
+		
+		/* FIXME: This memory is leaked if it's a quit command since the
+		   quit command handler calls exit().  No big deal, but may as
+		   well fix it.
+		*/
+		if (cmd != NULL) free(cmd);
+		if (args != NULL) free(args);
+	}
+	while (1);
+	
+	return 0;
+}
+
+static int handleSingleStepEvent(JNIEnv* env, JVMDI_Event* e)
+{
+	char* cmd;
+	char* args;
+	int i;
+
+	/* These are sorted by length, ties are not significant.  The elements
+	   correspond to the cmdHandlers array.
+	*/
+	char* validCmds[] =
+	{
+		"continue",
+		"quit",
+		"step"
+	};
+	int (*cmdHandlers[])(char*) =
+	{
+		doContinue,
+		doQuit,
+		doStep
+	};
+
+	fprintf(stdout, "jvmdb: Single step event received.\n");
+
+	do
+	{
+		if (!readAndParseCommand(&cmd, &args))
+		{
+			if (cmd != NULL) free(cmd);
+			if (args != NULL) free(args);
+			continue;
+		}
+
+		if (!(i = checkAndDispatchCommand(cmd,
+										  args,
+										  validCmds,
+										  sizeof(validCmds) / sizeof(char*),
+										  cmdHandlers)))
+		{
+			if (cmd != NULL) free(cmd);
+			if (args != NULL) free(args);
+			continue;
+		}
+		else
+		{
+			if (i == 1)
+			{
+				if (cmd != NULL) free(cmd);
+				if (args != NULL) free(args);
+				break;
+			}
+		}
+		
+		/* FIXME: This memory is leaked if it's a quit command since the
+		   quit command handler calls exit().  No big deal, but may as
+		   well fix it.
+		*/
+		if (cmd != NULL) free(cmd);
+		if (args != NULL) free(args);
+	}
+	while (1);
+	
+	return 0;
+}
+
+static int handleVMDeathEvent()
+{
+	char* cmd;
+	char* args;
+	int i;
+
+	char* validCmds[] =
+	{
+		"quit"
+	};
+	int (*cmdHandlers[])(char*) =
+	{
+		doQuit
+	};
+	
+	fprintf(stdout, "jvmdb: VM death event received.\n");
+
+	do
+	{
+		if (!readAndParseCommand(&cmd, &args))
+		{
+			if (cmd != NULL) free(cmd);
+			if (args != NULL) free(args);
+			continue;
+		}
+
+		if (!(i = checkAndDispatchCommand(cmd,
+										  args,
+										  validCmds,
+										  sizeof(validCmds) / sizeof(char*),
+										  cmdHandlers)))
+		{
+			if (cmd != NULL) free(cmd);
+			if (args != NULL) free(args);
+			continue;
+		}
+		else
+		{
+			if (i == 1)
+			{
+				if (cmd != NULL) free(cmd);
+				if (args != NULL) free(args);
+				break;
+			}
+		}
+		
+		/* FIXME: This memory is leaked if it's a quit command since the
+		   quit command handler calls exit().  No big deal, but may as
+		   well fix it.
+		*/
+		if (cmd != NULL) free(cmd);
+		if (args != NULL) free(args);
+	}
+	while (1);
+		
+	return 0;
+}
+
+static int doContinue(char* args)
+{
+	fprintf(stdout, "jvmdb: Continuing.\n");
+	
+	return 1;
+}
+
+static int doStep(char* args)
+{
+	fprintf(stdout, "jvmdb: Steping.\n");
+	
+	return 1;
+}
+
+static int doQuit(char* args)
+{
+	fprintf(stdout, "jvmdb: Quiting.\n");
+	
+	exit(0);
+	
+	return 1;
+}
+
+static int setBreakpoint(char* args)
+{
+	char* p = args;
+	char* class = args;
+	char* meth;
+	char* loc;
+
+	if (!args)
+	{
+		fprintf(stderr, "jvmdb: Error.  Must give at least class and method, separated by \".\", as breakpoint command args\n");
+		return 0;
+	}
+
+	/* We work from right to left while parseing this command's args.
+	*/
+	p = args + strlen(args) - 1;
+	
+	/* Get the optional location.
+	*/
+	while (*p != ':' && *p != '.' && p > args)
+	{
+		p--;
+	}
+
+	/* Location?
+	*/
+	if (*p == ':')
+	{
+		loc = p + 1;
+	}
+	/* No location means "on function entry" breakpoint.
+	*/
+	else if (*p == '.')
+	{
+		loc = NULL;
+	}
+	else
+	{
+		fprintf(stderr, "jvmdb: Error.  Must give at least class and method, separated by \".\", as breakpoint command args\n");
+		return 0;
+	}
+	
+	/* Get the method name.
+	*/
+	if (*p == ':')
+	{
+		*p = '\0';
+
+		while (*p != '.' && p > args)
+		{
+			p--;
+		}
+
+		if (*p == '.')
+		{
+			meth = p + 1;
+			*p = '\0';
+		}
+		else
+		{
+			fprintf(stderr, "jvmdb: Error.  Must give at least class and method, separated by \".\", as breakpoint command args\n");
+			return 0;
+		}
+	}
+	else
+	{
+		meth = p + 1;
+		*p = '\0';
+	}
+	
+
+	if (loc != NULL)
+	{
+		fprintf(stdout, "jvmdb: Breakpoint set at %s.%s:%s\n",
+				class, meth, loc);
+	}
+	else
+	{
+		fprintf(stdout, "jvmdb: Breakpoint set at %s.%s\n",
+				class, meth);
+	}
+	
+	return 0;
+}
+
+/* Caller must free cmd and args.
+*/
+static int readAndParseCommand(char** cmd, char** args)
+{
+	const int maxLineLen = 512;
+	char* buf;
+	char* p;
+	char* q;
+	
+	buf = readline(prompt);
+	p = buf;
+
+	/* Get the command part of the string.  First, trim whitespace from
+	   the beginning.
+	*/
+	if (!safelySkipWhitespace(&p, maxLineLen))
+	{
+		fprintf(stderr,
+				"jvmdb: Error.  Input line exceeded %d characters.\n",
+				maxLineLen);
+		free(buf);
+		return 0;
+	}
+
+	/* Null command?
+	*/
+	if (*p == '\0')
+	{
+		free(buf);
+		return 0;
+	}
+
+	/* Skip over the command part.
+	*/
+	q = p;
+	if (!safelySkipNonWhitespace(&q, maxLineLen - (q - buf)))
+	{
+		fprintf(stderr,
+				"jvmdb: Error.  Input line exceeded %d characters.\n",
+				maxLineLen);
+		free(buf);
+		return 0;
+	}
+		
+	/* Get the argument part of the command.
+	*/
+	if (*q == '\0')
+	{
+		/* No argument part - just pass NULL as args to the command
+		   handler.
+		*/
+		q = NULL;
+	}
+	else
+	{
+		*q = '\0';
+		q++;
+
+		/* Trim whitespace from the beginning of the argument part.
+		*/
+		if (!safelySkipWhitespace(&q, maxLineLen - (q - buf)))
+		{
+			fprintf(stderr,
+					"jvmdb: Error.  Input line exceeded %d characters.\n",
+					maxLineLen);
+			free(buf);
+			return 0;
+		}
+			
+		if (*q == '\0')
+		{
+			/* Aha!  No argument part, but the shameful user tried to fool us!
+			*/
+			q = NULL;
+		}
+	}
+
+	if (p != NULL)
+	{
+		*cmd = strdup(p);
+	}
+	else
+	{
+		*cmd = (char*)malloc(sizeof(char*));
+		*cmd = NULL;
+	}
+
+	if (q != NULL)
+	{
+		*args = strdup(q);
+	}
+	else
+	{
+		*args = (char*)malloc(sizeof(char*));
+		*args = NULL;
+	}
+
+	free(buf);
+
+	return 1;
+}
+
+static int checkAndDispatchCommand(char* cmd,
+								   char* args,
+								   char* validCmds[],
+								   int nCmds,
+								   int (*cmdHandlers[])(char*))
+{
+	int i;
+
+	if (strlen(cmd) > strlen(validCmds[0]))
+	{
+		fprintf(stderr, "jvmdb: Error.  Unrecognized command.\n");
+		return 0;
+	}
+
+	for (i = 0; i < nCmds; i++)
+	{
+		if (strstr(validCmds[i], cmd) == validCmds[i])
+		{
+			break;
+		}
+	}
+
+	if (i == nCmds)
+	{
+		fprintf(stderr, "jvmdb: Error.  Unrecognized command.\n");
+		return 0;
+	}
+	else
+	{
+		if (cmdHandlers[i](args))
+		{
+			return 1;
+		}
+		else
+		{
+			return 2;
+		}
+	}
+}
+
+static int safelySkipWhitespace(char** s, int maxLen)
+{
+	int i;
+	
+	for (i = 0; i < maxLen; i++)
+	{
+		if (**s != ' ' && **s != '\t')
+		{
+			return 1;
+		}
+		else
+		{
+			(*s)++;
+		}
+	}
+
+	/* Line too long.
+	*/
+	return 0;
+}
+
+static int safelySkipNonWhitespace(char** s, int maxLen)
+{
+	int i;
+	
+	for (i = 0; i < maxLen; i++)
+	{
+		if (**s == ' ' || **s == '\t' || **s == '\0')
+		{
+			return 1;
+		}
+		else
+		{
+			(*s)++;
+		}
+	}
+
+	/* Line too long.
+	*/
+	return 0;
+}
+
+/* End of jpdaBackend.c */
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/libjpdaBackend.so and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/libjpdaBackend.so differ
Binary files kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/libjvmdiClient.so and kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/libjvmdiClient.so differ
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/localVars.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/localVars.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/localVars.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/localVars.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,44 @@
+
+#include "jvmdi.h"
+
+jvmdiError GetLocalObject(jframeID frame, jint slot, jobject* valuePtr)
+{
+}
+
+jvmdiError GetLocalInt(jframeID frame, jint slot, jint* valuePtr)
+{
+}
+
+jvmdiError GetLocalLong(jframeID frame, jint slot, jlong* valuePtr)
+{
+}
+
+jvmdiError GetLocalFloat(jframeID frame, jint slot, jfloat* valuePtr)
+{
+}
+
+jvmdiError GetLocalDouble(jframeID frame, jint slot, jdouble* valuePtr)
+{
+}
+
+jvmdiError Set LocalObject(jframeID frame, jint slot, jobject value)
+{
+}
+
+jvmdiError Set LocalInt(jframeID frame, jint slot, jint value)
+{
+}
+
+jvmdiError Set LocalLong(jframeID frame, jint slot, jlong value)
+{
+}
+
+jvmdiError Set LocalFloat(jframeID frame, jint slot, jfloat value)
+{
+}
+
+jvmdiError Set LocalDouble(jframeID frame, jint slot, jdouble value)
+{
+}
+
+/* End of local_vars.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/methodInfo.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/methodInfo.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/methodInfo.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/methodInfo.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,76 @@
+
+#include "jvmdi.h"
+
+jvmdiError GetMethodName(jclass clazz, jmethodID method,
+						 char** namePtr, char** signaturePtr)
+{
+}
+
+jvmdiError GetMethodDeclaringClass(jclass clazz, jmethodID method,
+								   jclass* declaringClassPtr)
+{
+}
+
+jvmdiError GetMethodModifiers(jclass clazz, jmethodID method,
+							  jint* modifiersPtr)
+{
+}
+
+jvmdiError GetMaxStack(jclass clazz, jmethodID method, jint* maxPtr)
+{
+}
+
+jvmdiError GetMaxLocals(jclass clazz, jmethodID method, jint* maxPtr)
+{
+}
+
+jvmdiError GetArgumentsSize(jclass clazz, jmethodID method, jint* sizePtr)
+{
+}
+
+jvmdiError GetLineNumberTable(jclass clazz, jmethodID method,
+							  jint* entryCountPtr,
+							  JVMDI_line_number_entry** tablePtr)
+{
+}
+
+jvmdiError GetMethodLocation(jclass clazz, jmethodID method,
+							 jlocation* startLocationPtr,
+							 jlocation* endLocationptr)
+{
+}
+
+jvmdiError GetLocalVariableTable(jclass clazz, jmethodID method,
+								 jint* entryCountPtr,
+								 JVMDI_local_variable_entry** tablePtr)
+{
+}
+
+jvmdiError GetExceptionhandlerTable(jclass clazz, jmethodID method,
+									jint* entryCountPtr,
+									JVMDI_exception_handler_entry** tablePtr)
+{
+}
+
+jvmdiError GetThrownExceptions(jclass clazz, jmethodID method,
+							   jint* exceptioncountPtr,
+							   jclass** exceptionsPtr)
+{
+}
+
+jvmdiError GetByteCodes(jclass clazz, jmethodID method, jint* bytecodeCountPtr,
+						jbyte** bytecodesPtr)
+{
+}
+
+jvmdiError IsMethodNative(jclass clazz, jmethodID method,
+						  jboolean* isNativePtr)
+{
+}
+
+jvmdiError IsMethodSynthetic(jclass clazz, jmethodID method,
+							 jboolean* isSyntheticPtr)
+{
+}
+
+/* End of method_info.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/misc.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/misc.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/misc.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/misc.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,21 @@
+
+#include "jvmdi.h"
+
+jvmdiError GetLoadedClasses(jint* classCountPtr, jclass** classesPtr)
+{
+}
+
+jvmdiError GetClassLoaderClasses(jobject initiatingLoader,
+								 jint* classCountPtr, jclass** classesPtr)
+{
+}
+
+jvmdiError GetVersionNumber(jint* versionPtr)
+{
+}
+
+jvmdiError GetCapabilities(JVMDI_capabilities* capabilitiesPtr)
+{
+}
+
+/* End of misc.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/mm.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/mm.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/mm.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/mm.c	1999-12-07 20:57:42.000000000 -0500
@@ -0,0 +1,19 @@
+
+/* Memory Managment
+*/
+
+#include "jvmdi.h"
+
+jvmdiError SetAllocationHooks(JVMDI_AllocHook, JVMDI_DeallocHook)
+{
+}
+
+jvmdiError Allocate(jlong size, jbyte** memPtr)
+{
+}
+
+jvmdiError Deallocate(jbyte* mem /* FIXME: sic, they used "memPtr" before */)
+{
+}
+
+/* End of mm.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/noJVMDIClientLibError.test-case kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/noJVMDIClientLibError.test-case
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/noJVMDIClientLibError.test-case	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/noJVMDIClientLibError.test-case	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,2 @@
+Error loading JVMDI client library.
+NotASharedLibrary: cannot open shared object file: No such file or directory
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/object_info.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/object_info.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/object_info.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/object_info.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,12 @@
+
+#include "jvmdi.h"
+
+jvmdiError GetObjectHashCode(jobject object, jint* hashCodePtr)
+{
+}
+
+jvmdiError GetMonitorInfo(jobject, JVMDI_monitor_info* infoPtr)
+{
+}
+
+/* End of object_info.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/sockhelp.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/sockhelp.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/sockhelp.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/sockhelp.c	1999-12-27 13:32:46.000000000 -0500
@@ -0,0 +1,323 @@
+/*
+ *  This file is provided for use with the unix-socket-faq.  It is public
+ *  domain, and may be copied freely.  There is no copyright on it.  The
+ *  original work was by Vic Metcalfe (vic at brutus.tlug.org), and any
+ *  modifications made to that work were made with the understanding that
+ *  the finished work would be in the public domain.
+ *
+ *  If you have found a bug, please pass it on to me at the above address
+ *  acknowledging that there will be no copyright on your work.
+ *
+ *  The most recent version of this file, and the unix-socket-faq can be
+ *  found at http://www.interlog.com/~vic/sock-faq/.
+ */
+
+#include "sockhelp.h"
+
+/* Take a service name, and a service type, and return a port number.  If the
+   service name is not found, it tries it as a decimal number.  The number
+   returned is byte ordered for the network. */
+int atoport(service, proto)
+char *service;
+char *proto;
+{
+  int port;
+  long int lport;
+  struct servent *serv;
+  char *errpos;
+
+  /* First try to read it from /etc/services */
+  serv = getservbyname(service, proto);
+  if (serv != NULL)
+    port = serv->s_port;
+  else { /* Not in services, maybe a number? */
+    lport = strtol(service,&errpos,0);
+    if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) )
+      return -1; /* Invalid port address */
+    port = htons(lport);
+  }
+  return port;
+}
+
+/* Converts ascii text to in_addr struct.  NULL is returned if the address
+   can not be found. */
+struct in_addr *atoaddr(address)
+char *address;
+{
+  struct hostent *host;
+  static struct in_addr saddr;
+
+  /* First try it as aaa.bbb.ccc.ddd. */
+  saddr.s_addr = inet_addr(address);
+  if (saddr.s_addr != -1) {
+    return &saddr;
+  }
+  host = gethostbyname(address);
+  if (host != NULL) {
+    return (struct in_addr *) *host->h_addr_list;
+  }
+  return NULL;
+}
+
+/* This function listens on a port, and returns connections.  It forks
+   returns off internally, so your main function doesn't have to worry
+   about that.  This can be confusing if you don't know what is going on.
+   The function will create a new process for every incoming connection,
+   so in the listening process, it will never return.  Only when a connection
+   comes in, and we create a new process for it will the function return.
+   This means that your code that calls it should _not_ loop.
+
+   The parameters are as follows:
+     socket_type: SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets)
+     port: The port to listen on.  Remember that ports < 1024 are
+       reserved for the root user.  Must be passed in network byte
+       order (see "man htons").
+     listener: This is a pointer to a variable for holding the file
+       descriptor of the socket which is being used to listen.  It
+       is provided so that you can write a signal handler to close
+       it in the event of program termination.  If you aren't interested,
+       just pass NULL.  Note that all modern unixes will close file
+       descriptors for you on exit, so this is not required. */
+int get_connection(socket_type, port, listener)
+int socket_type;
+u_short port;
+int *listener;
+{
+  struct sockaddr_in address;
+  int listening_socket;
+  int connected_socket = -1;
+  int new_process;
+  int reuse_addr = 1;
+
+  /* Setup internet address information.  
+     This is used with the bind() call */
+  memset((char *) &address, 0, sizeof(address));
+  address.sin_family = AF_INET;
+  address.sin_port = port;
+  address.sin_addr.s_addr = htonl(INADDR_ANY);
+
+  listening_socket = socket(AF_INET, socket_type, 0);
+  if (listening_socket < 0) {
+    perror("socket");
+    exit(EXIT_FAILURE);
+  }
+
+  if (listener != NULL)
+    *listener = listening_socket;
+
+  setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse_addr, 
+			 sizeof(reuse_addr));
+
+  if (bind(listening_socket, (struct sockaddr *) &address, 
+    sizeof(address)) < 0) {
+    perror("bind");
+    close(listening_socket);
+    exit(EXIT_FAILURE);
+  }
+
+  if (socket_type == SOCK_STREAM) {
+    listen(listening_socket, 5); /* Queue up to five connections before
+                                  having them automatically rejected. */
+
+    while(connected_socket < 0) {
+      connected_socket = accept(listening_socket, NULL, NULL);
+      if (connected_socket < 0) {
+        /* Either a real error occured, or blocking was interrupted for
+           some reason.  Only abort execution if a real error occured. */
+        if (errno != EINTR) {
+          perror("accept");
+          close(listening_socket);
+          exit(EXIT_FAILURE);
+        } else {
+          continue;    /* don't fork - do the accept again */
+        }
+      }
+
+      new_process = fork();
+      if (new_process < 0) {
+        perror("fork");
+        close(connected_socket);
+        connected_socket = -1;
+      }
+      else { /* We have a new process... */
+        if (new_process == 0) {
+          /* This is the new process. */
+          close(listening_socket); /* Close our copy of this socket */
+	  if (listener != NULL)
+	          *listener = -1; /* Closed in this process.  We are not 
+				     responsible for it. */
+        }
+        else {
+          /* This is the main loop.  Close copy of connected socket, and
+             continue loop. */
+          close(connected_socket);
+          connected_socket = -1;
+        }
+      }
+    }
+    return connected_socket;
+  }
+  else
+    return listening_socket;
+}
+
+/* This is a generic function to make a connection to a given server/port.
+   service is the port name/number,
+   type is either SOCK_STREAM or SOCK_DGRAM, and
+   netaddress is the host name to connect to.
+   The function returns the socket, ready for action.*/
+int make_connection(service, type, netaddress)
+char *service;
+int type;
+char *netaddress;
+{
+  /* First convert service from a string, to a number... */
+  int port = -1;
+  struct in_addr *addr;
+  int sock, connected;
+  struct sockaddr_in address;
+
+  if (type == SOCK_STREAM) 
+    port = atoport(service, "tcp");
+  if (type == SOCK_DGRAM)
+    port = atoport(service, "udp");
+  if (port == -1) {
+    fprintf(stderr,"make_connection:  Invalid socket type.\n");
+    return -1;
+  }
+  addr = atoaddr(netaddress);
+  if (addr == NULL) {
+    fprintf(stderr,"make_connection:  Invalid network address.\n");
+    return -1;
+  }
+ 
+  memset((char *) &address, 0, sizeof(address));
+  address.sin_family = AF_INET;
+  address.sin_port = (port);
+  address.sin_addr.s_addr = addr->s_addr;
+
+  sock = socket(AF_INET, type, 0);
+
+  printf("Connecting to %s on port %d.\n",inet_ntoa(*addr),htons(port));
+
+  if (type == SOCK_STREAM) {
+    connected = connect(sock, (struct sockaddr *) &address, 
+      sizeof(address));
+    if (connected < 0) {
+      perror("connect");
+      return -1;
+    }
+    return sock;
+  }
+  /* Otherwise, must be for udp, so bind to address. */
+  if (bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) {
+    perror("bind");
+    return -1;
+  }
+  return sock;
+}
+
+/* This is just like the read() system call, accept that it will make
+   sure that all your data goes through the socket. */
+int sock_read(sockfd, buf, count)
+int sockfd;
+char *buf;
+size_t count;
+{
+  size_t bytes_read = 0;
+  int this_read;
+
+  while (bytes_read < count) {
+    do
+      this_read = read(sockfd, buf, count - bytes_read);
+    while ( (this_read < 0) && (errno == EINTR) );
+    if (this_read < 0)
+      return this_read;
+    else if (this_read == 0)
+      return bytes_read;
+    bytes_read += this_read;
+    buf += this_read;
+  }
+  return count;
+}
+
+/* This is just like the write() system call, accept that it will
+   make sure that all data is transmitted. */
+int sock_write(sockfd, buf, count)
+int sockfd;
+char *buf;
+size_t count;
+{
+  size_t bytes_sent = 0;
+  int this_write;
+
+  while (bytes_sent < count) {
+    do
+      this_write = write(sockfd, buf, count - bytes_sent);
+    while ( (this_write < 0) && (errno == EINTR) );
+    if (this_write <= 0)
+      return this_write;
+    bytes_sent += this_write;
+    buf += this_write;
+  }
+  return count;
+}
+
+/* This function reads from a socket, until it recieves a linefeed
+   character.  It fills the buffer "str" up to the maximum size "count".
+
+   This function will return -1 if the socket is closed during the read
+   operation.
+
+   Note that if a single line exceeds the length of count, the extra data
+   will be read and discarded!  You have been warned. */
+int sock_gets(sockfd, str, count)
+int sockfd;
+char *str;
+size_t count;
+{
+  int bytes_read;
+  int total_count = 0;
+  char *current_position;
+  char last_read = 0;
+
+  current_position = str;
+  while (last_read != 10) {
+    bytes_read = read(sockfd, &last_read, 1);
+    if (bytes_read <= 0) {
+      /* The other side may have closed unexpectedly */
+      return -1; /* Is this effective on other platforms than linux? */
+    }
+    if ( (total_count < count) && (last_read != 10) && (last_read !=13) ) {
+      current_position[0] = last_read;
+      current_position++;
+      total_count++;
+    }
+  }
+  if (count > 0)
+    current_position[0] = 0;
+  return total_count;
+}
+
+/* This function writes a character string out to a socket.  It will 
+   return -1 if the connection is closed while it is trying to write. */
+int sock_puts(sockfd, str)
+int sockfd;
+char *str;
+{
+  return sock_write(sockfd, str, strlen(str));
+}
+
+/* This ignores the SIGPIPE signal.  This is usually a good idea, since
+   the default behaviour is to terminate the application.  SIGPIPE is
+   sent when you try to write to an unconnected socket.  You should
+   check your return codes to make sure you catch this error! */
+void ignore_pipe(void)
+{
+  struct sigaction sig;
+
+  sig.sa_handler = SIG_IGN;
+  sig.sa_flags = 0;
+  sigemptyset(&sig.sa_mask);
+  sigaction(SIGPIPE,&sig,NULL);
+}
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/test.sh kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/test.sh
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/test.sh	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/test.sh	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,9 @@
+
+rm -f test.stdout test.stderr
+kaffe -XrunNotASharedLibrary:hi,chico HiChico 1>test.stdout 2>test.stderr && echo "Error: kaffe did not return failure status"
+diff test.stderr noJVMDIClientLibError.test-case || echo "Error: diff failed"
+[ "`ls -s test.stdout`" != "   0 test.stdout" ] && echo "Error: stdout test failed"
+
+kaffe Hello && echo "Error: kaffe returned failure status"
+
+# End of test.sh
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/test.stderr kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/test.stderr
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/test.stderr	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/test.stderr	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,2 @@
+Error loading JVMDI client library.
+NotASharedLibrary: cannot open shared object file: No such file or directory
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/threadExec.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/threadExec.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/threadExec.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/threadExec.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,49 @@
+/* Thread Execution Functions
+*/
+
+#include "jvmdi.h"
+
+jvmdiError GetThreadStatus(jthread thread, jint* threadStatusPtr,
+						   jint* suspendStatusPtr)
+{
+}
+
+jvmdiError GetAllThreads(jint* threadsCountPtr, jthread** threadsPtr)
+{
+}
+
+jvmdiError SuspendThread(jthread thread)
+{
+}
+
+jvmdiError ResumeThread(jthread thread)
+{
+}
+
+jvmdiError StopThread(jthread thread, jobject exception)
+{
+}
+
+jvmdiError InterruptThread(jthread thread)
+{
+}
+
+jvmdiError GetThreadInfo(jthread thread, JVMDI_thread_info* infoPtr)
+{
+}
+
+jvmdiError GetOwnedMonitorInfo(jthread thread,
+							   JVMDI_owned_monitor_info* infoPtr)
+{
+}
+
+jvmdierror GetCurrentContendedMonitor(jthread thread, jobject* monitorPtr)
+{
+}
+
+jvmdiError RunDebugThread(jthread thread, JVMDIR_StartFunction proc,
+						  void* arg, int priority)
+{
+}
+
+/* End of thread_exec.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/threadGroups.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/threadGroups.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/threadGroups.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/threadGroups.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,15 @@
+
+#include "jvmdi.h"
+
+jvmdiError GetThreadGroupInfo(jthreadGroup goup,
+							  JVMDIR_thread_group_info* infoPtr)
+{
+}
+
+jvmdiError GetThreadGroupChildren(jthreadGroup group, jint* threadCountPtr,
+								  jthread** threadsPtr, jint* groupCountPtr,
+								  jthreadGroup** groupsPtr)
+{
+}
+
+/* End of thread_groups.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/watches.c kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/watches.c
--- kaffe-1.0.5/kaffe/kaffevm/jpdaBackend/watches.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jpdaBackend/watches.c	1999-12-07 20:57:43.000000000 -0500
@@ -0,0 +1,20 @@
+
+#include "jvmdi.h"
+
+jvmdiError SetFieldAccessWatch(jclass clazz, jfieldID field)
+{
+}
+
+jvmdiError ClearFieldAccessWatch(jclass clazz, jfieldID field)
+{
+}
+
+jvmdiError SetFieldModificationWatch(jclass clazz, jfieldID field)
+{
+}
+
+jvmdiError ClearFieldModificationWatch(jclass clazz, jfieldID field)
+{
+}
+
+/* End of watches.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jvmdi.c kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdi.c
--- kaffe-1.0.5/kaffe/kaffevm/jvmdi.c	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdi.c	2000-01-11 19:05:35.000000000 -0500
@@ -0,0 +1,526 @@
+
+/* Outside Interface API */
+#include "jvmdi.h"
+
+/* Inside Event Interface API */
+#include "jvmdiEvents.h"
+#include "jvmdiRawMonitor.h"
+
+/* FIXME: Duh!  This can't stay global, static */
+JVMDI_EventHook theHook;
+
+jvmdiError SetEventHook(JVMDI_EventHook hook)
+{
+	JVMDI_RawMonitor m;
+	jvmdiError err;
+
+	/* Lock
+	*/
+	if ((err = CreateAndEnterRawMonitor("__JVMDI_Lock", &m)) !=
+		JVMDI_ERROR_NONE)
+	{
+		return err;
+	}
+	
+	/* Set thread-specific hook
+	*/
+	theHook = hook;
+	
+	/* Unlock
+	*/
+	if ((err = ExitAndDestroyRawMonitor(m)) != JVMDI_ERROR_NONE)
+	{
+		/* Unset thread-specific hook
+		*/
+		theHook = NULL;
+		
+		return err;
+	}
+	
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError SetEventNotificationMode(jint mode, jint eventType,
+									jthread thead, ...)
+{
+	JVMDI_RawMonitor m;
+	jvmdiError err;
+	
+	/* Lock
+	*/
+	if ((err = CreateAndEnterRawMonitor("__JVMDI_Lock", &m)) !=
+		JVMDI_ERROR_NONE)
+	{
+		return err;
+	}
+	
+	/* Set thread-specific event notify mask */
+	
+	/* Unlock
+	*/
+	if ((err = ExitAndDestroyRawMonitor(m)) != JVMDI_ERROR_NONE)
+	{
+		/* Unset thread-specific event notify mask */
+		
+		return err;
+	}
+	
+	return JVMDI_ERROR_NONE;
+}
+
+static void fireEvent(JVMDI_Event e)
+{
+	JNIEnv* env;
+	
+	/* Get a JNIEnv
+	*/
+	env = (JNIEnv*)malloc(sizeof(*env));
+
+	/* Call the hook
+	*/
+	if (theHook)
+	{
+		(void)theHook(env, &e);
+	}
+
+	/* dealloc JNIEnv
+	*/
+	free(env);
+}
+
+void fireSingleStepEvent(jthread thread,
+						 jclass clazz,
+						 jmethodID method,
+						 jlocation location)
+{
+	JVMDI_Event* e;
+	JVMDI_single_step_event_data* ss;
+
+	/* +++ FIXME */
+	printf("SingleStepEvent!! pc is %x\n", (int)location);
+	/* --- FIXME */
+	   
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_SINGLE_STEP;
+	ss = (JVMDI_single_step_event_data*)(&(e->u));
+	ss->thread = thread;
+	ss->clazz = clazz;
+	ss->method = method;
+	ss->location = location;
+
+	fireEvent(*e);
+	
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireBreakpointEvent(jthread thread, jclass clazz,
+						 jmethodID method, jlocation location)
+{
+	JVMDI_Event* e;
+	JVMDI_breakpoint_event_data* b;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_BREAKPOINT;
+	b = (JVMDI_breakpoint_event_data*)(&(e->u));
+	b->thread = thread;
+	b->clazz = clazz;
+	b->method = method;
+	b->location = location;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+static void frameEvent(jint kind,
+					   jthread thread,
+					   jclass clazz,
+					   jmethodID method,
+					   jframeID frame)
+{
+	JVMDI_Event* e;
+	JVMDI_frame_event_data* fe;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = kind;
+	fe = (JVMDI_frame_event_data*)(&(e->u));
+	fe->thread = thread;
+	fe->clazz = clazz;
+	fe->method = method;
+	fe->frame = frame;
+
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireFramePopEvent(jthread thread, jclass clazz,
+					   jmethodID method, jframeID frame)
+{
+	frameEvent(JVMDI_EVENT_FRAME_POP, thread, clazz, method, frame);
+}
+
+void fireMethodEntryEvent(jthread thread, jclass clazz,
+						  jmethodID method, jframeID frame)
+{
+	frameEvent(JVMDI_EVENT_METHOD_ENTRY, thread, clazz, method, frame);
+}
+
+void fireMethodExitEvent(jthread thread, jclass clazz,
+						 jmethodID method, jframeID frame)
+{
+	frameEvent(JVMDI_EVENT_METHOD_EXIT, thread, clazz, method, frame);
+}
+
+void fireFieldAccessEvent(jthread thread, jclass clazz,
+						  jmethodID method, jlocation location,
+						  jclass field_clazz, jobject object,
+						  jfieldID field)
+{
+	JVMDI_Event* e;
+	JVMDI_field_access_event_data* fa;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_FIELD_ACCESS;
+	fa = (JVMDI_field_access_event_data*)(&(e->u));
+	fa->thread = thread;
+	fa->clazz = clazz;
+	fa->method = method;
+	fa->location = location;
+	fa->field_clazz = field_clazz;
+	fa->object = object;
+	fa->field = field;
+
+	fireEvent(*e);
+	
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireFieldModificationEvent(jthread thread, jclass clazz,
+								jmethodID method, jlocation location,
+								jclass field_clazz, jobject object,
+								jfieldID field, char signature_type,
+								jvalue new_value)
+{
+	JVMDI_Event* e;
+	JVMDI_field_modification_event_data* fm;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_FIELD_MODIFICATION;
+	fm = (JVMDI_field_modification_event_data*)(&(e->u));
+	fm->thread = thread;
+	fm->clazz = clazz;
+	fm->method = method;
+	fm->location = location;
+	fm->field_clazz = field_clazz;
+	fm->object = object;
+	fm->field = field;
+	fm->signature_type = signature_type;
+	fm->new_value = new_value;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireExceptionEvent(jthread thread, jclass clazz,
+						jmethodID method, jlocation location,
+						jobject exception, jclass catch_clazz,
+						jmethodID catch_method, jlocation catch_location)
+{
+	JVMDI_Event* e;
+	JVMDI_exception_event_data* ex;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_EXCEPTION;
+	ex = (JVMDI_exception_event_data*)(&(e->u));
+	ex->thread = thread;
+	ex->clazz = clazz;
+	ex->method = method;
+	ex->location = location;
+	ex->exception = exception;
+	ex->catch_clazz = catch_clazz;
+	ex->catch_method = catch_method;
+	ex->catch_location = catch_location;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireExceptionCatchEvent(jthread thread, jclass clazz,
+							 jmethodID method, jlocation location,
+							 jobject exception)
+{
+	JVMDI_Event* e;
+	JVMDI_exception_catch_event_data* ec;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_EXCEPTION_CATCH;
+	ec = (JVMDI_exception_catch_event_data*)(&(e->u));
+	ec->thread = thread;
+	ec->clazz = clazz;
+	ec->method = method;
+	ec->location = location;
+	ec->exception = exception;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireUserDefinedEvent(jobject object, jint key)
+{
+	JVMDI_Event* e;
+	JVMDI_user_event_data* ud;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_USER_DEFINED;
+	ud = (JVMDI_user_event_data*)(&(e->u));
+	ud->object = object;
+	ud->key = key;
+
+	fireEvent(*e);
+	
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+static void threadChangeEvent(jint kind, jthread thread)
+{
+	JVMDI_Event* e;
+	JVMDI_thread_change_event_data* tc;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = kind;
+	tc = (JVMDI_thread_change_event_data*)(&(e->u));
+	tc->thread = thread;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireThreadStartEvent(jthread thread)
+{
+	threadChangeEvent(JVMDI_EVENT_THREAD_START, thread);
+}
+
+void fireThreadEndEvent(jthread thread)
+{
+	threadChangeEvent(JVMDI_EVENT_THREAD_END, thread);
+}
+
+static void classEvent(jint kind, jthread thread, jclass clazz)
+{
+	JVMDI_Event* e;
+	JVMDI_class_event_data* c;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = kind;
+	c = (JVMDI_class_event_data*)(&(e->u));
+	c->thread = thread;
+	c->clazz = clazz;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+	
+void fireClassLoadEvent(jthread thread, jclass clazz)
+{
+	classEvent(JVMDI_EVENT_CLASS_LOAD, thread, clazz);
+}
+
+void fireClassUnloadEvent(jthread thread, jclass clazz)
+{
+	classEvent(JVMDI_EVENT_CLASS_UNLOAD, thread, clazz);
+}
+
+void fireClassPrepareEvent(jthread thread, jclass clazz)
+{
+	classEvent(JVMDI_EVENT_CLASS_PREPARE, thread, clazz);
+}
+
+void fireVMInitEvent(void)
+{
+	JVMDI_Event* e;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	
+	e->kind = JVMDI_EVENT_VM_INIT;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireVMDeathEvent(void)
+{
+	JVMDI_Event* e;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_VM_DEATH;
+
+	fireEvent(*e);
+	
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+jvmdiError CreateRawMonitor(char* name, JVMDI_RawMonitor* monitorPtr)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError DestroyRawMonitor(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorEnter(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorExit(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorWait(JVMDI_RawMonitor monitor, jlong millis)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorNotify(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorNotifyAll(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError CreateAndEnterRawMonitor(char* name, JVMDI_RawMonitor* monitorPtr)
+{
+	jvmdiError err;
+	
+	if ((err = CreateRawMonitor(name, monitorPtr) != JVMDI_ERROR_NONE))
+	{
+		return err;
+	}
+	else
+	{
+		if ((err = RawMonitorEnter(*monitorPtr) != JVMDI_ERROR_NONE))
+		{
+			(void)DestroyRawMonitor(*monitorPtr);
+			return err;
+		}
+	}
+	
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError ExitAndDestroyRawMonitor(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+/* End of jvmdi.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jvmdi.h kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdi.h
--- kaffe-1.0.5/kaffe/kaffevm/jvmdi.h	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdi.h	1999-12-07 20:56:44.000000000 -0500
@@ -0,0 +1,491 @@
+
+#ifndef __jvmdi_h
+#define __jvmdi_h
+
+/*
+   FIXME.  QUESTION: Can I lift this file from Sun?  If so, lets use theirs for
+   compatibility sake.  We can also leverage some of their testing effort
+   for free.  Just in case I've derived this myself from the spec.
+*/
+
+/* NOTES
+
+   All the "name" parameters are commented with "Name in UTF-8".  I've omited
+   those in favor of mentioning it once here.
+
+*/
+
+#include <jtypes.h>
+#include <jthread.h>
+
+/* FIXME: No way these are right...
+*/
+typedef jlong jthreadGroup;
+typedef jlong jframeID;
+typedef jlong jlocation;
+
+typedef struct {
+	jlong q;
+} JVMDI_local_variable_entry;
+
+typedef struct {
+	jlong q;
+} JVMDI_exception_handler_entry;
+
+typedef struct {
+	jlong q;
+} JVMDI_RawMonitor;
+
+/* FIXME: what should this really be?
+*/
+typedef jint jvmdiError;
+
+typedef struct
+{
+	jthread thread;
+	jclass clazz;
+	jmethodID method;
+	jlocation location;
+} JVMDI_single_step_event_data;
+
+typedef struct
+{
+	jthread thread;
+	jclass clazz;
+	jmethodID method;
+	jlocation location;
+} JVMDI_breakpoint_event_data;
+
+typedef struct
+{
+	jthread thread;
+	jclass clazz;
+	jmethodID method;
+	jlocation location;
+	jclass field_clazz;
+	jobject object;
+	jfieldID field;
+} JVMDI_field_access_event_data;
+
+typedef struct
+{
+	jthread thread;
+	jclass clazz;
+	jmethodID method;
+	jlocation location;
+	jclass field_clazz;
+	jobject object;
+	jfieldID field;
+	char signature_type;
+	jvalue new_value;
+} JVMDI_field_modification_event_data;
+
+typedef struct
+{
+	jthread thread;
+	jclass clazz;
+	jmethodID method;
+	jframeID frame;
+} JVMDI_frame_event_data;
+
+typedef struct
+{
+	jthread thread;
+	jclass clazz;
+	jmethodID method;
+	jlocation location;
+	jobject exception;
+	jclass catch_clazz;
+	jmethodID catch_method;
+	jlocation catch_location;
+} JVMDI_exception_event_data;
+
+typedef struct
+{
+	jthread thread;
+	jclass clazz;
+	jmethodID method;
+	jlocation location;
+	jobject exception;
+} JVMDI_exception_catch_event_data;
+
+typedef struct
+{
+	jobject object;
+	jint key;
+} JVMDI_user_event_data;
+
+typedef struct
+{
+	jthread thread;
+} JVMDI_thread_change_event_data;
+
+typedef struct
+{
+	jthread thread;
+	jclass clazz;
+} JVMDI_class_event_data;
+
+typedef struct
+{
+	jint kind;
+
+	union
+	{
+		#define JVMDI_EVENT_SINGLE_STEP 1
+		JVMDI_single_step_event_data single_step;
+
+		#define JVMDI_EVENT_BREAKPOINT 2
+		JVMDI_breakpoint_event_data breakpoint;
+		
+		#define JVMDI_EVENT_FRAME_POP 3
+		#define JVMDI_EVENT_METHOD_ENTRY 4
+		#define JVMDI_EVENT_METHOD_EXIT 5
+		JVMDI_frame_event_data frame;
+		
+		#define JVMDI_EVENT_FIELD_ACCESS 6
+		JVMDI_field_access_event_data field_access;
+		
+		#define JVMDI_EVENT_FIELD_MODIFICATION 7
+		JVMDI_field_modification_event_data field_modification;
+		
+		#define JVMDI_EVENT_EXCEPTION 8
+		JVMDI_exception_event_data exception;
+
+		#define JVMDI_EVENT_EXCEPTION_CATCH 9
+		JVMDI_exception_catch_event_data execption_catch;
+		
+		#define JVMDI_EVENT_USER_DEFINED 10
+		JVMDI_user_event_data user;
+		
+		#define JVMDI_EVENT_THREAD_END 11
+		#define JVMDI_EVENT_THREAD_START 12
+		JVMDI_thread_change_event_data thread_change;
+		
+		#define JVMDI_EVENT_CLASS_LOAD 13
+		#define JVMDI_EVENT_CLASS_UNLOAD 14
+		#define JVMDI_EVENT_CLASS_PREPARE 15
+		JVMDI_class_event_data class_event;
+
+		#define JVMDI_EVENT_VM_DEATH 16
+		#define JVMDI_EVENT_VM_INIT 17
+	} u;
+} JVMDI_Event;
+
+/* Memory Managment
+*/
+typedef jvmdiError (*JVMDI_AllocHook)(jlong size, jbyte** memPtr);
+
+typedef jvmdiError (*JVMDI_DeallocHook)(jbyte* buffer);
+
+jvmdiError SetAllocationHooks(JVMDI_AllocHook, JVMDI_DeallocHook);
+
+jvmdiError Allocate(jlong size, jbyte** memPtr);
+
+jvmdiError Deallocate(jbyte* mem /* FIXME: sic, they used "memPtr" before */);
+
+/* Thread Execution Functions
+*/
+jvmdiError GetThreadStatus(jthread thread, jint* threadStatusPtr,
+						   jint* suspendStatusPtr);
+
+jvmdiError GetAllThreads(jint* threadsCountPtr, jthread** threadsPtr);
+
+jvmdiError SuspendThread(jthread thread);
+
+jvmdiError ResumeThread(jthread thread);
+
+jvmdiError StopThread(jthread thread, jobject exception);
+
+jvmdiError InterruptThread(jthread thread);
+
+typedef struct
+{
+	char* name;
+	jint priority;
+	jboolean is_daemon;
+	jthreadGroup thread_group;
+	jobject context_class_loader;
+} JVMDI_thread_info;
+
+jvmdiError GetThreadInfo(jthread thread, JVMDI_thread_info* infoPtr);
+
+typedef struct
+{
+	jint owned_monitor_count;
+	jobject* owned_monitors;
+} JVMDI_owned_monitor_info;
+
+jvmdiError GetOwnedMonitorInfo(jthread thread,
+							   JVMDI_owned_monitor_info* infoPtr);
+
+jvmdiError GetCurrentContendedMonitor(jthread thread, jobject* monitorPtr);
+
+typedef void (*JVMDIR_StartFunction)(void*);
+
+jvmdiError RunDebugThread(jthread thread, JVMDIR_StartFunction proc,
+						  void* arg, int priority);
+
+/* Thread Groups
+*/
+jvmdiError GetTopThreadGroups(jint* groupCountPtr, jthreadGroup** groupsPtr);
+
+typedef struct
+{
+	jthreadGroup parent;
+	char* name;
+	jint max_priority;
+	jboolean is_daemon;
+} JVMDIR_thread_group_info;
+
+jvmdiError GetThreadGroupInfo(jthreadGroup goup,
+							  JVMDIR_thread_group_info* infoPtr);
+jvmdiError GetThreadGroupChildren(jthreadGroup group, jint* threadCountPtr,
+								  jthread** threadsPtr, jint* groupCountPtr,
+								  jthreadGroup** groupsPtr);
+
+/* Stack Frame Access
+*/
+jvmdiError GetFrameCount(jthread thread, jint* countPtr);
+
+jvmdiError GetCurrentFrame(jthread thread, jframeID* framePtr);
+
+jvmdiError GetCallerFrame(jframeID called, jframeID* framePtr);
+
+jvmdiError GetFrameLocation(jframeID frame, jclass* classPtr, jlocation* locationPtr);
+
+jvmdiError NotifyFramePop(jframeID frame);
+
+/* Local Variable Access
+*/
+jvmdiError GetLocalObject(jframeID frame, jint slot, jobject* valuePtr);
+
+jvmdiError GetLocalInt(jframeID frame, jint slot, jint* valuePtr);
+
+jvmdiError GetLocalLong(jframeID frame, jint slot, jlong* valuePtr);
+
+jvmdiError GetLocalFloat(jframeID frame, jint slot, jfloat* valuePtr);
+
+jvmdiError GetLocalDouble(jframeID frame, jint slot, jdouble* valuePtr);
+
+jvmdiError SetLocalObject(jframeID frame, jint slot, jobject value);
+
+jvmdiError SetLocalInt(jframeID frame, jint slot, jint value);
+
+jvmdiError SetLocalLong(jframeID frame, jint slot, jlong value);
+
+jvmdiError SetLocalFloat(jframeID frame, jint slot, jfloat value);
+
+jvmdiError SetLocalDouble(jframeID frame, jint slot, jdouble value);
+
+/* Breakpoints
+*/
+jvmdiError SetBreakpoint(jclass clazz, jmethodID method, jlocation location);
+
+jvmdiError ClearBreakpoint(jclass class, jmethodID method, jlocation location);
+
+jvmdiError ClearAllBreakpoints(void);
+
+/* Watched Fields
+*/
+jvmdiError SetFieldAccessWatch(jclass clazz, jfieldID field);
+
+jvmdiError ClearFieldAccessWatch(jclass clazz, jfieldID field);
+
+jvmdiError SetFieldModificationWatch(jclass clazz, jfieldID field);
+
+jvmdiError ClearFieldModificationWatch(jclass clazz, jfieldID field);
+
+/* Class Information
+*/
+jvmdiError GetClassSignature(jclass clazz, char** sigPtr);
+
+jvmdiError GetClassStatus(jclass clazz, char* statusPtr);
+
+jvmdiError GetSourceFileName(jclass clazz, char** sourceNamePtr);
+
+jvmdiError GetClassModifiers(jclass clazz, jint* modifiersPtr);
+
+jvmdiError GetClassMethods(jclass clazz, jint* methodCountPtr,
+						   jmethodID** methodsPtr);
+
+jvmdiError GetClassFields(jclass clazz, jint* fieldCountPtr,
+						  jfieldID** fieldsPtr);
+
+jvmdiError GetImplementedInterfaces(jclass clazz, jint* interfaceCountPtr,
+									jclass** interfacesPtr);
+
+jvmdiError IsInterface(jclass clazz, jboolean* isInterfacePtr);
+
+jvmdiError IsArrayclass(jclass clazz, jboolean* isArrayClassPyr);
+
+jvmdiError GetClassLoader(jclass clazz, jobject* classloaderPtr);
+
+/* Object Information
+*/
+jvmdiError GetObjectHashCode(jobject object, jint* hashCodePtr);
+
+typedef struct
+{
+	jthread owner;
+	jint entry_count;
+	jint waiter_count;
+	jthread* waiters;
+} JVMDI_monitor_info;
+
+jvmdiError GetMonitorInfo(jobject, JVMDI_monitor_info* infoPtr);
+
+/* Field Information
+*/
+jvmdiError GetFieldName(jclass clazz, jfieldID field, char** namePtr,
+						char** signaturePtr);
+
+jvmdiError GetFieldDeclaringClass(jclass clazz, jfieldID field,
+								  jclass* declaringClassPtr);
+
+jvmdiError GetFieldModifiers(jclass clazz, jfieldID field, jint* modifiersPtr);
+
+jvmdiError IsFieldSynthetic(jclass clazz, jfieldID field,
+							jboolean* isSyntheticPtr);
+
+/* MethodInformation
+*/
+jvmdiError GetMethodName(jclass clazz, jmethodID method,
+						 char** namePtr, char** signaturePtr);
+
+jvmdiError GetMethodDeclaringClass(jclass clazz, jmethodID method,
+								   jclass* declaringClassPtr);
+
+jvmdiError GetMethodModifiers(jclass clazz, jmethodID method,
+							  jint* modifiersPtr);
+
+
+jvmdiError GetMaxStack(jclass clazz, jmethodID method, jint* maxPtr);
+
+jvmdiError GetMaxLocals(jclass clazz, jmethodID method, jint* maxPtr);
+
+jvmdiError GetArgumentsSize(jclass clazz, jmethodID method, jint* sizePtr);
+
+typedef struct
+{
+	jlocation start_location;
+	jint line_number;
+} JVMDI_line_number_entry;
+
+jvmdiError GetLineNumberTable(jclass clazz, jmethodID method,
+							  jint* entryCountPtr,
+							  JVMDI_line_number_entry** tablePtr);
+
+jvmdiError GetMethodLocation(jclass clazz, jmethodID method,
+							 jlocation* startLocationPtr,
+							 jlocation* endLocationptr);
+
+jvmdiError GetLocalVariableTable(jclass clazz, jmethodID method,
+								 jint* entryCountPtr,
+								 JVMDI_local_variable_entry** tablePtr);
+
+jvmdiError GetExceptionhandlerTable(jclass clazz, jmethodID method,
+									jint* entryCountPtr,
+									JVMDI_exception_handler_entry** tablePtr);
+
+jvmdiError GetThrownExceptions(jclass clazz, jmethodID method,
+							   jint* exceptioncountPtr,
+							   jclass** exceptionsPtr);
+
+jvmdiError GetByteCodes(jclass clazz, jmethodID method, jint* bytecodeCountPtr,
+						jbyte** bytecodesPtr);
+
+jvmdiError IsMethodNative(jclass clazz, jmethodID method,
+						  jboolean* isNativePtr);
+
+jvmdiError IsMethodSynthetic(jclass clazz, jmethodID method,
+							 jboolean* isSyntheticPtr);
+
+/* Raw Monitor Support
+*/
+jvmdiError CreateRawMonitor(char* name, JVMDI_RawMonitor* monitorPtr);
+
+jvmdiError DestroyRawMontor(JVMDI_RawMonitor monitor);
+
+jvmdiError RawMonitorEnter(JVMDI_RawMonitor monitor);
+
+jvmdiError RawMonitorExit(JVMDI_RawMonitor monitor);
+
+jvmdiError RawMonitorwait(JVMDI_RawMonitor monitor, jlong millis);
+
+jvmdiError RawMonitorNotify(JVMDI_RawMonitor monitor);
+
+jvmdiError RawMonitorNotifyAll(JVMDI_RawMonitor monitor);
+
+/* Events
+*/
+typedef void (*JVMDI_EventHook)(JNIEnv* env, JVMDI_Event* event);
+
+jvmdiError SetEventHook(JVMDI_EventHook hook);
+
+jvmdiError SetEventNotificationMode(jint mode, jint eventType,
+									jthread thead, ...);
+
+/* Miscellaneous Functions
+*/
+jvmdiError GetLoadedClasses(jint* classCountPtr, jclass** classesPtr);
+
+jvmdiError GetClassLoaderClasses(jobject initiatingLoader,
+								 jint* classCountPtr, jclass** classesPtr);
+
+jvmdiError GetVersionNumber(jint* versionPtr);
+
+typedef struct
+{
+	unsigned int can_watch_field_modification;
+	unsigned int can_watch_field_access;
+	unsigned int can_get_bytecodes;
+	unsigned int can_get_synthetic_attribute;
+	unsigned int can_get_owned_monitor_info;
+	unsigned int can_get_current_contended_monitor;
+	unsigned int can_get_monitor_info;
+} JVMDI_capabilities;
+
+jvmdiError GetCapabilities(JVMDI_capabilities* capabilitiesPtr);
+
+/* Universal Errors
+*/
+#define JVMDI_ERROR_NONE 0
+#define JVMDI_ERROR_OUT_OF_MEMORY 1
+#define JVMDI_ERROR_ACCESS_DENIED 2
+#define JVMDI_ERROR_UNATTACHED_THREAD 3
+#define JVMDI_ERROR_VM_DEAD 4
+#define JVMDI_ERROR_INTERNAL 5
+
+/* Function Specific Errors
+*/
+#define JVMDI_ERROR_INVALID_THREAD 6
+#define JVMDI_ERROR_INVALID_FIELDID 7
+#define JVMDI_ERROR_INVALID_METHODID 8
+#define JVMDI_ERROR_INVALID_LOCATION 9
+#define JVMDI_ERROR_INVALID_FRAMEID 10
+#define JVMDI_ERROR_NO_MORE_FRAMES 11
+#define JVMDI_ERROR_OPAQUE_FRAME 12
+#define JVMDI_ERROR_NOT_CURRENT_FRAME 13
+#define JVMDI_ERROR_TYPE_MISMATCH 14
+#define JVMDI_ERROR_INVALID_SLOT 15
+#define JVMDI_ERROR_DUPLICATE 16
+#define JVMDI_ERROR_THREAD_NOT_SUSPENDED 17
+#define JVMDI_ERROR_THREAD_SUSPENDED 18
+#define JVMDI_ERROR_INVALID_OBJECT 19
+#define JVMDI_ERROR_INVLAID_CLASS 20
+#define JVMDI_ERROR_CLASS_NOT_PREPARED 21
+#define JVMDI_ERROR_NULL_POINTER 22
+#define JVMDI_ERROR_ABSENT_INFORMATION 23
+#define JVMDI_ERROR_INVALID_EVENT_TYPE 24
+#define JVMDI_ERROR_NOT_IMPLEMENTED 25
+#define JVMDI_ERROR_INVALID_THREAD_GROUP 26
+#define JVMDI_ERROR_INVALID_PRIORITY 27
+#define JVMDI_ERROR_NOT_FOUND 28
+#define JVMDI_ERROR_INAVLID_MONITOR 29
+#define JVMDI_ERROR_ILLEGAL_ARGUMENT 30
+#define JVMDI_ERROR_NOT_MONITOR_OWNER 31
+#define JVMDI_ERROR_INTERRUPT 32
+#define JVMDI_ERROR_INVALID_TYPESTATE 33
+
+#endif
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jvmdiEvents.c-save kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdiEvents.c-save
--- kaffe-1.0.5/kaffe/kaffevm/jvmdiEvents.c-save	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdiEvents.c-save	1999-12-07 20:56:44.000000000 -0500
@@ -0,0 +1,467 @@
+
+/* Outside Interface API */
+#include "jvmdi.h"
+
+/* Inside Event Interface API */
+#include "jvmdiEvents.h"
+#include "jvmdiRawMonitor.h"
+
+/* FIXME: Duh!  This can't stay global, static */
+JVMDI_EventHook theHook;
+
+jvmdiError SetEventHook(JVMDI_EventHook hook)
+{
+	JVMDI_RawMonitor m;
+	jvmdiError err;
+
+	/* Lock
+	*/
+	if ((err = CreateAndEnterRawMonitor("__JVMDI_Lock", &m)) !=
+		JVMDI_ERROR_NONE)
+	{
+		return err;
+	}
+	
+	/* Set thread-specific hook
+	*/
+	theHook = hook;
+	
+	/* Unlock
+	*/
+	if ((err = ExitAndDestroyRawMonitor(m)) != JVMDI_ERROR_NONE)
+	{
+		/* Unset thread-specific hook
+		*/
+		theHook = NULL;
+		
+		return err;
+	}
+	
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError SetEventNotificationMode(jint mode, jint eventType,
+									jthread thead, ...)
+{
+	JVMDI_RawMonitor m;
+	jvmdiError err;
+	
+	/* Lock
+	*/
+	if ((err = CreateAndEnterRawMonitor("__JVMDI_Lock", &m)) !=
+		JVMDI_ERROR_NONE)
+	{
+		return err;
+	}
+	
+	/* Set thread-specific event notify mask */
+	
+	/* Unlock
+	*/
+	if ((err = ExitAndDestroyRawMonitor(m)) != JVMDI_ERROR_NONE)
+	{
+		/* Unset thread-specific event notify mask */
+		
+		return err;
+	}
+	
+	return JVMDI_ERROR_NONE;
+}
+
+static void fireEvent(JVMDI_Event e)
+{
+	JNIEnv* env;
+	
+	/* Get a JNIEnv
+	*/
+	env = (JNIEnv*)malloc(sizeof(*env));
+
+	/* Call the hook
+	*/
+	if (theHook)
+	{
+		(void)theHook(env, &e);
+	}
+
+	/* dealloc JNIEnv
+	*/
+	free(env);
+}
+
+void fireSingleStepEvent(jthread thread,
+						 jclass clazz,
+						 jmethodID method,
+						 jlocation location)
+{
+	JVMDI_Event* e;
+	JVMDI_single_step_event_data* ss;
+
+	/* +++ FIXME */
+	printf("SingleStepEvent!! pc is %x\n", location);
+	/* --- FIXME */
+	   
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_SINGLE_STEP;
+	ss = (JVMDI_single_step_event_data*)(&(e->u));
+	ss->thread = thread;
+	ss->clazz = clazz;
+	ss->method = method;
+	ss->location = location;
+
+	fireEvent(*e);
+	
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireBreakpointEvent(jthread thread, jclass clazz,
+						 jmethodID method, jlocation location)
+{
+	JVMDI_Event* e;
+	JVMDI_breakpoint_event_data* b;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_BREAKPOINT;
+	b = (JVMDI_breakpoint_event_data*)(&(e->u));
+	b->thread = thread;
+	b->clazz = clazz;
+	b->method = method;
+	b->location = location;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+static void frameEvent(jint kind,
+					   jthread thread,
+					   jclass clazz,
+					   jmethodID method,
+					   jframeID frame)
+{
+	JVMDI_Event* e;
+	JVMDI_frame_event_data* fe;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = kind;
+	fe = (JVMDI_frame_event_data*)(&(e->u));
+	fe->thread = thread;
+	fe->clazz = clazz;
+	fe->method = method;
+	fe->frame = frame;
+
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireFramePopEvent(jthread thread, jclass clazz,
+					   jmethodID method, jframeID frame)
+{
+	frameEvent(JVMDI_EVENT_FRAME_POP, thread, clazz, method, frame);
+}
+
+void fireMethodEntryEvent(jthread thread, jclass clazz,
+						  jmethodID method, jframeID frame)
+{
+	frameEvent(JVMDI_EVENT_METHOD_ENTRY, thread, clazz, method, frame);
+}
+
+void fireMethodExitEvent(jthread thread, jclass clazz,
+						 jmethodID method, jframeID frame)
+{
+	frameEvent(JVMDI_EVENT_METHOD_EXIT, thread, clazz, method, frame);
+}
+
+void fireFieldAccessEvent(jthread thread, jclass clazz,
+						  jmethodID method, jlocation location,
+						  jclass field_clazz, jobject object,
+						  jfieldID field)
+{
+	JVMDI_Event* e;
+	JVMDI_field_access_event_data* fa;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_FIELD_ACCESS;
+	fa = (JVMDI_field_access_event_data*)(&(e->u));
+	fa->thread = thread;
+	fa->clazz = clazz;
+	fa->method = method;
+	fa->location = location;
+	fa->field_clazz = field_clazz;
+	fa->object = object;
+	fa->field = field;
+
+	fireEvent(*e);
+	
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireFieldModificationEvent(jthread thread, jclass clazz,
+								jmethodID method, jlocation location,
+								jclass field_clazz, jobject object,
+								jfieldID field, char signature_type,
+								jvalue new_value)
+{
+	JVMDI_Event* e;
+	JVMDI_field_modification_event_data* fm;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_FIELD_MODIFICATION;
+	fm = (JVMDI_field_modification_event_data*)(&(e->u));
+	fm->thread = thread;
+	fm->clazz = clazz;
+	fm->method = method;
+	fm->location = location;
+	fm->field_clazz = field_clazz;
+	fm->object = object;
+	fm->field = field;
+	fm->signature_type = signature_type;
+	fm->new_value = new_value;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireExceptionEvent(jthread thread, jclass clazz,
+						jmethodID method, jlocation location,
+						jobject exception, jclass catch_clazz,
+						jmethodID catch_method, jlocation catch_location)
+{
+	JVMDI_Event* e;
+	JVMDI_exception_event_data* ex;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_EXCEPTION;
+	ex = (JVMDI_exception_event_data*)(&(e->u));
+	ex->thread = thread;
+	ex->clazz = clazz;
+	ex->method = method;
+	ex->location = location;
+	ex->exception = exception;
+	ex->catch_clazz = catch_clazz;
+	ex->catch_method = catch_method;
+	ex->catch_location = catch_location;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireExceptionCatchEvent(jthread thread, jclass clazz,
+							 jmethodID method, jlocation location,
+							 jobject exception)
+{
+	JVMDI_Event* e;
+	JVMDI_exception_catch_event_data* ec;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_EXCEPTION_CATCH;
+	ec = (JVMDI_exception_catch_event_data*)(&(e->u));
+	ec->thread = thread;
+	ec->clazz = clazz;
+	ec->method = method;
+	ec->location = location;
+	ec->exception = exception;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireUserDefinedEvent(jobject object, jint key)
+{
+	JVMDI_Event* e;
+	JVMDI_user_event_data* ud;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_USER_DEFINED;
+	ud = (JVMDI_user_event_data*)(&(e->u));
+	ud->object = object;
+	ud->key = key;
+
+	fireEvent(*e);
+	
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+static void threadChangeEvent(jint kind, jthread thread)
+{
+	JVMDI_Event* e;
+	JVMDI_thread_change_event_data* tc;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = kind;
+	tc = (JVMDI_thread_change_event_data*)(&(e->u));
+	tc->thread = thread;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireThreadStartEvent(jthread thread)
+{
+	threadChangeEvent(JVMDI_EVENT_THREAD_START, thread);
+}
+
+void fireThreadEndEvent(jthread thread)
+{
+	threadChangeEvent(JVMDI_EVENT_THREAD_END, thread);
+}
+
+static void classEvent(jint kind, jthread thread, jclass clazz)
+{
+	JVMDI_Event* e;
+	JVMDI_class_event_data* c;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = kind;
+	c = (JVMDI_class_event_data*)(&(e->u));
+	c->thread = thread;
+	c->clazz = clazz;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+	
+void fireClassLoadEvent(jthread thread, jclass clazz)
+{
+	classEvent(JVMDI_EVENT_CLASS_LOAD, thread, clazz);
+}
+
+void fireClassUnloadEvent(jthread thread, jclass clazz)
+{
+	classEvent(JVMDI_EVENT_CLASS_UNLOAD, thread, clazz);
+}
+
+void fireClassPrepareEvent(jthread thread, jclass clazz)
+{
+	classEvent(JVMDI_EVENT_CLASS_PREPARE, thread, clazz);
+}
+
+void fireVMInitEvent(void)
+{
+	JVMDI_Event* e;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	
+	e->kind = JVMDI_EVENT_VM_INIT;
+
+	fireEvent(*e);
+
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+void fireVMDeathEvent(void)
+{
+	JVMDI_Event* e;
+	
+	/* obtain raw monitor */
+
+	/* alloc specific JVMDI_Event (FIXME as a "JNI local ref")
+	*/
+	e = (JVMDI_Event*)malloc(sizeof(*e));
+	e->kind = JVMDI_EVENT_VM_DEATH;
+
+	fireEvent(*e);
+	
+	/* dealloc JVMDI_Event
+	*/	
+	free(e);
+	
+	/* release raw monitor */
+}
+
+/* End of jvmdiEvents.c */
+
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jvmdiEvents.h kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdiEvents.h
--- kaffe-1.0.5/kaffe/kaffevm/jvmdiEvents.h	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdiEvents.h	1999-12-07 20:56:44.000000000 -0500
@@ -0,0 +1,58 @@
+
+#ifndef __jvmdi_events_h
+#define __jvmdi_events_h
+
+#include <jthread.h>
+
+void fireSingleStepEvent(jthread thread, jclass clazz,
+						 jmethodID method, jlocation location);
+
+void fireBreakpointEvent(jthread thread, jclass clazz,
+						 jmethodID method, jlocation location);
+
+void fireFramePopEvent(jthread thread, jclass clazz,
+					   jmethodID method, jframeID frame);
+
+void fireMethodEntryEvent(jthread thread, jclass clazz,
+						  jmethodID method, jframeID frame);
+
+void fireMethodExitEvent(jthread thread, jclass clazz,
+						 jmethodID method, jframeID frame);
+
+void fireFieldAccessEvent(jthread thread, jclass clazz,
+						  jmethodID method, jlocation location,
+						  jclass field_clazz, jobject object,
+						  jfieldID field);
+
+void fireFieldModificationEvent(jthread thread, jclass clazz,
+								jmethodID method, jlocation location,
+								jclass field_clazz, jobject object,
+								jfieldID field, char signature_type,
+								jvalue new_value);
+
+void fireExceptionEvent(jthread thread, jclass clazz,
+						jmethodID method, jlocation location,
+						jobject exception, jclass catch_clazz,
+						jmethodID catch_method, jlocation catch_location);
+
+void fireExceptionCatchEvent(jthread thread, jclass clazz,
+							 jmethodID method, jlocation location,
+							 jobject exception);
+
+void fireUserDefinedEvent(jobject object, jint key);
+
+void fireThreadStartEvent(jthread thread);
+
+void fireThreadEndEvent(jthread thread);
+
+void fireClassLoadEvent(jthread thread, jclass clazz);
+
+void fireClassUnloadEvent(jthread thread, jclass clazz);
+
+void fireClassPrepareEvent(jthread thread, jclass clazz);
+
+void fireVMInitEvent(void);
+
+void fireVMDeathEvent(void);
+
+#endif
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jvmdiRawMonitor.c-save kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdiRawMonitor.c-save
--- kaffe-1.0.5/kaffe/kaffevm/jvmdiRawMonitor.c-save	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdiRawMonitor.c-save	1999-12-07 20:56:44.000000000 -0500
@@ -0,0 +1,66 @@
+
+#include "jvmdi.h"
+
+#include "jvmdiRawMonitor.h"
+
+jvmdiError CreateRawMonitor(char* name, JVMDI_RawMonitor* monitorPtr)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError DestroyRawMonitor(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorEnter(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorExit(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorWait(JVMDI_RawMonitor monitor, jlong millis)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorNotify(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError RawMonitorNotifyAll(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError CreateAndEnterRawMonitor(char* name, JVMDI_RawMonitor* monitorPtr)
+{
+	jvmdiError err;
+	
+	if ((err = CreateRawMonitor(name, monitorPtr) != JVMDI_ERROR_NONE))
+	{
+		return err;
+	}
+	else
+	{
+		if ((err = RawMonitorEnter(*monitorPtr) != JVMDI_ERROR_NONE))
+		{
+			(void)DestroyRawMonitor(*monitorPtr);
+			return err;
+		}
+	}
+	
+	return JVMDI_ERROR_NONE;
+}
+
+jvmdiError ExitAndDestroyRawMonitor(JVMDI_RawMonitor monitor)
+{
+	return JVMDI_ERROR_NONE;
+}
+
+/* End of jvmdiRawMonitor.c */
diff -Nru kaffe-1.0.5/kaffe/kaffevm/jvmdiRawMonitor.h kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdiRawMonitor.h
--- kaffe-1.0.5/kaffe/kaffevm/jvmdiRawMonitor.h	1969-12-31 19:00:00.000000000 -0500
+++ kaffe-1.0.5-hacks/kaffe/kaffevm/jvmdiRawMonitor.h	1999-12-07 20:56:44.000000000 -0500
@@ -0,0 +1,9 @@
+
+#ifndef __jvmdi_raw_monitor_h
+
+#define __jvmdi_raw_monitor_h
+
+jvmdiError CreateAndEnterRawMonitor(char* name, JVMDI_RawMonitor* monitorPtr);
+jvmdiError ExitAndDestroyRawMonitor(JVMDI_RawMonitor monitor);
+
+#endif



More information about the kaffe mailing list