English translation
[cacao.git] / loader.c
index 38324b03115b82db437be211d757e9e0fcef849a..466951b3440c9acc50af469c04abe93b22492581 100644 (file)
--- a/loader.c
+++ b/loader.c
@@ -1,16 +1,18 @@
-/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
-/****************************** loader.c ***************************************
 
-       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+/* loader.c ********************************************************************
+
+       Copyright (c) 1999 A. Krall, R. Grafl, R. Obermaiser, M. Probst
 
        See file COPYRIGHT for information on usage and disclaimer of warranties
 
        Contains the functions of the class loader.
 
        Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
-       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Andreas Krall       EMAIL: cacao@complang.tuwien.ac.at
+                Roman Obermaiser    EMAIL: cacao@complang.tuwien.ac.at
+                Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
 
-       Last Change: 1997/06/03
+       Last Change: 1999/11/08
 
 *******************************************************************************/
 
 
 #include "global.h"
 #include "loader.h"
-
-#include "tables.h"
 #include "native.h"
+#include "tables.h"
 #include "builtin.h"
+#include "jit.h"
+#ifdef OLD_COMPILER
 #include "compiler.h"
+#endif
 #include "asmpart.h"
 
-#include "threads/thread.h"                        /* schani */
-
+#include "threads/thread.h"
+#include <sys/stat.h>
 
-/*************************** globale Variablen *******************************/
+/* global variables ***********************************************************/
 
-extern bool newcompiler;               
+extern bool newcompiler;        /* true if new compiler is used               */               
 
-int count_class_infos = 0;
+int count_class_infos = 0;      /* variables for measurements                 */
 int count_const_pool_len = 0;
 int count_vftbl_len = 0;
 int count_all_methods = 0;
 int count_vmcode_len = 0;
 int count_extable_len = 0;
+int count_class_loads = 0;
+int count_class_inits = 0;
 
-bool loadverbose = false;        /* Switches f"ur mehr Debug-Meldungen */
+bool loadverbose = false;       /* switches for debug messages                */
 bool linkverbose = false;
 bool initverbose = false;
 
 bool makeinitializations = true;
 
-bool getloadingtime = false;
+bool getloadingtime  = false;   /* to measure the runtime                     */
 long int loadingtime = 0;
 
+static s4 interfaceindex;       /* sequential numbering of interfaces         */ 
+
+list unloadedclasses;       /* list of all referenced but not loaded classes  */
+list unlinkedclasses;       /* list of all loaded but not linked classes      */
+list linkedclasses;         /* list of all completely linked classes          */
 
-static u4 interfaceindex;        /* fortlaufende Nummer f"ur Interfaces */ 
 
-static list unloadedclasses;     /* Liste alle referenzierten, aber noch nicht 
-                                    geladenen Klassen */
-static list unlinkedclasses;     /* Liste aller geladenen, aber noch nicht
-                                    gelinkten Klassen */ 
-       list linkedclasses;       /* Liste aller fertig gelinkten Klassen */
+/* utf-symbols for pointer comparison of frequently used strings */
 
+static utf *utf_innerclasses;          /* InnerClasses                    */
+static utf *utf_constantvalue;                 /* ConstantValue                   */
+static utf *utf_code;                      /* Code                            */
+static utf *utf_finalize;                  /* finalize                            */
+static utf *utf_fidesc;                    /* ()V                                     */
+static utf *utf_clinit;                    /* <clinit>                            */
+static utf *utf_initsystemclass;       /* initializeSystemClass   */
+static utf *utf_systemclass;           /* java/lang/System        */
 
 
-/***************** die Referenzen auf die wichtigen Systemklassen ************/
+/* important system classes ***************************************************/
 
 classinfo *class_java_lang_Object;
 classinfo *class_java_lang_String;
@@ -71,12 +85,31 @@ classinfo *class_java_lang_NegativeArraySizeException;
 classinfo *class_java_lang_OutOfMemoryError;
 classinfo *class_java_lang_ArithmeticException;
 classinfo *class_java_lang_ArrayStoreException;
-classinfo *class_java_lang_ThreadDeath;                 /* schani */
+classinfo *class_java_lang_ThreadDeath;
+classinfo *class_array = NULL;
 
-classinfo *class_array;
 
+/******************************************************************************
+
+   structure for primitive classes: contains the class for wrapping the 
+   primitive type, the primitive class, the name of the class for wrapping, 
+   the one character type signature and the name of the primitive class
+ ******************************************************************************/
+primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { 
+               { NULL, NULL, "java/lang/Double",    'D', "double"  },
+               { NULL, NULL, "java/lang/Float",     'F', "float"   },
+               { NULL, NULL, "java/lang/Character", 'C', "char"    },
+               { NULL, NULL, "java/lang/Integer",   'I', "int"     },
+               { NULL, NULL, "java/lang/Long",      'J', "long"    },
+               { NULL, NULL, "java/lang/Byte",      'B', "byte"    },
+               { NULL, NULL, "java/lang/Short",     'S', "short"   },
+               { NULL, NULL, "java/lang/Boolean",   'Z', "boolean" },
+               { NULL, NULL, "java/lang/Void",      'V', "void"    }};
 
-/************ einige vorgefertigte Instanzen wichtiger Systemklassen *********/
+
+/* instances of important system classes **************************************/
 
 java_objectheader *proto_java_lang_ClassCastException;
 java_objectheader *proto_java_lang_NullPointerException;
@@ -85,17 +118,226 @@ java_objectheader *proto_java_lang_NegativeArraySizeException;
 java_objectheader *proto_java_lang_OutOfMemoryError;
 java_objectheader *proto_java_lang_ArithmeticException;
 java_objectheader *proto_java_lang_ArrayStoreException;
-java_objectheader *proto_java_lang_ThreadDeath;         /* schani */
+java_objectheader *proto_java_lang_ThreadDeath;
+
+
+/************* functions for reading classdata *********************************
+
+    getting classdata in blocks of variable size
+    (8,16,32,64-bit integer or float)
+
+*******************************************************************************/
+
+static char *classpath    = "";     /* searchpath for classfiles              */
+static u1 *classbuffer    = NULL;   /* pointer to buffer with classfile-data  */
+static u1 *classbuf_pos;            /* current position in classfile buffer   */
+static int classbuffer_size;        /* size of classfile-data                 */
+
+/* transfer block of classfile data into a buffer */
+
+#define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
+                                classbuf_pos+=len;
+
+/* skip block of classfile data */
+
+#define skip_nbytes(len) classbuf_pos+=len;
+
+#define suck_u1() (*++classbuf_pos)
+#define suck_s8() (s8) suck_u8()
+#define suck_s2() (s2) suck_u2()
+#define suck_s4() (s4) suck_u4()
+#define suck_s1() (s1) suck_u1()
+#define suck_u2() (u2) ((suck_u1()<<8)+suck_u1())
+#define suck_u4() (u4) ((((u4)suck_u1())<<24)+(((u4)suck_u1())<<16)+(((u4)suck_u1())<<8)+((u4)suck_u1()))
+
+
+/* get u8 from classfile data */
+
+static u8 suck_u8 ()
+{
+#if U8_AVAILABLE
+       u8 lo,hi;
+       hi = suck_u4();
+       lo = suck_u4();
+       return (hi<<32) + lo;
+#else
+       u8 v;
+       v.high = suck_u4();
+       v.low = suck_u4();
+       return v;
+#endif
+}
+
+/* get float from classfile data */
+
+static float suck_float ()
+{
+       float f;
+
+#if !WORDS_BIGENDIAN 
+               u1 buffer[4];
+               u2 i;
+               for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
+               memcpy ( (u1*) (&f), buffer, 4);
+#else 
+               suck_nbytes ( (u1*) (&f), 4 );
+#endif
+
+       PANICIF (sizeof(float) != 4, "Incompatible float-format");
+       
+       return f;
+}
+
+/* get double from classfile data */
+static double suck_double ()
+{
+       double d;
+
+#if !WORDS_BIGENDIAN 
+               u1 buffer[8];
+               u2 i;   
+               for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
+               memcpy ( (u1*) (&d), buffer, 8);
+#else 
+               suck_nbytes ( (u1*) (&d), 8 );
+#endif
+
+       PANICIF (sizeof(double) != 8, "Incompatible double-format" );
+       
+       return d;
+}
+
+/************************** function suck_init *********************************
+
+       called once at startup, sets the searchpath for the classfiles
+
+*******************************************************************************/
+
+void suck_init (char *cpath)
+{
+       classpath   = cpath;
+       classbuffer = NULL;
+}
 
 
+/************************** function suck_start ********************************
 
+       returns true if classbuffer is already loaded or a file for the
+       specified class has succussfully been read in. All directories of
+       the searchpath are used to find the classfile (<classname>.class).
+       Returns false if no classfile is found and writes an error message. 
+       
+*******************************************************************************/
+
+
+bool suck_start (utf *classname) {
+
+#define MAXFILENAME 1000               /* maximum length of a filename           */
+       
+       char filename[MAXFILENAME+10];  /* room for '.class'                      */    
+       char *pathpos;                  /* position in searchpath                 */
+       char c, *utf_ptr;               /* pointer to the next utf8-character     */
+       FILE *classfile;
+       int  filenamelen, err;
+       struct stat buffer;
+       
+       if (classbuffer)                /* classbuffer is already valid */
+               return true;
+
+       pathpos = classpath;
+       
+       while (*pathpos) {
+
+               /* skip path separator */
+
+               while (*pathpos == ':')
+                       pathpos++;
+               /* extract directory from searchpath */
+
+               filenamelen = 0;
+               while ((*pathpos) && (*pathpos!=':')) {
+                   PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
+                       filename[filenamelen++] = *(pathpos++);
+                       }
+
+               filename[filenamelen++] = '/';  
+   
+               /* add classname to filename */
+
+               utf_ptr = classname->text;
+               while (utf_ptr < utf_end(classname)) {
+                       PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
+                       c = *utf_ptr++;
+                       if ((c <= ' ' || c > 'z') && (c != '/'))     /* invalid character */ 
+                               c = '?'; 
+                       filename[filenamelen++] = c;    
+                       }
+      
+               /* add suffix */
 
-/****************************************************************************/
-/******************* Einige Support-Funkionen *******************************/
-/****************************************************************************/
+               strcpy (filename+filenamelen, ".class");
 
+               classfile = fopen(filename, "r");
+               if (classfile) {                                       /* file exists */
+                       
+                       /* determine size of classfile */
 
-/********** interne Funktion: printflags  (nur zu Debug-Zwecken) ************/
+                       err = stat (filename, &buffer);
+
+                       if (!err) {                                /* read classfile data */                            
+                               classbuffer_size = buffer.st_size;                              
+                               classbuffer      = MNEW(u1, classbuffer_size);
+                               classbuf_pos     = classbuffer-1;
+                               fread(classbuffer, 1, classbuffer_size, classfile);
+                               fclose(classfile);
+                               return true;
+                       }
+               }
+       }
+
+       if (verbose) {
+               sprintf (logtext, "Warning: Can not open class file '%s'", filename);
+               dolog();
+       }
+
+       return false;
+}
+
+
+/************************** function suck_stop *********************************
+
+       frees memory for buffer with classfile data.
+       Caution: this function may only be called if buffer has been allocated
+                by suck_start with reading a file
+       
+*******************************************************************************/
+
+void suck_stop () {
+
+       /* determine amount of classdata not retrieved by suck-operations         */
+
+       int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
+
+       if (classdata_left > 0) {               
+               /* surplus */           
+               sprintf (logtext,"There are %d access bytes at end of classfile",
+                        classdata_left);
+               dolog();
+       }
+
+       /* free memory */
+
+       MFREE(classbuffer, u1, classbuffer_size);
+       classbuffer = NULL;
+}
+
+/******************************************************************************/
+/******************* Some support functions ***********************************/
+/******************************************************************************/
+
+
+/********** internal function: printflags  (only for debugging) ***************/
 
 static void printflags (u2 f)
 {
@@ -113,210 +355,305 @@ static void printflags (u2 f)
 }
 
 
-/************************* Funktion: skipattribute ****************************
+/************************* Function: skipattribute *****************************
 
-       "uberliest im ClassFile eine (1) 'attribute'-Struktur 
+       skips a (1) 'attribute' structure in the class file
 
-******************************************************************************/
+*******************************************************************************/
 
 static void skipattribute ()
 {
-       u4 len;
-
        suck_u2 ();
-       len = suck_u4 ();
-       skip_nbytes (len);      
+       skip_nbytes(suck_u4()); 
 }
 
-/********************** Funktion: skipattributebody ***************************
+/********************** Function: skipattributebody ****************************
 
-       "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name - 
-       Referenz schon gelesen worden ist.
+       skips an attribute after the 16 bit reference to attribute_name has already
+       been read
        
-******************************************************************************/
+*******************************************************************************/
 
 static void skipattributebody ()
 {
-       u4 len = suck_u4 ();
-       skip_nbytes (len);
+       skip_nbytes(suck_u4());
 }
 
+/************************* Function: skipattributes ****************************
 
-/************************* Funktion: skipattributes ***************************
-
-       "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
+       skips num attribute structures
        
-******************************************************************************/
+*******************************************************************************/
 
 static void skipattributes (u4 num)
 {
        u4 i;
-       for (i=0; i<num; i++) skipattribute();
+       for (i = 0; i < num; i++)
+               skipattribute();
 }
 
+/******************** function: innerclass_getconstant ************************
 
+    like class_getconstant, but if cptags is ZERO null is returned                                      
+       
+*******************************************************************************/
 
-/************************** Funktion: loadUtf8 ********************************
-
-       liest aus dem ClassFile einen Utf8-String (=komprimierter unicode-text) 
-       und legt daf"ur ein unicode-Symbol an. 
-       Return: Zeiger auf das Symbol 
+voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype) 
+{
+       /* invalid position in constantpool */
+       if (pos >= c->cpcount) 
+               panic ("Attempt to access constant outside range");
 
-******************************************************************************/
+       /* constantpool entry of type 0 */      
+       if (!c->cptags[pos])
+               return NULL;
 
-#define MAXUNICODELEN 5000
-static u2 unicodebuffer[MAXUNICODELEN];
+       /* check type of constantpool entry */
+       if (c->cptags[pos] != ctype) {
+               sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
+                (int) ctype, (int) c->cptags[pos] );
+               error();
+               }
+               
+       return c->cpinfos[pos];
+}
 
-static unicode *loadUtf8 ()
-{
-       u4 unicodelen;
-       u4 letter;
+/************************ function: attribute_load ****************************
 
-       u4 utflen;
-       u4 b1,b2,b3;
+    read attributes from classfile
+       
+*******************************************************************************/
 
-       unicodelen = 0;
+static void attribute_load (u4 num, classinfo *c)
+{
+       u4 i,j;
 
-       utflen = suck_u2 ();
-       while (utflen > 0) {
-               b1 = suck_u1 ();
-               utflen --;
-               if (b1<0x80) letter = b1;
-               else {
-                       b2 = suck_u1 ();
-                       utflen --;
-                       if (b1<0xe0) letter = ((b1 & 0x1f) << 6) | (b2 & 0x3f);
-                       else {
-                               b3 = suck_u1 ();
-                               utflen --;
-                               letter = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
-                               }
-                       }       
-       
+       for (i = 0; i < num; i++) {
+               /* retrieve attribute name */   
+               utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
 
-               if (unicodelen >= MAXUNICODELEN) {
-                       panic ("String constant too long");
+               if ( aname == utf_innerclasses)  {                      
+                       /* innerclasses attribute */
+                               
+                       /* skip attribute length */                                             
+                       suck_u4(); 
+                       /* number of records */
+                       c->innerclasscount = suck_u2();
+                       /* allocate memory for innerclass structure */
+                       c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
+
+                       for (j=0;j<c->innerclasscount;j++) {
+                               
+                               /*  The innerclass structure contains a class with an encoded name, 
+                                   its defining scope, its simple name  and a bitmask of the access flags. 
+                                   If an inner class is not a member, its outer_class is NULL, 
+                                   if a class is anonymous, its name is NULL.                              */
+                                                               
+                               innerclassinfo *info = c->innerclass + j;
+
+                               info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
+                               info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
+                               info->name  = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8);        /* CONSTANT_Utf8_info index  */
+                               info->flags = suck_u2 ();                                                 /* access_flags bitmask      */
                        }
-               
-               unicodebuffer[unicodelen++] = letter;                   
+               } else {
+                       /* unknown attribute */
+                       skipattributebody ();
                }
+       }
+}
+
+/******************* function: checkfielddescriptor ****************************
 
+       checks whether a field-descriptor is valid and aborts otherwise
+       all referenced classes are inserted into the list of unloaded classes
        
-       return unicode_new_u2 (unicodebuffer, unicodelen);
-}
+*******************************************************************************/
 
+static void checkfielddescriptor (char *utf_ptr, char *end_pos)
+{
+       char *tstart;  /* pointer to start of classname */
+       char ch;
+       
+       switch (*utf_ptr++) {
+       case 'B':
+       case 'C':
+       case 'I':
+       case 'S':
+       case 'Z':  
+       case 'J':  
+       case 'F':  
+       case 'D':
+               /* primitive type */  
+               break;
 
+       case 'L':
+               /* save start of classname */
+               tstart = utf_ptr;  
+               
+               /* determine length of classname */
+               while ( *utf_ptr++ != ';' )
+                       if (utf_ptr>=end_pos) 
+                               panic ("Missing ';' in objecttype-descriptor");
 
-/******************** interne Funktion: checkfieldtype ***********************/
+               /* cause loading of referenced class */                 
+               class_new ( utf_new(tstart, utf_ptr-tstart-1) );
+               break;
 
-static void checkfieldtype (u2 *text, u4 *count, u4 length)
-{
-       u4 l;
+       case '[' : 
+               /* array type */
+               while ((ch = *utf_ptr++)=='[') 
+                       /* skip */ ;
 
-       if (*count >= length) panic ("Type-descriptor exceeds unicode length");
-       
-       l = text[(*count)++];
-       
-       switch (l) {
-               default: panic ("Invalid symbol in type descriptor");
-                        return;
+               /* component type of array */
+               switch (ch) {
                case 'B':
                case 'C':
-               case 'D':
-               case 'F':
                case 'I':
-               case 'J':
                case 'S':
-               case 'Z': return;
-               
-               case '[': checkfieldtype (text, count, length);
-                         return;
-                         
-               case 'L': 
-                       {
-                       u4 tlen,tstart = *count;
+               case 'Z':  
+               case 'J':  
+               case 'F':  
+               case 'D':
+                       /* primitive type */  
+                       break;
                        
-                       if (*count >= length) 
-                          panic ("Objecttype descriptor of length zero");
+               case 'L':
+                       /* save start of classname */
+                       tstart = utf_ptr;
                        
-                       while ( text[*count] != ';' ) {
-                               (*count)++;
-                               if (*count >= length) 
-                                  panic ("Missing ';' in objecttype-descriptor");
-                               }
+                       /* determine length of classname */
+                       while ( *utf_ptr++ != ';' )
+                               if (utf_ptr>=end_pos) 
+                                       panic ("Missing ';' in objecttype-descriptor");
+
+                       /* cause loading of referenced class */                 
+                       class_new ( utf_new(tstart, utf_ptr-tstart-1) );
+                       break;
+
+               default:   
+                       panic ("Ill formed methodtype-descriptor");
+               }
+               break;
                        
-                       tlen = (*count) - tstart;
-                       (*count)++;
+       default:   
+               panic ("Ill formed methodtype-descriptor");
+       }                       
 
-                       if (tlen == 0) panic ("Objecttype descriptor with empty name");
-                                       
-                       class_get ( unicode_new_u2 (text+tstart, tlen) );
-                       }
-               }       
+        /* exceeding characters */             
+       if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
 }
 
 
-/******************* Funktion: checkfielddescriptor ***************************
+/******************* function checkmethoddescriptor ****************************
 
-       "uberpr"uft, ob ein Field-Descriptor ein g"ultiges Format hat.
-       Wenn nicht, dann wird das System angehalten.
-       Au"serdem werden alle Klassen, die hier referenziert werden, 
-       in die Liste zu ladender Klassen eingetragen.
+    checks whether a method-descriptor is valid and aborts otherwise.
+    All referenced classes are inserted into the list of unloaded classes.
        
-******************************************************************************/
+*******************************************************************************/
 
-void checkfielddescriptor (unicode *d)
+static void checkmethoddescriptor (utf *d)
 {
-       u4 count=0;
-       checkfieldtype (d->text, &count, d->length);
-       if (count != d->length) panic ("Invalid type-descritor encountered");
-}
+       char *utf_ptr = d->text;     /* current position in utf text   */
+       char *end_pos = utf_end(d);  /* points behind utf string       */
+       char *tstart;                /* pointer to start of classname  */
+       char c,ch;
+
+       /* method descriptor must start with parenthesis */
+       if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
+
+       /* check arguments */
+       while ((c = *utf_ptr++) != ')') {
+               switch (c) {
+               case 'B':
+               case 'C':
+               case 'I':
+               case 'S':
+               case 'Z':  
+               case 'J':  
+               case 'F':  
+               case 'D':
+                       /* primitive type */  
+                       break;
 
+               case 'L':
+                       /* save start of classname */ 
+                       tstart = utf_ptr;
+                       
+                       /* determine length of classname */
+                       while ( *utf_ptr++ != ';' )
+                               if (utf_ptr>=end_pos) 
+                                       panic ("Missing ';' in objecttype-descriptor");
+                       
+                       /* cause loading of referenced class */
+                       class_new ( utf_new(tstart, utf_ptr-tstart-1) );
+                       break;
+          
+               case '[' :
+                       /* array type */ 
+                       while ((ch = *utf_ptr++)=='[') 
+                               /* skip */ ;
+
+                       /* component type of array */
+                       switch (ch) {
+                       case 'B':
+                       case 'C':
+                       case 'I':
+                       case 'S':
+                       case 'Z':  
+                       case 'J':  
+                       case 'F':  
+                       case 'D':
+                               /* primitive type */  
+                               break;
 
-/******************* Funktion: checkmethoddescriptor **************************
+                       case 'L':
+                               /* save start of classname */
+                               tstart = utf_ptr;
+                       
+                               /* determine length of classname */     
+                               while ( *utf_ptr++ != ';' )
+                                       if (utf_ptr>=end_pos) 
+                                               panic ("Missing ';' in objecttype-descriptor");
 
-       "uberpr"uft, ob ein Method-Descriptor ein g"ultiges Format hat.
-       Wenn nicht, dann wird das System angehalten.
-       Au"serdem werden alle Klassen, die hier referenziert werden, 
-       in die Liste zu ladender Klassen eingetragen.
-       
-******************************************************************************/
+                               /* cause loading of referenced class */
+                               class_new ( utf_new(tstart, utf_ptr-tstart-1) );
+                               break;
 
-void checkmethoddescriptor (unicode *d)
-{
-       u2 *text=d->text;
-       u4 length=d->length;
-       u4 count=0;
-       
-       if (length<2) panic ("Method descriptor too short");
-       if (text[0] != '(') panic ("Missing '(' in method descriptor");
-       count=1;
-       
-       while (text[count] != ')') {
-               checkfieldtype (text,&count,length);
-               if ( count > length-2 ) panic ("Unexpected end of descriptor");
-               }
-               
-       count++;
-       if (text[count] == 'V') count++;
-       else                    checkfieldtype (text, &count,length);
-               
-       if (count != length) panic ("Method-descriptor has exceeding chars");
+                       default:   
+                               panic ("Ill formed methodtype-descriptor");
+                       } 
+                       break;
+                       
+               default:   
+                       panic ("Ill formed methodtype-descriptor");
+               }                       
+       }
+
+       /* check returntype */
+       if (*utf_ptr=='V') {
+               /* returntype void */
+               if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
+       }
+       else
+               /* treat as field-descriptor */
+               checkfielddescriptor (utf_ptr,end_pos);
 }
 
 
-/******************** Funktion: buildarraydescriptor ****************************
+/******************** Function: buildarraydescriptor ***************************
 
-       erzeugt zu einem namentlich als u2-String vorliegenden Arraytyp eine
-       entsprechende constant_arraydescriptor - Struktur 
+       creates a constant_arraydescriptor structure for the array type named by an
+       utf string
        
-********************************************************************************/
+*******************************************************************************/
 
-static constant_arraydescriptor * buildarraydescriptor(u2 *name, u4 namelen)
+constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
 {
        constant_arraydescriptor *d;
        
-       if (name[0]!='[') panic ("Attempt to build arraydescriptor for non-array");
+       if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
+
        d = NEW (constant_arraydescriptor);
        d -> objectclass = NULL;
        d -> elementdescriptor = NULL;
@@ -325,7 +662,7 @@ static constant_arraydescriptor * buildarraydescriptor(u2 *name, u4 namelen)
        count_const_pool_len += sizeof(constant_arraydescriptor);
 #endif
 
-       switch (name[1]) {
+       switch (*utf_ptr) {
        case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
        case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
        case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
@@ -337,22 +674,21 @@ static constant_arraydescriptor * buildarraydescriptor(u2 *name, u4 namelen)
 
        case '[':
                d -> arraytype = ARRAYTYPE_ARRAY; 
-               d -> elementdescriptor = buildarraydescriptor (name+1, namelen-1);
+               d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
                break;
                
        case 'L':
                d -> arraytype = ARRAYTYPE_OBJECT;
-               d -> objectclass = class_get ( unicode_new_u2 (name+2, namelen-3) );
+               d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
                break;
        }
        return d;
 }
 
 
-/******************* Funktion: freearraydescriptor ****************************
+/******************* Function: freearraydescriptor *****************************
 
-       entfernt eine mit buildarraydescriptor erzeugte Struktur wieder 
-       aus dem Speicher
+       removes a structure created by buildarraydescriptor from memory
        
 *******************************************************************************/
 
@@ -365,7 +701,7 @@ static void freearraydescriptor (constant_arraydescriptor *d)
                }
 }
 
-/*********************** Funktion: displayarraydescriptor *********************/
+/*********************** Function: displayarraydescriptor *********************/
 
 static void displayarraydescriptor (constant_arraydescriptor *d)
 {
@@ -379,43 +715,43 @@ static void displayarraydescriptor (constant_arraydescriptor *d)
        case ARRAYTYPE_LONG: printf ("long[]"); break;
        case ARRAYTYPE_SHORT: printf ("short[]"); break;
        case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
-       case ARRAYTYPE_OBJECT: unicode_display(d->objectclass->name); printf("[]"); break;
+       case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
        }
 }
 
 
 
-/*****************************************************************************/
-/******************** Funktionen fuer Fields *********************************/
-/*****************************************************************************/
+/******************************************************************************/
+/******************** Functionen fuer Fields **********************************/
+/******************************************************************************/
 
 
-/************************ Funktion: field_load ********************************
+/************************ Function: field_load *********************************
 
        l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
        und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
        Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
        reserviert.
 
-******************************************************************************/
+*******************************************************************************/
 
 static void field_load (fieldinfo *f, classinfo *c)
 {
        u4 attrnum,i;
        u4 jtype;
 
-       f -> flags = suck_u2 ();
-       f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
-       f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
-       f -> type = jtype = desc_to_type (f->descriptor);
-       f -> offset = 0;
-
+       f -> flags = suck_u2 ();                                           /* ACC flags                   */
+       f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);       /* name of field               */
+       f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor           */
+       f -> type = jtype = desc_to_type (f->descriptor);                  /* data type                   */
+       f -> offset = 0;                                                   /* offset from start of object */
+       
        switch (f->type) {
        case TYPE_INT:        f->value.i = 0; break;
        case TYPE_FLOAT:      f->value.f = 0.0; break;
        case TYPE_DOUBLE:     f->value.d = 0.0; break;
-       case TYPE_ADDRESS:    f->value.a = NULL; 
-                             heap_addreference (&(f->value.a));
+       case TYPE_ADDRESS:    f->value.a = NULL;                              
+                             heap_addreference (&(f->value.a));           /* make global reference (GC)  */    
                              break;
        case TYPE_LONG:
 #if U8_AVAILABLE
@@ -424,21 +760,28 @@ static void field_load (fieldinfo *f, classinfo *c)
                f->value.l.low = 0; f->value.l.high = 0; break;
 #endif 
        }
-       
+
+       /* read attributes */
        attrnum = suck_u2();
        for (i=0; i<attrnum; i++) {
                u4 pindex;
-               unicode *aname;
+               utf *aname;
 
                aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
-
-               if ( aname != unicode_new_char ("ConstantValue") ) {
+               
+               if ( aname != utf_constantvalue ) {
+                       /* unknown attribute */
                        skipattributebody ();
                        }
                else {
+                       /* constant value attribute */
+                       
+                       /* skip attribute length */
                        suck_u4();
+                       /* index of value in constantpool */            
                        pindex = suck_u2();
-                               
+               
+                       /* initialize field with value from constantpool */             
                        switch (jtype) {
                                case TYPE_INT: {
                                        constant_integer *ci = 
@@ -471,9 +814,9 @@ static void field_load (fieldinfo *f, classinfo *c)
                                        }
                                        break;
                                                
-                               case TYPE_ADDRESS: {
-                                       unicode *u = 
-                                               class_getconstant(c, pindex, CONSTANT_String);
+                               case TYPE_ADDRESS: { 
+                                       utf *u = class_getconstant(c, pindex, CONSTANT_String);
+                                       /* create javastring from compressed utf8-string */                                     
                                        f->value.a = literalstring_new(u);
                                        }
                                        break;
@@ -485,47 +828,44 @@ static void field_load (fieldinfo *f, classinfo *c)
 
                        }
                }
-               
 }
 
 
-/********************** Funktion: field_free *********************************/
+/********************** function: field_free **********************************/
 
 static void field_free (fieldinfo *f)
 {
+       /* empty */
 }
 
 
-/************** Funktion: field_display (nur zu Debug-Zwecken) ***************/
+/************** Function: field_display (nur zu Debug-Zwecken) ****************/
 
 static void field_display (fieldinfo *f)
 {
        printf ("   ");
        printflags (f -> flags);
        printf (" ");
-       unicode_display (f -> name);
+       utf_display (f -> name);
        printf (" ");
-       unicode_display (f -> descriptor);      
+       utf_display (f -> descriptor);  
        printf (" offset: %ld\n", (long int) (f -> offset) );
 }
 
 
+/******************************************************************************/
+/************************* Functions for methods ******************************/ 
+/******************************************************************************/
 
 
-/*****************************************************************************/
-/************************* Funktionen f"ur Methods ***************************/ 
-/*****************************************************************************/
-
-
-/*********************** Funktion: method_load ********************************
+/*********************** Function: method_load *********************************
 
-       l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit 
-       eine schon existierende 'methodinfo'-Struktur aus.
-       Bei allen native-Methoden wird au"serdem gleich der richtige 
-       Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
-       Zeiger auf den Compiler 
+       Loads a method from the class file and fills an existing 'methodinfo'
+       structure. For native methods, the function pointer field is set to the
+       real function pointer, for JavaVM methods a pointer to the compiler is used
+       preliminarily.
        
-******************************************************************************/
+*******************************************************************************/
 
 static void method_load (methodinfo *m, classinfo *c)
 {
@@ -551,24 +891,29 @@ static void method_load (methodinfo *m, classinfo *c)
                m -> stubroutine = createcompilerstub (m);
                }
        else {
+
                functionptr f = native_findfunction 
                       (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
                if (f) {
+#ifdef OLD_COMPILER
                if (newcompiler)
-                       m -> stubroutine = ncreatenativestub (f, m);
-               else
+#endif
                        m -> stubroutine = createnativestub (f, m);
+#ifdef OLD_COMPILER
+               else
+                       m -> stubroutine = oldcreatenativestub (f, m);
+#endif
                        }
                }
        
        
        attrnum = suck_u2();
        for (i=0; i<attrnum; i++) {
-               unicode *aname;
+               utf *aname;
 
                aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
 
-               if ( aname != unicode_new_char("Code"))  {
+               if ( aname != utf_code)  {
                        skipattributebody ();
                        }
                else {
@@ -608,16 +953,13 @@ static void method_load (methodinfo *m, classinfo *c)
                        
                }
 
-
 }
 
+/********************* Function: method_free ***********************************
 
-/********************* Funktion: method_free **********************************
-
-       gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
-       wieder frei
+       frees all memory that was allocated for this method
 
-******************************************************************************/
+*******************************************************************************/
 
 static void method_free (methodinfo *m)
 {
@@ -632,27 +974,26 @@ static void method_free (methodinfo *m)
 }
 
 
-/************** Funktion: method_display  (nur zu Debug-Zwecken) *************/
+/************** Function: method_display  (debugging only) **************/
 
 void method_display (methodinfo *m)
 {
        printf ("   ");
        printflags (m -> flags);
        printf (" ");
-       unicode_display (m -> name);
+       utf_display (m -> name);
        printf (" "); 
-       unicode_display (m -> descriptor);
+       utf_display (m -> descriptor);
        printf ("\n");
 }
 
 
-/******************** Funktion: method_canoverwrite ***************************
+/******************** Function: method_canoverwrite ****************************
 
-       "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch 
-       ist (also mit einer Methodendefinition eine andere "uberschrieben 
-       werden kann).
+       Check if m and old are identical with respect to type and name. This means
+       that old can be overwritten with m.
        
-******************************************************************************/  
+*******************************************************************************/  
 
 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
 {
@@ -665,69 +1006,25 @@ static bool method_canoverwrite (methodinfo *m, methodinfo *old)
 
 
 
-/*****************************************************************************/
-/************************ Funktionen fuer Class ******************************/
-/*****************************************************************************/
+/******************************************************************************/
+/************************ Functions for class *********************************/
+/******************************************************************************/
 
 
-/******************** Funktion: class_get *************************************
+/******************** function: class_getconstant ******************************
 
-       Sucht im System die Klasse mit dem gew"unschten Namen, oder erzeugt
-       eine neue 'classinfo'-Struktur (und h"angt sie in die Liste der zu
-       ladenen Klassen ein).
+       retrieves the value at position 'pos' of the constantpool of a class
+       if the type of the value is other than 'ctype' the system is stopped
 
-******************************************************************************/
-
-classinfo *class_get (unicode *u)
-{
-       classinfo *c;
-       
-       if (u->class) return u->class;
-       
-#ifdef STATISTICS
-       count_class_infos += sizeof(classinfo);
-#endif
-
-       c = NEW (classinfo);
-       c -> flags = 0;
-       c -> name = u;
-       c -> cpcount = 0;
-       c -> cptags = NULL;
-       c -> cpinfos = NULL;
-       c -> super = NULL;
-       c -> sub = NULL;
-       c -> nextsub = NULL;
-       c -> interfacescount = 0;
-       c -> interfaces = NULL;
-       c -> fieldscount = 0;
-       c -> fields = NULL;
-       c -> methodscount = 0;
-       c -> methods = NULL;
-       c -> linked = false;
-       c -> index = 0;
-       c -> instancesize = 0;
-       c -> vftbl = NULL;
-       c -> initialized = false;
-       
-       unicode_setclasslink (u,c);
-       list_addlast (&unloadedclasses, c);
-               
-       return c;
-}
-
-
-
-/******************** Funktion: class_getconstant *****************************
-
-       holt aus dem ConstantPool einer Klasse den Wert an der Stelle 'pos'.
-       Der Wert mu"s vom Typ 'ctype' sein, sonst wird das System angehalten.
-
-******************************************************************************/
+*******************************************************************************/
 
 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
 {
+       /* invalid position in constantpool */  
        if (pos >= c->cpcount) 
                panic ("Attempt to access constant outside range");
+
+       /* check type of constantpool entry */
        if (c->cptags[pos] != ctype) {
                sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
                 (int) ctype, (int) c->cptags[pos] );
@@ -738,12 +1035,11 @@ voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
 }
 
 
-/********************* Funktion: class_constanttype ***************************
+/********************* Function: class_constanttype ****************************
 
-       Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer 
-       Klasse hat.
+       Determines the type of a class entry in the ConstantPool
        
-******************************************************************************/
+*******************************************************************************/
 
 u4 class_constanttype (classinfo *c, u4 pos)
 {
@@ -753,31 +1049,38 @@ u4 class_constanttype (classinfo *c, u4 pos)
 }
 
 
-/******************** Funktion: class_loadcpool *******************************
+/******************** function: class_loadcpool ********************************
 
-       l"adt den gesammten ConstantPool einer Klasse.
-       
-       Dabei werden die einzelnen Eintr"age in ein wesentlich einfachers 
-       Format gebracht (Klassenreferenzen werden aufgel"ost, ...)
-       F"ur eine genaue "Ubersicht "uber das kompakte Format siehe: 'global.h' 
+       loads the constantpool of a class, 
+       the entries are transformed into a simpler format 
+       by resolving references
+       (a detailed overview of the compact structures can be found in global.h)        
 
-******************************************************************************/
+*******************************************************************************/
 
 static void class_loadcpool (classinfo *c)
 {
 
-       typedef struct forward_class {      /* Diese Strukturen dienen dazu, */
-               struct forward_class *next;     /* die Infos, die beim ersten */
-               u2 thisindex;                   /* Durchgang durch den ConstantPool */
-               u2 name_index;                  /* gelesen werden, aufzunehmen. */
-       } forward_class;                    /* Erst nachdem der ganze Pool */ 
-                                        /* gelesen wurde, k"onnen alle */
-       typedef struct forward_string {     /* Felder kompletiert werden */
-               struct forward_string *next;    /* (und das auch nur in der richtigen */
-               u2 thisindex;                   /* Reihenfolge) */
+       /* The following structures are used to save information which cannot be 
+          processed during the first pass. After the complete constantpool has 
+          been traversed the references can be resolved. 
+          (only in specific order)                                                */
+       
+       /* CONSTANT_Class_info entries */
+       typedef struct forward_class {      
+               struct forward_class *next; 
+               u2 thisindex;               
+               u2 name_index;              
+       } forward_class;                    
+                                        
+       /* CONSTANT_String */                                      
+       typedef struct forward_string { 
+               struct forward_string *next; 
+               u2 thisindex;                
                u2 string_index;
        } forward_string;
 
+       /* CONSTANT_NameAndType */
        typedef struct forward_nameandtype {
                struct forward_nameandtype *next;
                u2 thisindex;
@@ -785,6 +1088,7 @@ static void class_loadcpool (classinfo *c)
                u2 sig_index;
        } forward_nameandtype;
 
+       /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
        typedef struct forward_fieldmethint {   
                struct forward_fieldmethint *next;
                u2 thisindex;
@@ -794,7 +1098,6 @@ static void class_loadcpool (classinfo *c)
        } forward_fieldmethint;
 
 
-
        u4 idx;
        long int dumpsize = dump_size ();
 
@@ -803,29 +1106,31 @@ static void class_loadcpool (classinfo *c)
        forward_nameandtype *forward_nameandtypes = NULL;
        forward_fieldmethint *forward_fieldmethints = NULL;
 
+       /* number of entries in the constant_pool table  */
        u4 cpcount       = c -> cpcount = suck_u2();
+       /* allocate memory */
        u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
-       voidptr *cpinfos = c -> cpinfos =  MNEW (voidptr, cpcount);
+       voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
 
 #ifdef STATISTICS
        count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
 #endif
-
        
+       /* initialize constantpool */
        for (idx=0; idx<cpcount; idx++) {
                cptags[idx] = CONSTANT_UNUSED;
                cpinfos[idx] = NULL;
                }
 
                        
-               /******* Erster Durchgang *******/
-               /* Alle Eintr"age, die nicht unmittelbar aufgel"ost werden k"onnen, 
-                  werden einmal `auf Vorrat' in tempor"are Strukturen eingelesen,
-                  und dann am Ende nocheinmal durchgegangen */
-
+               /******* first pass *******/
+               /* entries which cannot be resolved now are written into 
+                  temporary structures and traversed again later        */
+                  
        idx = 1;
        while (idx < cpcount) {
-               u4 t = suck_u1 ();
+               /* get constant type */
+               u4 t = suck_u1 (); 
                switch ( t ) {
 
                        case CONSTANT_Class: { 
@@ -835,7 +1140,8 @@ static void class_loadcpool (classinfo *c)
                                forward_classes = nfc;
 
                                nfc -> thisindex = idx;
-                               nfc -> name_index = suck_u2 ();
+                               /* reference to CONSTANT_NameAndType */
+                               nfc -> name_index = suck_u2 (); 
 
                                idx++;
                                break;
@@ -843,18 +1149,21 @@ static void class_loadcpool (classinfo *c)
                        
                        case CONSTANT_Fieldref:
                        case CONSTANT_Methodref:
-                       case CONSTANT_InterfaceMethodref: {
+                       case CONSTANT_InterfaceMethodref: { 
                                forward_fieldmethint *nff = DNEW (forward_fieldmethint);
                                
                                nff -> next = forward_fieldmethints;
                                forward_fieldmethints = nff;
 
                                nff -> thisindex = idx;
+                               /* constant type */
                                nff -> tag = t;
-                               nff -> class_index = suck_u2 ();
+                               /* class or interface type that contains the declaration of the field or method */
+                               nff -> class_index = suck_u2 (); 
+                               /* name and descriptor of the field or method */
                                nff -> nameandtype_index = suck_u2 ();
 
-                               idx ++;                                         
+                               idx ++;
                                break;
                                }
                                
@@ -865,6 +1174,7 @@ static void class_loadcpool (classinfo *c)
                                forward_strings = nfs;
                                
                                nfs -> thisindex = idx;
+                               /* reference to CONSTANT_Utf8_info with string characters */
                                nfs -> string_index = suck_u2 ();
                                
                                idx ++;
@@ -878,7 +1188,9 @@ static void class_loadcpool (classinfo *c)
                                forward_nameandtypes = nfn;
                                
                                nfn -> thisindex = idx;
+                               /* reference to CONSTANT_Utf8_info containing simple name */
                                nfn -> name_index = suck_u2 ();
+                               /* reference to CONSTANT_Utf8_info containing field or method descriptor */
                                nfn -> sig_index = suck_u2 ();
                                
                                idx ++;
@@ -942,13 +1254,15 @@ static void class_loadcpool (classinfo *c)
                                break;
                                }
                                
-                       case CONSTANT_Utf8: {
-                               unicode *u;
-
-                               u = loadUtf8 ();
-
-                               cptags [idx] = CONSTANT_Utf8;
-                               cpinfos [idx] = u;
+                       case CONSTANT_Utf8: { 
+
+                               /* number of bytes in the bytes array (not string-length) */
+                               u4 length = suck_u2();
+                               cptags [idx]  = CONSTANT_Utf8;
+                               /* insert utf-string into the utf-symboltable */
+                               cpinfos [idx] = utf_new(classbuf_pos+1, length);
+                               /* skip bytes of the string */
+                               skip_nbytes(length);
                                idx++;
                                break;
                                }
@@ -963,32 +1277,35 @@ static void class_loadcpool (classinfo *c)
                
 
 
-          /* Aufl"osen der noch unfertigen Eintr"age */
+          /* resolve entries in temporary structures */
 
        while (forward_classes) {
-               unicode *name =
+               utf *name =
                  class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
                
-               if ( (name->length>0) && (name->text[0]=='[') ) {
-                       checkfielddescriptor (name); 
+               if ( (name->blength>0) && (name->text[0]=='[') ) {
+                       /* check validity of descriptor */
+                       checkfielddescriptor (name->text, utf_end(name)); 
 
                        cptags  [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
                        cpinfos [forward_classes -> thisindex] = 
-                          buildarraydescriptor(name->text, name->length);
+                          buildarraydescriptor(name->text, name->blength);
 
                        }
-               else {          
+               else {                                  
                        cptags  [forward_classes -> thisindex] = CONSTANT_Class;
-                       cpinfos [forward_classes -> thisindex] = class_get (name);
+                       /* retrieve class from class-table */
+                       cpinfos [forward_classes -> thisindex] = class_new (name);
                        }
                forward_classes = forward_classes -> next;
                
                }
 
        while (forward_strings) {
-               unicode *text = 
+               utf *text = 
                  class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
-                       
+       
+               /* resolve utf-string */                
                cptags   [forward_strings -> thisindex] = CONSTANT_String;
                cpinfos  [forward_strings -> thisindex] = text;
                
@@ -1002,6 +1319,7 @@ static void class_loadcpool (classinfo *c)
                count_const_pool_len += sizeof(constant_nameandtype);
 #endif
 
+               /* resolve simple name and descriptor */
                cn -> name = class_getconstant 
                   (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
                cn -> descriptor = class_getconstant
@@ -1021,7 +1339,7 @@ static void class_loadcpool (classinfo *c)
 #ifdef STATISTICS
                count_const_pool_len += sizeof(constant_FMIref);
 #endif
-
+               /* resolve simple name and descriptor */
                nat = class_getconstant
                        (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
 
@@ -1034,10 +1352,12 @@ static void class_loadcpool (classinfo *c)
                cpinfos [forward_fieldmethints -> thisindex] = fmi;
        
                switch (forward_fieldmethints -> tag) {
-               case CONSTANT_Fieldref:  checkfielddescriptor (fmi->descriptor);
+               case CONSTANT_Fieldref:  /* check validity of descriptor */
+                                        checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
                                         break;
                case CONSTANT_InterfaceMethodref: 
-               case CONSTANT_Methodref: checkmethoddescriptor (fmi->descriptor);
+               case CONSTANT_Methodref: /* check validity of descriptor */
+                                        checkmethoddescriptor (fmi->descriptor);
                                         break;
                }               
        
@@ -1050,36 +1370,44 @@ static void class_loadcpool (classinfo *c)
 }
 
 
-/********************** Funktion: class_load **********************************
-
-       l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
-       'classinfo'-Struktur mu"s bereits angelegt worden sein.
-       
-       Die Superklasse und die Interfaces, die diese Klasse implementiert,
-       m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die 
-       Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
+/********************** Function: class_load ***********************************
        
-       Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
-       und in die Liste 'unlinkedclasses' eingh"angt.
+       Loads everything interesting about a class from the class file. The
+       'classinfo' structure must have been allocated previously.
+
+       The super class and the interfaces implemented by this class need not be
+       loaded. The link is set later by the function 'class_link'.
+
+       The loaded class is removed from the list 'unloadedclasses' and added to
+       the list 'unlinkedclasses'.
        
-******************************************************************************/
+*******************************************************************************/
 
-static void class_load (classinfo *c)
+static int class_load (classinfo *c)
 {
        u4 i;
        u4 mi,ma;
 
+#ifdef STATISTICS
+       count_class_loads++;
+#endif
 
-       if (loadverbose) {
+       /* output for debugging purposes */
+       if (loadverbose) {              
                sprintf (logtext, "Loading class: ");
-               unicode_sprint (logtext+strlen(logtext), c->name );
+               utf_sprint (logtext+strlen(logtext), c->name );
                dolog();
                }
-
-
-       suck_start (c->name);
-
-       if (suck_u4() != MAGIC) panic("Can not find class-file signature");   
+       
+       /* load classdata, throw exception on error */
+       if (!suck_start (c->name)) {
+               throw_classnotfoundexception();            
+               return false;
+       }
+       
+       /* check signature */           
+       if (suck_u4() != MAGIC) panic("Can not find class-file signature");     
+       /* check version */
        mi = suck_u2(); 
        ma = suck_u2();
        if (ma != MAJOR_VERSION) {
@@ -1095,9 +1423,12 @@ static void class_load (classinfo *c)
 
        class_loadcpool (c);
        
-       c -> flags = suck_u2 ();
-       suck_u2 ();       /* this */
+       /* ACC flags */
+       c -> flags = suck_u2 (); 
+       /* this class */
+       suck_u2 ();       
        
+       /* retrieve superclass */
        if ( (i = suck_u2 () ) ) {
                c -> super = class_getconstant (c, i, CONSTANT_Class);
                }
@@ -1105,6 +1436,7 @@ static void class_load (classinfo *c)
                c -> super = NULL;
                }
                         
+       /* retrieve interfaces */
        c -> interfacescount = suck_u2 ();
        c -> interfaces = MNEW (classinfo*, c -> interfacescount);
        for (i=0; i < c -> interfacescount; i++) {
@@ -1112,12 +1444,14 @@ static void class_load (classinfo *c)
                      class_getconstant (c, suck_u2(), CONSTANT_Class);
                }
 
+       /* load fields */
        c -> fieldscount = suck_u2 ();
        c -> fields = MNEW (fieldinfo, c -> fieldscount);
        for (i=0; i < c -> fieldscount; i++) {
                field_load (&(c->fields[i]), c);
                }
 
+       /* load methods */
        c -> methodscount = suck_u2 ();
        c -> methods = MNEW (methodinfo, c -> methodscount);
        for (i=0; i < c -> methodscount; i++) {
@@ -1130,24 +1464,28 @@ static void class_load (classinfo *c)
        count_class_infos += sizeof(methodinfo) * c -> methodscount;
 #endif
 
+       /* load variable-length attribute structures */ 
+       attribute_load (suck_u2(), c);
 
-       skipattributes ( suck_u2() );
-
-
+       /* free memory */
        suck_stop ();
 
+       /* remove class from list of unloaded classes and 
+          add to list of unlinked classes                */
        list_remove (&unloadedclasses, c);
        list_addlast (&unlinkedclasses, c);
+
+       return true;
 }
 
 
 
-/************** interne Funktion: class_highestinterface **********************
+/************** internal Function: class_highestinterface ***********************
 
-       wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
-       die Interfacetable einer Klasse sein mu"s.
+       Used by the function class_link to determine the amount of memory needed
+       for the interface table.
 
-******************************************************************************/
+*******************************************************************************/
 
 static s4 class_highestinterface (classinfo *c) 
 {
@@ -1156,7 +1494,7 @@ static s4 class_highestinterface (classinfo *c)
        
        if ( ! (c->flags & ACC_INTERFACE) ) {
                sprintf (logtext, "Interface-methods count requested for non-interface:  ");
-       unicode_sprint (logtext+strlen(logtext), c->name);
+       utf_sprint (logtext+strlen(logtext), c->name);
        error();
        }
     
@@ -1169,46 +1507,46 @@ static s4 class_highestinterface (classinfo *c)
 }
 
 
-/**************** Funktion: class_addinterface ********************************
+/* class_addinterface **********************************************************
 
-       wird von der Funktion class_link ben"otigt, um eine Virtual Function 
-       Table f"ur ein Interface (und alle weiteren von diesem Interface
-       implementierten Interfaces) in eine Klasse einzutragen.
+       Is needed by class_link for adding a VTBL to a class. All interfaces
+       implemented by ic are added as well.
 
-******************************************************************************       
+*******************************************************************************/       
 
 static void class_addinterface (classinfo *c, classinfo *ic)
 {
-       u4 i = ic->index;
-       u4 j,m;
+       s4     j, m;
+       s4     i     = ic->index;
        vftbl *vftbl = c->vftbl;
        
-       if (i>=vftbl->interfacetablelength) panic ("Interfacetable-Overflow");
-       if (vftbl->interfacevftbl[i]) return;
+       if (i >= vftbl->interfacetablelength)
+               panic ("Inernal error: interfacetable overflow");
+       if (vftbl->interfacetable[-i])
+               return;
 
-       if (ic->methodscount==0) {  /* wenn interface keine Methoden hat, dann 
-                                      trotzdem eine Tabelle mit L"ange 1 anlegen,
-                                      wegen Subclass-Tests */
-               vftbl -> interfacevftbllength[i] = 1;
-               vftbl -> interfacevftbl[i] = MNEW(methodptr, 1);
-               vftbl -> interfacevftbl[i][0] = NULL;
+       if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
+               vftbl->interfacevftbllength[i] = 1;
+               vftbl->interfacetable[-i] = MNEW(methodptr, 1);
+               vftbl->interfacetable[-i][0] = NULL;
                }
        else {
-               vftbl -> interfacevftbllength[i] = ic -> methodscount;
-               vftbl -> interfacevftbl[i] = MNEW(methodptr, ic -> methodscount); 
+               vftbl->interfacevftbllength[i] = ic->methodscount;
+               vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
 
 #ifdef STATISTICS
-       count_vftbl_len += sizeof(methodptr) * ic -> methodscount;
+       count_vftbl_len += sizeof(methodptr) *
+                                (ic->methodscount + (ic->methodscount == 0));
 #endif
 
                for (j=0; j<ic->methodscount; j++) {
                        classinfo *sc = c;
                        while (sc) {
-                               for (m=0; m<sc->methodscount; m++) {
+                               for (m = 0; m < sc->methodscount; m++) {
                                        methodinfo *mi = &(sc->methods[m]);
-                                       if (method_canoverwrite (mi, &(ic->methods[j])) ) {
-                                               vftbl->interfacevftbl[i][j] = 
-                                                        vftbl->table[mi->vftblindex];
+                                       if (method_canoverwrite(mi, &(ic->methods[j]))) {
+                                               vftbl->interfacetable[-i][j] = 
+                                                                         vftbl->table[mi->vftblindex];
                                                goto foundmethod;
                                                }
                                        }
@@ -1217,104 +1555,108 @@ static void class_addinterface (classinfo *c, classinfo *ic)
                         foundmethod: ;
                        }
                }
-               
-       for (j=0; j<ic->interfacescount; j++) 
+
+       for (j = 0; j < ic->interfacescount; j++) 
                class_addinterface(c, ic->interfaces[j]);
 }
 
 
-/********************** Funktion: class_link **********************************
+/********************** Function: class_link ***********************************
 
-       versucht, eine Klasse in das System voll zu integrieren (linken). Dazu 
-       m"ussen sowol die Superklasse, als auch alle implementierten
-       Interfaces schon gelinkt sein.
-       Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz 
-       dieser Klasse, als auch die Virtual Function Tables f"ur normale
-       Methoden als auch Interface-Methoden.
+       Tries to link a class. The super class and every implemented interface must
+       already have been linked. The function calculates the length in bytes that
+       an instance of this class requires as well as the VTBL for methods and
+       interface methods.
        
-       Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
-       der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
-       eingetragen.
-       Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
+       If the class can be linked, it is removed from the list 'unlinkedclasses'
+       and added to 'linkedclasses'. Otherwise, it is moved to the end of
+       'unlinkedclasses'.
 
-       Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
-                eine Endlosschleife!!  (Da muss ich mir noch was einfallen lassen)
+       Attention: If cyclical class definitions are encountered, the program gets
+       into an infinite loop (we'll have to work that out)
 
-******************************************************************************/
+*******************************************************************************/
 
 static void class_link (classinfo *c)
 {
-       u4 supervftbllength;          /* L"ange der VFTBL der Superklasse */
-       u4 vftbllength;               /* L"ange der VFTBL dieser Klasse */
-       classinfo *super = c->super;  
-       classinfo *ic,*c2;            /* Hilfsvariablen */
-       vftbl *v;
-       u4 i;                          
+       s4 supervftbllength;          /* vftbllegnth of super class               */
+       s4 vftbllength;               /* vftbllength of current class             */
+       s4 interfacetablelength;      /* interface table length                   */
+       classinfo *super = c->super;  /* super class                              */
+       classinfo *ic, *c2;           /* intermediate class variables             */
+       vftbl *v;                     /* vftbl of current class                   */
+       s4 i;                         /* interface/method/field counter           */                     
+
 
+       /*  check if all superclasses are already linked, if not put c at end of
+           unlinked list and return. Additionally initialize class fields.       */
 
-               /* schauen, ob alle "ubergeordneten Klassen schon fertig sind, 
-                  und richtiges Initialisieren der lokalen Variablen */ 
+       /*  check interfaces */
 
-       for ( i=0; i<c->interfacescount; i++) {
+       for (i = 0; i < c->interfacescount; i++) {
                ic = c->interfaces[i];
-               if ( !ic -> linked) {
-                       list_remove (&unlinkedclasses,c );
-                       list_addlast (&unlinkedclasses,c );
+               if (!ic->linked) {
+                       list_remove(&unlinkedclasses, c);
+                       list_addlast(&unlinkedclasses, c);
                        return; 
                        }
                }
        
-       if (! super) {
-               c -> index = 0;
-               c -> instancesize = sizeof (java_objectheader);
+       /*  check super class */
+
+       if (super == NULL) {          /* class java.long.Object */
+               c->index = 0;
+               c->instancesize = sizeof(java_objectheader);
                
                vftbllength = supervftbllength = 0;
 
-               c -> finalizer = NULL;
+               c->finalizer = NULL;
                }
        else {
-               if ( !super -> linked ) {
-                       list_remove (&unlinkedclasses,c );
-                       list_addlast (&unlinkedclasses,c );
+               if (!super->linked) {
+                       list_remove(&unlinkedclasses, c);
+                       list_addlast(&unlinkedclasses, c);
                        return; 
                        }
 
-               if ( c->flags & ACC_INTERFACE)     c -> index = interfaceindex++;
-                                       else       c -> index = super -> index + 1;
+               if (c->flags & ACC_INTERFACE)
+                       c->index = interfaceindex++;
+               else
+                       c->index = super->index + 1;
                
-               c -> instancesize = super -> instancesize;
+               c->instancesize = super->instancesize;
                
-               vftbllength = supervftbllength = super -> vftbl -> vftbllength;
+               vftbllength = supervftbllength = super->vftbl->vftbllength;
                
-               c -> finalizer = super -> finalizer;
+               c->finalizer = super->finalizer;
                }
 
 
        if (linkverbose) {
                sprintf (logtext, "Linking Class: ");
-               unicode_sprint (logtext+strlen(logtext), c->name );
+               utf_sprint (logtext+strlen(logtext), c->name );
                dolog ();
                }
 
-               /* Erstellen der Virtual Function Table */
+       /* compute vftbl length */
 
-       for (i=0; i < c->methodscount; i++) {
+       for (i = 0; i < c->methodscount; i++) {
                methodinfo *m = &(c->methods[i]);
                        
-               if (! (m->flags & ACC_STATIC) ) {
+               if (!(m->flags & ACC_STATIC)) { /* is instance method */
                        classinfo *sc = super;
                        while (sc) {
                                int j;
-                               for (j=0; j < sc->methodscount; j++) {
-                                       if ( method_canoverwrite (m, &(sc->methods[j])) ) {
-                                               m -> vftblindex = sc->methods[j].vftblindex;
+                               for (j = 0; j < sc->methodscount; j++) {
+                                       if (method_canoverwrite(m, &(sc->methods[j]))) {
+                                               m->vftblindex = sc->methods[j].vftblindex;
                                                goto foundvftblindex;
                                                }
                                        }
                                sc = sc->super;
                                }
-                       m -> vftblindex = (vftbllength++);
-                 foundvftblindex: ;
+                       m->vftblindex = (vftbllength++);
+foundvftblindex: ;
                        }
                }       
        
@@ -1322,106 +1664,113 @@ static void class_link (classinfo *c)
        count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
 #endif
 
-       c -> vftbl = v = (vftbl*) 
-            mem_alloc (sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1));
-       v -> class = c;
-       v -> vftbllength = vftbllength;
-       v -> interfacetablelength = 0;
-       
-       for (i=0; i < supervftbllength; i++) 
-          v -> table[i] = super -> vftbl -> table[i];
+       /* compute interfacetable length */
+
+       interfacetablelength = 0;
+       c2 = c;
+       while (c2) {
+               for (i = 0; i < c2->interfacescount; i++) {
+                       s4 h = class_highestinterface (c2->interfaces[i]) + 1;
+                       if (h > interfacetablelength)
+                               interfacetablelength = h;
+                       }
+               c2 = c2->super;
+               }
+
+       /* allocate virtual function table */
+
+       v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
+                   (vftbllength - 1) + sizeof(methodptr*) *
+                   (interfacetablelength - (interfacetablelength > 0)));
+       v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
+                                        (interfacetablelength > 1));
+       c->header.vftbl = c->vftbl = v;
+       v->class = c;
+       v->vftbllength = vftbllength;
+       v->interfacetablelength = interfacetablelength;
+
+       /* copy virtual function table of super class */
+
+       for (i = 0; i < supervftbllength; i++) 
+          v->table[i] = super->vftbl->table[i];
        
-       for (i=0; i < c->methodscount; i++) {
+       /* add method stubs into virtual function table */
+
+       for (i = 0; i < c->methodscount; i++) {
                methodinfo *m = &(c->methods[i]);
-               if ( ! (m->flags & ACC_STATIC) ) {
-                       v -> table[m->vftblindex] = m -> stubroutine;
+               if (!(m->flags & ACC_STATIC)) {
+                       v->table[m->vftblindex] = m->stubroutine;
                        }
                }
 
-
-               /* Berechnen der Instanzengr"o"se und der Offsets der einzelnen 
-                  Felder */
+       /* compute instance size and offset of each field */
        
-       for (i=0; i < c->fieldscount; i++) {
-               u4 dsize;
-               fieldinfo *f = &(c -> fields[i]);
+       for (i = 0; i < c->fieldscount; i++) {
+               s4 dsize;
+               fieldinfo *f = &(c->fields[i]);
                
-               if ( ! (f->flags & ACC_STATIC) ) {
+               if (!(f->flags & ACC_STATIC) ) {
                        dsize = desc_typesize (f->descriptor);
-                       c -> instancesize = ALIGN ( c->instancesize, dsize);
-                       f -> offset = c -> instancesize;
-                       c -> instancesize += dsize;
+                       c->instancesize = ALIGN (c->instancesize, dsize);
+                       f->offset = c->instancesize;
+                       c->instancesize += dsize;
                        }
-
                }
 
+       /* initialize interfacetable and interfacevftbllength */
        
-               /* Berechnen der Virtual Function Tables f"ur alle Interfaces */
-       
-       c2 = c;
-       while (c2) {
-               for (i=0; i<c2->interfacescount; i++) {
-                       s4 h = class_highestinterface (c2->interfaces[i]) + 1;
-                       if ( h > v->interfacetablelength) v->interfacetablelength = h;
-                       }
-               c2 = c2->super;
-               }
-       v -> interfacevftbllength = MNEW (u4, v->interfacetablelength);
-       v -> interfacevftbl = MNEW (methodptr *, v->interfacetablelength); 
+       v->interfacevftbllength = MNEW (s4, interfacetablelength);
 
 #ifdef STATISTICS
-       count_vftbl_len += (4 + sizeof(methodptr*)) * v->interfacetablelength;
+       count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
 #endif
 
-       for (i=0; i < v->interfacetablelength; i++) {
-               v -> interfacevftbllength[i] = 0;
-               v -> interfacevftbl[i] = NULL;
+       for (i = 0; i < interfacetablelength; i++) {
+               v->interfacevftbllength[i] = 0;
+               v->interfacetable[-i] = NULL;
                }
        
-       c2 = c;
-       while (c2) {
-               for (i=0; i<c2->interfacescount; i++) {
+       /* add interfaces */
+       
+       for (c2 = c; c2 != NULL; c2 = c2->super)
+               for (i = 0; i < c2->interfacescount; i++) {
                        class_addinterface (c, c2->interfaces[i]);
                        }
-               c2 = c2->super;
-               }
-               
-
 
-               /* Die finalizer-Methode suchen und eintragen (wenn vorhanden), 
-                  aber nur bei Objekten ausser java.lang.Object */
+       /* add finalizer method (not for java.lang.Object) */
 
-       if (super) {
+       if (super != NULL) {
                methodinfo *fi;
-               static unicode *finame=NULL,*fidesc=NULL;
-               
-               if (!finame) finame = unicode_new_char ("finalize");
-               if (!fidesc) fidesc = unicode_new_char ("()V");
+               static utf *finame = NULL;
+               static utf *fidesc = NULL;
+
+               if (finame == NULL)
+                       finame = utf_finalize;
+               if (fidesc == NULL)
+                       fidesc = utf_fidesc;
 
                fi = class_findmethod (c, finame, fidesc);
-               if (fi) {
-                       if (! (fi->flags & ACC_STATIC) ) {
-                               c -> finalizer = fi;
+               if (fi != NULL) {
+                       if (!(fi->flags & ACC_STATIC)) {
+                               c->finalizer = fi;
                                }
                        }
-       }
-       
-       
-               /* Abschlie"sende Aktionen */
-       
-       c -> linked = true;     
+               }
+
+       /* final tasks */
+
+       c->linked = true;       
 
        list_remove (&unlinkedclasses, c);
        list_addlast (&linkedclasses, c);
 }
 
 
-/******************* Funktion: class_freepool *********************************
+/******************* Function: class_freepool **********************************
 
-       Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
-       wieder frei.
+       Frees all resources used by this classes Constant Pool.
 
-******************************************************************************/
+*******************************************************************************/
 
 static void class_freecpool (classinfo *c)
 {
@@ -1467,97 +1816,167 @@ static void class_freecpool (classinfo *c)
 }
 
 
-/*********************** Funktion: class_free *********************************
+/*********************** Function: class_free **********************************
 
-       Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
+       Frees all resources used by the class.
 
-******************************************************************************/
+*******************************************************************************/
 
 static void class_free (classinfo *c)
 {
-       u4 i;
+       s4 i;
        vftbl *v;
                
-       unicode_unlinkclass (c->name);
-       
        class_freecpool (c);
 
        MFREE (c->interfaces, classinfo*, c->interfacescount);
 
-       for (i=0; i < c->fieldscount; i++) field_free ( &(c->fields[i]) );
+       for (i = 0; i < c->fieldscount; i++)
+               field_free(&(c->fields[i]));
        MFREE (c->fields, fieldinfo, c->fieldscount);
        
-       for (i=0; i < c->methodscount; i++) method_free ( &(c->methods[i]) );
+       for (i = 0; i < c->methodscount; i++)
+               method_free(&(c->methods[i]));
        MFREE (c->methods, methodinfo, c->methodscount);
 
-       if ( (v = c->vftbl) ) {
-               for (i=0; i<v->interfacetablelength; i++) {
-                       MFREE (v->interfacevftbl[i], methodptr, v->interfacevftbllength[i]);
+       if ((v = c->vftbl) != NULL) {
+               for (i = 0; i < v->interfacetablelength; i++) {
+                       MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
                        }
-               MFREE (v->interfacevftbllength, u4, v->interfacetablelength);
-               MFREE (v->interfacevftbl, methodptr*, v->interfacetablelength);
-
-               mem_free (v, sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1));
+               MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
+
+               i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
+                   sizeof(methodptr*) * (v->interfacetablelength -
+                                        (v->interfacetablelength > 0));
+               v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
+                                            (v->interfacetablelength > 1));
+               mem_free (v, i);
                }
-               
+
+       if (c->innerclasscount)
+               MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
+
        FREE (c, classinfo);
 }
 
-
-/************************* Funktion: class_findfield *************************
+/************************* Function: class_findfield ***************************
        
-       sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
-       Namen und Typ.
+       Searches a 'classinfo' structure for a field having the given name and
+       type.
+
+*******************************************************************************/
 
-*****************************************************************************/
 
-fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc)
+fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
 {
-       u4 i;
-       for (i=0; i < c->fieldscount; i++) {
-               if ( (c->fields[i].name == name)  &&  (c->fields[i].descriptor == desc) )
-                       return &(c->fields[i]);
-               }
+       s4 i;
+
+       for (i = 0; i < c->fieldscount; i++) { 
+               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
+                       return &(c->fields[i]);                                                         
+    }
+
        panic ("Can not find field given in CONSTANT_Fieldref");
        return NULL;
 }
 
 
-/************************* Funktion: class_findmethod *************************
+/************************* Function: class_findmethod **************************
        
-       sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
-       Namen und Typ.
-       Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
+       Searches a 'classinfo' structure for a method having the given name and
+       type.
+       If type is NULL, it is ignored.
 
-*****************************************************************************/
+*******************************************************************************/
 
-methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc)
+methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
 {
-       u4 i;
-       for (i=0; i < c->methodscount; i++) {
-               if (     (c->methods[i].name == name)  
-                         && (    (desc == NULL) 
-                             ||  (c->methods[i].descriptor == desc) 
-                            )  
-                  )
+       s4 i;
+       for (i = 0; i < c->methodscount; i++) {
+               if ((c->methods[i].name == name) && ((desc == NULL) ||
+                                                  (c->methods[i].descriptor == desc)))
                        return &(c->methods[i]);
                }
        return NULL;
 }
 
+/************************* Function: class_findmethod_approx ******************
+       
+       like class_findmethod but ignores the return value when comparing the
+       descriptor.
+
+*******************************************************************************/
+
+methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
+{
+       s4 i;
+
+       for (i = 0; i < c->methodscount; i++) 
+               if (c->methods[i].name == name) {
+                       utf *meth_descr = c->methods[i].descriptor;
+                       
+                       if (desc == NULL) 
+                               /* ignore type */
+                               return &(c->methods[i]);
+
+                       if (desc->blength <= meth_descr->blength) {
+                                          /* current position in utf text   */
+                                          char *desc_utf_ptr = desc->text;      
+                                          char *meth_utf_ptr = meth_descr->text;                                         
+                                          /* points behind utf strings */
+                                          char *desc_end = utf_end(desc);         
+                                          char *meth_end = utf_end(meth_descr);   
+                                          char ch;
+
+                                          /* compare argument types */
+                                          while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
+
+                                                  if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
+                                                          break; /* no match */
+
+                                                  if (ch==')')
+                                                          return &(c->methods[i]);   /* all parameter types equal */
+                                          }
+                       }
+               }
 
-/************************* Funktion: class_resolvemethod *************************
+       return NULL;
+}
+
+/***************** Function: class_resolvemethod_approx ***********************
        
-       sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
+       Searches a class and every super class for a method (without paying
+       attention to the return value)
 
-*****************************************************************************/
+*******************************************************************************/
+
+methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
+{
+       while (c) {
+               /* search for method (ignore returntype) */
+               methodinfo *m = class_findmethod_approx (c, name, desc);
+               /* method found */
+               if (m) return m;
+               /* search superclass */
+               c = c->super;
+               }
+       return NULL;
+}
+
+
+/************************* Function: class_resolvemethod ***********************
+       
+       Searches a class and every super class for a method.
+
+*******************************************************************************/
 
 
-methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *desc)
+methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
 {
        while (c) {
                methodinfo *m = class_findmethod (c, name, desc);
                if (m) return m;
+               /* search superclass */
                c = c->super;
                }
        return NULL;
@@ -1565,11 +1984,11 @@ methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *desc)
        
 
 
-/************************* Funktion: class_issubclass ************************
+/************************* Function: class_issubclass **************************
 
-       "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.            
+       Checks if sub is a descendant of super.
        
-*****************************************************************************/
+*******************************************************************************/
 
 bool class_issubclass (classinfo *sub, classinfo *super)
 {
@@ -1582,14 +2001,13 @@ bool class_issubclass (classinfo *sub, classinfo *super)
 
 
 
-/****************** Initialisierungsfunktion f"ur eine Klasse ****************
+/****************** Initialization function for classes ******************
 
-       In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
-       Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
-       Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
-       wird.
+       In Java, every class can have a static initialization function. This
+       function has to be called BEFORE calling other methods or accessing static
+       variables.
 
-******************************************************************************/
+*******************************************************************************/
 
 #ifdef USE_THREADS
 extern int blockInts;
@@ -1602,31 +2020,38 @@ void class_init (classinfo *c)
        s4 i;
        int b;
 
-       if (!makeinitializations) return;
-       if (c->initialized) return;
+       if (!makeinitializations)
+               return;
+       if (c->initialized)
+               return;
        c -> initialized = true;
        
-       if (c->super) class_init (c->super);
-       for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
+#ifdef STATISTICS
+       count_class_inits++;
+#endif
+
+       if (c->super)
+               class_init (c->super);
+       for (i=0; i < c->interfacescount; i++)
+               class_init(c->interfaces[i]);
 
-       m = class_findmethod (c, 
-                             unicode_new_char ("<clinit>"), 
-                             unicode_new_char ("()V"));
+       m = class_findmethod (c, utf_clinit, utf_fidesc);
        if (!m) {
                if (initverbose) {
                        sprintf (logtext, "Class ");
-                       unicode_sprint (logtext+strlen(logtext), c->name);
-                       sprintf (logtext+strlen(logtext), " has no initializer");       
+                       utf_sprint (logtext+strlen(logtext), c->name);
+                       sprintf (logtext+strlen(logtext), " has no initializer");       
                        dolog ();
                        }
                return;
                }
                
-       if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
+       if (! (m->flags & ACC_STATIC))
+               panic ("Class initializer is not static!");
        
        if (initverbose) {
                sprintf (logtext, "Starting initializer for class: ");
-               unicode_sprint (logtext+strlen(logtext), c->name);
+               utf_sprint (logtext+strlen(logtext), c->name);
                dolog ();
        }
 
@@ -1642,25 +2067,63 @@ void class_init (classinfo *c)
        blockInts = b;
 #endif
 
-       if (exceptionptr) {     
-               printf ("#### Initializer has thrown: ");
-               unicode_display (exceptionptr->vftbl->class->name);
+       if (exceptionptr) {     
+               printf ("#### Initializer of ");
+               utf_display (c->name);
+               printf (" has thrown: ");
+               utf_display (exceptionptr->vftbl->class->name);
                printf ("\n");
                fflush (stdout);
                }
 
        if (initverbose) {
                sprintf (logtext, "Finished initializer for class: ");
-               unicode_sprint (logtext+strlen(logtext), c->name);
+               utf_sprint (logtext+strlen(logtext), c->name);
                dolog ();
        }
 
+       if (c->name == utf_systemclass) {
+               /* class java.lang.System requires explicit initialization */
+               
+               if (initverbose)
+                       printf ("#### Initializing class System");
+
+               /* find initializing method */     
+               m = class_findmethod (c, 
+                                       utf_initsystemclass,
+                                       utf_fidesc);
+
+               if (!m) {
+                       /* no method found */
+                       log("initializeSystemClass failed");
+                       return;
+               }
+
+               #ifdef USE_THREADS
+                       b = blockInts;
+                       blockInts = 0;
+               #endif
+
+               exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
+
+               #ifdef USE_THREADS
+                       assert(blockInts == 0);
+                       blockInts = b;
+               #endif
+
+               if (exceptionptr) {                     
+                       printf ("#### initializeSystemClass has thrown: ");
+                       utf_display (exceptionptr->vftbl->class->name);
+                       printf ("\n");
+                       fflush (stdout);                  
+               }
+       }
 }
 
 
 
 
-/********* Funktion: class_showconstantpool   (nur f"ur Debug-Zwecke) ********/
+/********* Function: class_showconstantpool   (debugging only) *********/
 
 void class_showconstantpool (classinfo *c) 
 {
@@ -1678,7 +2141,7 @@ void class_showconstantpool (classinfo *c)
                        switch (c -> cptags [i]) {
                                case CONSTANT_Class:
                                        printf ("Classreference -> ");
-                                       unicode_display ( ((classinfo*)e) -> name );
+                                       utf_display ( ((classinfo*)e) -> name );
                                        break;
                                
                                case CONSTANT_Fieldref:
@@ -1690,17 +2153,17 @@ void class_showconstantpool (classinfo *c)
                                  displayFMI:
                                        {
                                        constant_FMIref *fmi = e;
-                                       unicode_display ( fmi->class->name );
+                                       utf_display ( fmi->class->name );
                                        printf (".");
-                                       unicode_display ( fmi->name);
+                                       utf_display ( fmi->name);
                                        printf (" ");
-                                       unicode_display ( fmi->descriptor );
+                                       utf_display ( fmi->descriptor );
                                    }
                                        break;
 
                                case CONSTANT_String:
                                        printf ("String -> ");
-                                       unicode_display (e);
+                                       utf_display (e);
                                        break;
                                case CONSTANT_Integer:
                                        printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
@@ -1725,14 +2188,14 @@ void class_showconstantpool (classinfo *c)
                                case CONSTANT_NameAndType:
                                        { constant_nameandtype *cnt = e;
                                          printf ("NameAndType: ");
-                                         unicode_display (cnt->name);
+                                         utf_display (cnt->name);
                                          printf (" ");
-                                         unicode_display (cnt->descriptor);
+                                         utf_display (cnt->descriptor);
                                        }
                                        break;
                                case CONSTANT_Utf8:
                                        printf ("Utf8 -> ");
-                                       unicode_display (e);
+                                       utf_display (e);
                                        break;
                                case CONSTANT_Arraydescriptor:  {
                                        printf ("Arraydescriptor: ");
@@ -1752,25 +2215,25 @@ void class_showconstantpool (classinfo *c)
 
 
 
-/********** Funktion: class_showmethods   (nur f"ur Debug-Zwecke) ************/
+/********** Function: class_showmethods   (debugging only) *************/
 
 void class_showmethods (classinfo *c)
 {
-       u4 i;
+       s4 i;
        
        printf ("--------- Fields and Methods ----------------\n");
        printf ("Flags: ");     printflags (c->flags);  printf ("\n");
 
-       printf ("This: "); unicode_display (c->name); printf ("\n");
+       printf ("This: "); utf_display (c->name); printf ("\n");
        if (c->super) {
-               printf ("Super: "); unicode_display (c->super->name); printf ("\n");
+               printf ("Super: "); utf_display (c->super->name); printf ("\n");
                }
        printf ("Index: %d\n", c->index);
        
        printf ("interfaces:\n");       
        for (i=0; i < c-> interfacescount; i++) {
                printf ("   ");
-               unicode_display (c -> interfaces[i] -> name);
+               utf_display (c -> interfaces[i] -> name);
                printf (" (%d)\n", c->interfaces[i] -> index);
                }
 
@@ -1798,20 +2261,21 @@ void class_showmethods (classinfo *c)
 
 
 
-/*****************************************************************************/
-/******************* Funktionen fuer den Class-loader generell ***************/
-/*****************************************************************************/
+/******************************************************************************/
+/******************* General functions for the class loader *******************/
+/******************************************************************************/
 
+static int loader_inited = 0;
 
-/********************* Funktion: loader_load **********************************
+/********************* Function: loader_load ***********************************
 
-       l"adt und linkt die ge"unschte Klasse und alle davon 
-       referenzierten Klassen und Interfaces
-       Return: Einen Zeiger auf diese Klasse
+       Loads and links the class desired class and each class and interface
+       referenced by it.
+       Returns: a pointer to this class
 
-******************************************************************************/
+*******************************************************************************/
 
-classinfo *loader_load (unicode *topname)
+classinfo *loader_load (utf *topname)
 {
        classinfo *top;
        classinfo *c;
@@ -1819,18 +2283,28 @@ classinfo *loader_load (unicode *topname)
        
        intsDisable();                           /* schani */
 
-       if (getloadingtime) starttime = getcputime();
+       if (getloadingtime)
+               starttime = getcputime();
 
-       top = class_get (topname);
+       top = class_new (topname);
 
+       /* load classes */
        while ( (c = list_first(&unloadedclasses)) ) {
-               class_load (c);
-               }
+               if (!class_load (c)) {
+                       list_remove (&unloadedclasses, c);
+                       top=NULL;
+                   }
+        }
 
+       /* link classes */
        while ( (c = list_first(&unlinkedclasses)) ) {
                class_link (c);
                }
 
+       if (loader_inited)
+               loader_compute_subclasses();
+
+       /* measure time */
        if (getloadingtime) {
                stoptime = getcputime();
                loadingtime += (stoptime-starttime);
@@ -1838,71 +2312,130 @@ classinfo *loader_load (unicode *topname)
 
        intsRestore();                          /* schani */
 
-       return top;
+       return top; 
 }
 
 
-/******************* interne Funktion: loader_createarrayclass ****************
+/**************** function: create_primitive_classes ***************************
 
-       Erzeugt (und linkt) eine Klasse f"ur die Arrays.
-       
-******************************************************************************/
+       create classes representing primitive types 
 
-static classinfo *loader_createarrayclass ()
-{
-       classinfo *c;
-       c = class_get ( unicode_new_char ("The_Array_Class") );
-       
+********************************************************************************/
+
+
+void create_primitive_classes()
+{  
+       int i;
+
+       for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
+               /* create primitive class */
+               classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
+               
+               /* prevent loader from loading primitive class */
+               list_remove (&unloadedclasses, c);
+               /* add to unlinked classes */
+               list_addlast (&unlinkedclasses, c);             
+               c -> super = class_java_lang_Object;
+               class_link (c);
+
+               primitivetype_table[i].class_primitive = c;
+
+               /* create class for wrapping the primitive type */
+               primitivetype_table[i].class_wrap =
+                       class_new( utf_new_char(primitivetype_table[i].wrapname) );
+       }
+}
+
+/***************** function: create_array_class ********************************
+
+       create class representing an array
+
+********************************************************************************/
+
+
+classinfo *create_array_class(utf *u)
+{  
+       classinfo *c = class_new (u);
+       /* prevent loader from loading the array class */
        list_remove (&unloadedclasses, c);
+       /* add to unlinked classes */
        list_addlast (&unlinkedclasses, c);
        c -> super = class_java_lang_Object;
-       
-       class_link (c);
+       class_link(c);
+
        return c;
 }
 
+/********************** Function: loader_init **********************************
 
+       Initializes all lists and loads all classes required for the system or the
+       compiler.
 
-/********************** Funktion: loader_init *********************************
-
-       Initialisiert alle Listen und l"adt alle Klassen, die vom System
-       und vom Compiler direkt ben"otigt werden.
-
-******************************************************************************/
+*******************************************************************************/
  
 void loader_init ()
 {
+       utf *string_class;
        interfaceindex = 0;
        
        list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
        list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
        list_init (&linkedclasses, OFFSET(classinfo, listnode) );
 
+       /* create utf-symbols for pointer comparison of frequently used strings */
+       utf_innerclasses    = utf_new_char("InnerClasses");
+       utf_constantvalue   = utf_new_char("ConstantValue");
+       utf_code                = utf_new_char("Code");
+       utf_finalize        = utf_new_char("finalize");
+       utf_fidesc              = utf_new_char("()V");
+       utf_clinit              = utf_new_char("<clinit>");
+       utf_initsystemclass = utf_new_char("initializeSystemClass");
+       utf_systemclass     = utf_new_char("java/lang/System");
+
+       /* create class for arrays */
+       class_array = class_new ( utf_new_char ("The_Array_Class") );
+       list_remove (&unloadedclasses, class_array);
+
+       /* create class for strings, load it after class Object was loaded */
+       string_class = utf_new_char ("java/lang/String");
+       class_java_lang_String = class_new(string_class);
+       list_remove (&unloadedclasses, class_java_lang_String);
 
        class_java_lang_Object = 
-               loader_load ( unicode_new_char ("java/lang/Object") );
+               loader_load ( utf_new_char ("java/lang/Object") );
+
+       list_addlast(&unloadedclasses, class_java_lang_String);
+
        class_java_lang_String = 
-               loader_load ( unicode_new_char ("java/lang/String") );
+               loader_load ( string_class );
        class_java_lang_ClassCastException = 
-               loader_load ( unicode_new_char ("java/lang/ClassCastException") );
+               loader_load ( utf_new_char ("java/lang/ClassCastException") );
        class_java_lang_NullPointerException = 
-               loader_load ( unicode_new_char ("java/lang/NullPointerException") );
+               loader_load ( utf_new_char ("java/lang/NullPointerException") );
        class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( 
-            unicode_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
+            utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
        class_java_lang_NegativeArraySizeException = loader_load ( 
-            unicode_new_char ("java/lang/NegativeArraySizeException") );
+            utf_new_char ("java/lang/NegativeArraySizeException") );
        class_java_lang_OutOfMemoryError = loader_load ( 
-            unicode_new_char ("java/lang/OutOfMemoryError") );
+            utf_new_char ("java/lang/OutOfMemoryError") );
        class_java_lang_ArrayStoreException =
-               loader_load ( unicode_new_char ("java/lang/ArrayStoreException") );
+               loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
        class_java_lang_ArithmeticException = 
-               loader_load ( unicode_new_char ("java/lang/ArithmeticException") );
+               loader_load ( utf_new_char ("java/lang/ArithmeticException") );
        class_java_lang_ThreadDeath =                             /* schani */
-               loader_load ( unicode_new_char ("java/lang/ThreadDeath") );
+               loader_load ( utf_new_char ("java/lang/ThreadDeath") );
 
-       class_array = loader_createarrayclass ();
+       /* link class for arrays */
+       list_addlast (&unlinkedclasses, class_array);
+       class_array -> super = class_java_lang_Object;
+       class_link (class_array);
 
+       /* correct vftbl-entries (retarded loading of class java/lang/String) */
+       stringtable_update(); 
 
+       /* create classes representing primitive types */
+       create_primitive_classes();
+               
        proto_java_lang_ClassCastException = 
                builtin_new(class_java_lang_ClassCastException);
        heap_addreference ( (void**) &proto_java_lang_ClassCastException);
@@ -1934,16 +2467,18 @@ void loader_init ()
        proto_java_lang_ThreadDeath =                             /* schani */
                builtin_new(class_java_lang_ThreadDeath);
        heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
+
+       loader_inited = 1;
 }
 
 
 
 
-/********************* Funktion: loader_initclasses ****************************
+/********************* Function: loader_initclasses ****************************
 
-       initialisiert alle geladenen aber noch nicht initialisierten Klassen
+       Initializes all loaded but uninitialized classes
 
-******************************************************************************/
+*******************************************************************************/
 
 void loader_initclasses ()
 {
@@ -1962,26 +2497,26 @@ void loader_initclasses ()
        intsRestore();                      /* schani */
 }
 
-static s4 classvalue = 0;
+static s4 classvalue;
 
 static void loader_compute_class_values (classinfo *c)
 {
        classinfo *subs;
 
-       c->vftbl->lowclassval = classvalue++;
+       c->vftbl->baseval = ++classvalue;
        subs = c->sub;
        while (subs != NULL) {
                loader_compute_class_values(subs);
                subs = subs->nextsub;
                }
-       c->vftbl->highclassval = classvalue++;
+       c->vftbl->diffval = classvalue - c->vftbl->baseval;
 /*
        {
        int i;
        for (i = 0; i < c->index; i++)
                printf(" ");
-       printf("%3d  %3d  ", (int) c->vftbl->lowclassval, (int) c->vftbl->highclassval);
-       unicode_display(c->name);
+       printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
+       utf_display(c->name);
        printf("\n");
        }
 */
@@ -1994,6 +2529,15 @@ void loader_compute_subclasses ()
        
        intsDisable();                     /* schani */
 
+       c = list_first (&linkedclasses);
+       while (c) {
+               if (!(c->flags & ACC_INTERFACE)) {
+                       c->nextsub = 0;
+                       c->sub = 0;
+                       }
+               c = list_next (&linkedclasses, c);
+               }
+
        c = list_first (&linkedclasses);
        while (c) {
                if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
@@ -2003,6 +2547,7 @@ void loader_compute_subclasses ()
                c = list_next (&linkedclasses, c);
                }
 
+       classvalue = 0;
        loader_compute_class_values(class_java_lang_Object);
 
        intsRestore();                      /* schani */
@@ -2010,11 +2555,25 @@ void loader_compute_subclasses ()
 
 
 
-/******************** Funktion: loader_close **********************************
+/******************** function classloader_buffer ******************************
+    sets buffer for reading classdata
+
+*******************************************************************************/
+
+void classload_buffer(u1 *buf, int len)
+{
+       classbuffer        =  buf;
+       classbuffer_size   =  len;
+       classbuf_pos       =  buf - 1;
+}
 
-       gibt alle Resourcen wieder frei
+
+/******************** Function: loader_close ***********************************
+
+       Frees all resources
        
-******************************************************************************/
+*******************************************************************************/
 
 void loader_close ()
 {
@@ -2034,3 +2593,17 @@ void loader_close ()
                }
 }
 
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+