Changed some blockInts assertions to > 0.
[cacao.git] / loader.c
1
2 /* loader.c ********************************************************************
3
4         Copyright (c) 1999 A. Krall, R. Grafl, R. Obermaiser, M. Probst
5
6         See file COPYRIGHT for information on usage and disclaimer of warranties
7
8         Contains the functions of the class loader.
9
10         Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
11         Changes: Andreas Krall       EMAIL: cacao@complang.tuwien.ac.at
12                  Roman Obermaiser    EMAIL: cacao@complang.tuwien.ac.at
13                  Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
14
15         Last Change: 1999/11/08
16
17 *******************************************************************************/
18
19
20 #include <assert.h>
21
22 #include "global.h"
23 #include "loader.h"
24 #include "native.h"
25 #include "tables.h"
26 #include "builtin.h"
27 #include "jit.h"
28 #ifdef OLD_COMPILER
29 #include "compiler.h"
30 #endif
31 #include "asmpart.h"
32
33 #include "threads/thread.h"
34 #include <sys/stat.h>
35
36 /* global variables ***********************************************************/
37
38 extern bool newcompiler;        /* true if new compiler is used               */                
39
40 int count_class_infos = 0;      /* variables for measurements                 */
41 int count_const_pool_len = 0;
42 int count_vftbl_len = 0;
43 int count_all_methods = 0;
44 int count_vmcode_len = 0;
45 int count_extable_len = 0;
46 int count_class_loads = 0;
47 int count_class_inits = 0;
48
49 bool loadverbose = false;       /* switches for debug messages                */
50 bool linkverbose = false;
51 bool initverbose = false;
52
53 bool makeinitializations = true;
54
55 bool getloadingtime  = false;   /* to measure the runtime                     */
56 long int loadingtime = 0;
57
58 static s4 interfaceindex;       /* sequential numbering of interfaces         */ 
59
60 list unloadedclasses;       /* list of all referenced but not loaded classes  */
61 list unlinkedclasses;       /* list of all loaded but not linked classes      */
62 list linkedclasses;         /* list of all completely linked classes          */
63
64
65 /* utf-symbols for pointer comparison of frequently used strings */
66
67 static utf *utf_innerclasses;           /* InnerClasses                    */
68 static utf *utf_constantvalue;          /* ConstantValue                   */
69 static utf *utf_code;                       /* Code                            */
70 static utf *utf_finalize;                   /* finalize                            */
71 static utf *utf_fidesc;                     /* ()V                                     */
72 static utf *utf_clinit;                     /* <clinit>                            */
73 static utf *utf_initsystemclass;        /* initializeSystemClass   */
74 static utf *utf_systemclass;            /* java/lang/System        */
75
76
77 /* important system classes ***************************************************/
78
79 classinfo *class_java_lang_Object;
80 classinfo *class_java_lang_String;
81 classinfo *class_java_lang_ClassCastException;
82 classinfo *class_java_lang_NullPointerException;
83 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
84 classinfo *class_java_lang_NegativeArraySizeException;
85 classinfo *class_java_lang_OutOfMemoryError;
86 classinfo *class_java_lang_ArithmeticException;
87 classinfo *class_java_lang_ArrayStoreException;
88 classinfo *class_java_lang_ThreadDeath;
89 classinfo *class_array = NULL;
90
91
92 /******************************************************************************
93
94    structure for primitive classes: contains the class for wrapping the 
95    primitive type, the primitive class, the name of the class for wrapping, 
96    the one character type signature and the name of the primitive class
97  
98  ******************************************************************************/
99  
100 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { 
101                 { NULL, NULL, "java/lang/Double",    'D', "double"  },
102                 { NULL, NULL, "java/lang/Float",     'F', "float"   },
103                 { NULL, NULL, "java/lang/Character", 'C', "char"    },
104                 { NULL, NULL, "java/lang/Integer",   'I', "int"     },
105                 { NULL, NULL, "java/lang/Long",      'J', "long"    },
106                 { NULL, NULL, "java/lang/Byte",      'B', "byte"    },
107                 { NULL, NULL, "java/lang/Short",     'S', "short"   },
108                 { NULL, NULL, "java/lang/Boolean",   'Z', "boolean" },
109                 { NULL, NULL, "java/lang/Void",      'V', "void"    }};
110
111
112 /* instances of important system classes **************************************/
113
114 java_objectheader *proto_java_lang_ClassCastException;
115 java_objectheader *proto_java_lang_NullPointerException;
116 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
117 java_objectheader *proto_java_lang_NegativeArraySizeException;
118 java_objectheader *proto_java_lang_OutOfMemoryError;
119 java_objectheader *proto_java_lang_ArithmeticException;
120 java_objectheader *proto_java_lang_ArrayStoreException;
121 java_objectheader *proto_java_lang_ThreadDeath;
122
123
124 /************* functions for reading classdata *********************************
125
126     getting classdata in blocks of variable size
127     (8,16,32,64-bit integer or float)
128
129 *******************************************************************************/
130
131 static char *classpath    = "";     /* searchpath for classfiles              */
132 static u1 *classbuffer    = NULL;   /* pointer to buffer with classfile-data  */
133 static u1 *classbuf_pos;            /* current position in classfile buffer   */
134 static int classbuffer_size;        /* size of classfile-data                 */
135
136 /* transfer block of classfile data into a buffer */
137
138 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
139                                 classbuf_pos+=len;
140
141 /* skip block of classfile data */
142
143 #define skip_nbytes(len) classbuf_pos+=len;
144
145 #define suck_u1() (*++classbuf_pos)
146 #define suck_s8() (s8) suck_u8()
147 #define suck_s2() (s2) suck_u2()
148 #define suck_s4() (s4) suck_u4()
149 #define suck_s1() (s1) suck_u1()
150 #define suck_u2() (u2) ((suck_u1()<<8)+suck_u1())
151 #define suck_u4() (u4) ((((u4)suck_u1())<<24)+(((u4)suck_u1())<<16)+(((u4)suck_u1())<<8)+((u4)suck_u1()))
152
153
154 /* get u8 from classfile data */
155
156 static u8 suck_u8 ()
157 {
158 #if U8_AVAILABLE
159         u8 lo,hi;
160         hi = suck_u4();
161         lo = suck_u4();
162         return (hi<<32) + lo;
163 #else
164         u8 v;
165         v.high = suck_u4();
166         v.low = suck_u4();
167         return v;
168 #endif
169 }
170
171 /* get float from classfile data */
172
173 static float suck_float ()
174 {
175         float f;
176
177 #if !WORDS_BIGENDIAN 
178                 u1 buffer[4];
179                 u2 i;
180                 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
181                 memcpy ( (u1*) (&f), buffer, 4);
182 #else 
183                 suck_nbytes ( (u1*) (&f), 4 );
184 #endif
185
186         PANICIF (sizeof(float) != 4, "Incompatible float-format");
187         
188         return f;
189 }
190
191 /* get double from classfile data */
192 static double suck_double ()
193 {
194         double d;
195
196 #if !WORDS_BIGENDIAN 
197                 u1 buffer[8];
198                 u2 i;   
199                 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
200                 memcpy ( (u1*) (&d), buffer, 8);
201 #else 
202                 suck_nbytes ( (u1*) (&d), 8 );
203 #endif
204
205         PANICIF (sizeof(double) != 8, "Incompatible double-format" );
206         
207         return d;
208 }
209
210 /************************** function suck_init *********************************
211
212         called once at startup, sets the searchpath for the classfiles
213
214 *******************************************************************************/
215
216 void suck_init (char *cpath)
217 {
218         classpath   = cpath;
219         classbuffer = NULL;
220 }
221
222
223 /************************** function suck_start ********************************
224
225         returns true if classbuffer is already loaded or a file for the
226         specified class has succussfully been read in. All directories of
227         the searchpath are used to find the classfile (<classname>.class).
228         Returns false if no classfile is found and writes an error message. 
229         
230 *******************************************************************************/
231
232
233 bool suck_start (utf *classname) {
234
235 #define MAXFILENAME 1000                /* maximum length of a filename           */
236         
237         char filename[MAXFILENAME+10];  /* room for '.class'                      */    
238         char *pathpos;                  /* position in searchpath                 */
239         char c, *utf_ptr;               /* pointer to the next utf8-character     */
240         FILE *classfile;
241         int  filenamelen, err;
242         struct stat buffer;
243         
244         if (classbuffer)                /* classbuffer is already valid */
245                 return true;
246
247         pathpos = classpath;
248         
249         while (*pathpos) {
250
251                 /* skip path separator */
252
253                 while (*pathpos == ':')
254                         pathpos++;
255  
256                 /* extract directory from searchpath */
257
258                 filenamelen = 0;
259                 while ((*pathpos) && (*pathpos!=':')) {
260                     PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
261                         filename[filenamelen++] = *(pathpos++);
262                         }
263
264                 filename[filenamelen++] = '/';  
265    
266                 /* add classname to filename */
267
268                 utf_ptr = classname->text;
269                 while (utf_ptr < utf_end(classname)) {
270                         PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
271                         c = *utf_ptr++;
272                         if ((c <= ' ' || c > 'z') && (c != '/'))     /* invalid character */ 
273                                 c = '?'; 
274                         filename[filenamelen++] = c;    
275                         }
276       
277                 /* add suffix */
278
279                 strcpy (filename+filenamelen, ".class");
280
281                 classfile = fopen(filename, "r");
282                 if (classfile) {                                       /* file exists */
283                         
284                         /* determine size of classfile */
285
286                         err = stat (filename, &buffer);
287
288                         if (!err) {                                /* read classfile data */                            
289                                 classbuffer_size = buffer.st_size;                              
290                                 classbuffer      = MNEW(u1, classbuffer_size);
291                                 classbuf_pos     = classbuffer-1;
292                                 fread(classbuffer, 1, classbuffer_size, classfile);
293                                 fclose(classfile);
294                                 return true;
295                         }
296                 }
297         }
298
299         if (verbose) {
300                 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
301                 dolog();
302         }
303
304         return false;
305 }
306
307
308 /************************** function suck_stop *********************************
309
310         frees memory for buffer with classfile data.
311         Caution: this function may only be called if buffer has been allocated
312                  by suck_start with reading a file
313         
314 *******************************************************************************/
315
316 void suck_stop () {
317
318         /* determine amount of classdata not retrieved by suck-operations         */
319
320         int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
321
322         if (classdata_left > 0) {               
323                 /* surplus */           
324                 sprintf (logtext,"There are %d access bytes at end of classfile",
325                          classdata_left);
326                 dolog();
327         }
328
329         /* free memory */
330
331         MFREE(classbuffer, u1, classbuffer_size);
332         classbuffer = NULL;
333 }
334
335 /******************************************************************************/
336 /******************* Einige Support-Funkionen *********************************/
337 /******************************************************************************/
338
339
340 /********** interne Funktion: printflags  (nur zu Debug-Zwecken) **************/
341
342 static void printflags (u2 f)
343 {
344    if ( f & ACC_PUBLIC )       printf (" PUBLIC");
345    if ( f & ACC_PRIVATE )      printf (" PRIVATE");
346    if ( f & ACC_PROTECTED )    printf (" PROTECTED");
347    if ( f & ACC_STATIC )       printf (" STATIC");
348    if ( f & ACC_FINAL )        printf (" FINAL");
349    if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
350    if ( f & ACC_VOLATILE )     printf (" VOLATILE");
351    if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
352    if ( f & ACC_NATIVE )       printf (" NATIVE");
353    if ( f & ACC_INTERFACE )    printf (" INTERFACE");
354    if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
355 }
356
357
358 /************************* Funktion: skipattribute *****************************
359
360         "uberliest im ClassFile eine (1) 'attribute'-Struktur 
361
362 *******************************************************************************/
363
364 static void skipattribute ()
365 {
366         suck_u2 ();
367         skip_nbytes(suck_u4()); 
368 }
369
370 /********************** Funktion: skipattributebody ****************************
371
372         "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name - 
373         Referenz schon gelesen worden ist.
374         
375 *******************************************************************************/
376
377 static void skipattributebody ()
378 {
379         skip_nbytes(suck_u4());
380 }
381
382 /************************* Funktion: skipattributes ****************************
383
384         "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
385         
386 *******************************************************************************/
387
388 static void skipattributes (u4 num)
389 {
390         u4 i;
391         for (i = 0; i < num; i++)
392                 skipattribute();
393 }
394
395 /******************** function: innerclass_getconstant ************************
396
397     like class_getconstant, but if cptags is ZERO null is returned                                       
398         
399 *******************************************************************************/
400
401 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype) 
402 {
403         /* invalid position in constantpool */
404         if (pos >= c->cpcount) 
405                 panic ("Attempt to access constant outside range");
406
407         /* constantpool entry of type 0 */      
408         if (!c->cptags[pos])
409                 return NULL;
410
411         /* check type of constantpool entry */
412         if (c->cptags[pos] != ctype) {
413                 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
414                  (int) ctype, (int) c->cptags[pos] );
415                 error();
416                 }
417                 
418         return c->cpinfos[pos];
419 }
420
421 /************************ function: attribute_load ****************************
422
423     read attributes from classfile
424         
425 *******************************************************************************/
426
427 static void attribute_load (u4 num, classinfo *c)
428 {
429         u4 i,j;
430
431         for (i = 0; i < num; i++) {
432                 /* retrieve attribute name */   
433                 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
434
435                 if ( aname == utf_innerclasses)  {                      
436                         /* innerclasses attribute */
437                                 
438                         /* skip attribute length */                                             
439                         suck_u4(); 
440                         /* number of records */
441                         c->innerclasscount = suck_u2();
442                         /* allocate memory for innerclass structure */
443                         c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
444
445                         for (j=0;j<c->innerclasscount;j++) {
446                                 
447                                 /*  The innerclass structure contains a class with an encoded name, 
448                                     its defining scope, its simple name  and a bitmask of the access flags. 
449                                     If an inner class is not a member, its outer_class is NULL, 
450                                     if a class is anonymous, its name is NULL.                              */
451                                                                 
452                                 innerclassinfo *info = c->innerclass + j;
453
454                                 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
455                                 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
456                                 info->name  = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8);        /* CONSTANT_Utf8_info index  */
457                                 info->flags = suck_u2 ();                                                 /* access_flags bitmask      */
458                         }
459                 } else {
460                         /* unknown attribute */
461                         skipattributebody ();
462                 }
463         }
464 }
465
466 /******************* function: checkfielddescriptor ****************************
467
468         checks whether a field-descriptor is valid and aborts otherwise
469         all referenced classes are inserted into the list of unloaded classes
470         
471 *******************************************************************************/
472
473 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
474 {
475         char *tstart;  /* pointer to start of classname */
476         char ch;
477         
478         switch (*utf_ptr++) {
479         case 'B':
480         case 'C':
481         case 'I':
482         case 'S':
483         case 'Z':  
484         case 'J':  
485         case 'F':  
486         case 'D':
487                 /* primitive type */  
488                 break;
489
490         case 'L':
491                 /* save start of classname */
492                 tstart = utf_ptr;  
493                 
494                 /* determine length of classname */
495                 while ( *utf_ptr++ != ';' )
496                         if (utf_ptr>=end_pos) 
497                                 panic ("Missing ';' in objecttype-descriptor");
498
499                 /* cause loading of referenced class */                 
500                 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
501                 break;
502
503         case '[' : 
504                 /* array type */
505                 while ((ch = *utf_ptr++)=='[') 
506                         /* skip */ ;
507
508                 /* component type of array */
509                 switch (ch) {
510                 case 'B':
511                 case 'C':
512                 case 'I':
513                 case 'S':
514                 case 'Z':  
515                 case 'J':  
516                 case 'F':  
517                 case 'D':
518                         /* primitive type */  
519                         break;
520                         
521                 case 'L':
522                         /* save start of classname */
523                         tstart = utf_ptr;
524                         
525                         /* determine length of classname */
526                         while ( *utf_ptr++ != ';' )
527                                 if (utf_ptr>=end_pos) 
528                                         panic ("Missing ';' in objecttype-descriptor");
529
530                         /* cause loading of referenced class */                 
531                         class_new ( utf_new(tstart, utf_ptr-tstart-1) );
532                         break;
533
534                 default:   
535                         panic ("Ill formed methodtype-descriptor");
536                 }
537                 break;
538                         
539         default:   
540                 panic ("Ill formed methodtype-descriptor");
541         }                       
542
543         /* exceeding characters */              
544         if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
545 }
546
547
548 /******************* function checkmethoddescriptor ****************************
549
550     checks whether a method-descriptor is valid and aborts otherwise.
551     All referenced classes are inserted into the list of unloaded classes.
552         
553 *******************************************************************************/
554
555 static void checkmethoddescriptor (utf *d)
556 {
557         char *utf_ptr = d->text;     /* current position in utf text   */
558         char *end_pos = utf_end(d);  /* points behind utf string       */
559         char *tstart;                /* pointer to start of classname  */
560         char c,ch;
561
562         /* method descriptor must start with parenthesis */
563         if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
564
565         /* check arguments */
566         while ((c = *utf_ptr++) != ')') {
567                 switch (c) {
568                 case 'B':
569                 case 'C':
570                 case 'I':
571                 case 'S':
572                 case 'Z':  
573                 case 'J':  
574                 case 'F':  
575                 case 'D':
576                         /* primitive type */  
577                         break;
578
579                 case 'L':
580                         /* save start of classname */ 
581                         tstart = utf_ptr;
582                         
583                         /* determine length of classname */
584                         while ( *utf_ptr++ != ';' )
585                                 if (utf_ptr>=end_pos) 
586                                         panic ("Missing ';' in objecttype-descriptor");
587                         
588                         /* cause loading of referenced class */
589                         class_new ( utf_new(tstart, utf_ptr-tstart-1) );
590                         break;
591            
592                 case '[' :
593                         /* array type */ 
594                         while ((ch = *utf_ptr++)=='[') 
595                                 /* skip */ ;
596
597                         /* component type of array */
598                         switch (ch) {
599                         case 'B':
600                         case 'C':
601                         case 'I':
602                         case 'S':
603                         case 'Z':  
604                         case 'J':  
605                         case 'F':  
606                         case 'D':
607                                 /* primitive type */  
608                                 break;
609
610                         case 'L':
611                                 /* save start of classname */
612                                 tstart = utf_ptr;
613                         
614                                 /* determine length of classname */     
615                                 while ( *utf_ptr++ != ';' )
616                                         if (utf_ptr>=end_pos) 
617                                                 panic ("Missing ';' in objecttype-descriptor");
618
619                                 /* cause loading of referenced class */
620                                 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
621                                 break;
622
623                         default:   
624                                 panic ("Ill formed methodtype-descriptor");
625                         } 
626                         break;
627                         
628                 default:   
629                         panic ("Ill formed methodtype-descriptor");
630                 }                       
631         }
632
633         /* check returntype */
634         if (*utf_ptr=='V') {
635                 /* returntype void */
636                 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
637         }
638         else
639                 /* treat as field-descriptor */
640                 checkfielddescriptor (utf_ptr,end_pos);
641 }
642
643
644 /******************** Funktion: buildarraydescriptor ***************************
645
646         erzeugt zu einem namentlich als utf-String vorliegenden Arraytyp eine
647         entsprechende constant_arraydescriptor - Struktur 
648         
649 *******************************************************************************/
650
651 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
652 {
653         constant_arraydescriptor *d;
654         
655         if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
656
657         d = NEW (constant_arraydescriptor);
658         d -> objectclass = NULL;
659         d -> elementdescriptor = NULL;
660
661 #ifdef STATISTICS
662         count_const_pool_len += sizeof(constant_arraydescriptor);
663 #endif
664
665         switch (*utf_ptr) {
666         case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
667         case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
668         case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
669         case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
670         case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
671         case 'I': d -> arraytype = ARRAYTYPE_INT; break;
672         case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
673         case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
674
675         case '[':
676                 d -> arraytype = ARRAYTYPE_ARRAY; 
677                 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
678                 break;
679                 
680         case 'L':
681                 d -> arraytype = ARRAYTYPE_OBJECT;
682                 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
683                 break;
684         }
685         return d;
686 }
687
688
689 /******************* Funktion: freearraydescriptor *****************************
690
691         entfernt eine mit buildarraydescriptor erzeugte Struktur wieder 
692         aus dem Speicher
693         
694 *******************************************************************************/
695
696 static void freearraydescriptor (constant_arraydescriptor *d)
697 {
698         while (d) {
699                 constant_arraydescriptor *n = d->elementdescriptor;
700                 FREE (d, constant_arraydescriptor);
701                 d = n;
702                 }
703 }
704
705 /*********************** Funktion: displayarraydescriptor *********************/
706
707 static void displayarraydescriptor (constant_arraydescriptor *d)
708 {
709         switch (d->arraytype) {
710         case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
711         case ARRAYTYPE_BYTE: printf ("byte[]"); break;
712         case ARRAYTYPE_CHAR: printf ("char[]"); break;
713         case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
714         case ARRAYTYPE_FLOAT: printf ("float[]"); break;
715         case ARRAYTYPE_INT: printf ("int[]"); break;
716         case ARRAYTYPE_LONG: printf ("long[]"); break;
717         case ARRAYTYPE_SHORT: printf ("short[]"); break;
718         case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
719         case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
720         }
721 }
722
723
724
725 /******************************************************************************/
726 /******************** Funktionen fuer Fields **********************************/
727 /******************************************************************************/
728
729
730 /************************ Funktion: field_load *********************************
731
732         l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
733         und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
734         Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
735         reserviert.
736
737 *******************************************************************************/
738
739 static void field_load (fieldinfo *f, classinfo *c)
740 {
741         u4 attrnum,i;
742         u4 jtype;
743
744         f -> flags = suck_u2 ();                                           /* ACC flags                   */
745         f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);       /* name of field               */
746         f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor           */
747         f -> type = jtype = desc_to_type (f->descriptor);                  /* data type                   */
748         f -> offset = 0;                                                   /* offset from start of object */
749         
750         switch (f->type) {
751         case TYPE_INT:        f->value.i = 0; break;
752         case TYPE_FLOAT:      f->value.f = 0.0; break;
753         case TYPE_DOUBLE:     f->value.d = 0.0; break;
754         case TYPE_ADDRESS:    f->value.a = NULL;                              
755                               heap_addreference (&(f->value.a));           /* make global reference (GC)  */    
756                               break;
757         case TYPE_LONG:
758 #if U8_AVAILABLE
759                 f->value.l = 0; break;
760 #else
761                 f->value.l.low = 0; f->value.l.high = 0; break;
762 #endif 
763         }
764
765         /* read attributes */
766         attrnum = suck_u2();
767         for (i=0; i<attrnum; i++) {
768                 u4 pindex;
769                 utf *aname;
770
771                 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
772                 
773                 if ( aname != utf_constantvalue ) {
774                         /* unknown attribute */
775                         skipattributebody ();
776                         }
777                 else {
778                         /* constant value attribute */
779                         
780                         /* skip attribute length */
781                         suck_u4();
782                         /* index of value in constantpool */            
783                         pindex = suck_u2();
784                 
785                         /* initialize field with value from constantpool */             
786                         switch (jtype) {
787                                 case TYPE_INT: {
788                                         constant_integer *ci = 
789                                                 class_getconstant(c, pindex, CONSTANT_Integer);
790                                         f->value.i = ci -> value;
791                                         }
792                                         break;
793                                         
794                                 case TYPE_LONG: {
795                                         constant_long *cl = 
796                                            class_getconstant(c, pindex, CONSTANT_Long);
797         
798                                         f->value.l = cl -> value;
799                                         }
800                                         break;
801
802                                 case TYPE_FLOAT: {
803                                         constant_float *cf = 
804                                             class_getconstant(c, pindex, CONSTANT_Float);
805         
806                                         f->value.f = cf->value;
807                                         }
808                                         break;
809                                                                                         
810                                 case TYPE_DOUBLE: {
811                                         constant_double *cd = 
812                                             class_getconstant(c, pindex, CONSTANT_Double);
813         
814                                         f->value.d = cd->value;
815                                         }
816                                         break;
817                                                 
818                                 case TYPE_ADDRESS: { 
819                                         utf *u = class_getconstant(c, pindex, CONSTANT_String);
820                                         /* create javastring from compressed utf8-string */                                     
821                                         f->value.a = literalstring_new(u);
822                                         }
823                                         break;
824         
825                                 default: 
826                                         log_text ("Invalid Constant - Type");
827
828                                 }
829
830                         }
831                 }
832 }
833
834
835 /********************** function: field_free **********************************/
836
837 static void field_free (fieldinfo *f)
838 {
839         /* empty */
840 }
841
842
843 /************** Funktion: field_display (nur zu Debug-Zwecken) ****************/
844
845 static void field_display (fieldinfo *f)
846 {
847         printf ("   ");
848         printflags (f -> flags);
849         printf (" ");
850         utf_display (f -> name);
851         printf (" ");
852         utf_display (f -> descriptor);  
853         printf (" offset: %ld\n", (long int) (f -> offset) );
854 }
855
856
857 /******************************************************************************/
858 /************************* Funktionen f"ur Methods ****************************/ 
859 /******************************************************************************/
860
861
862 /*********************** Funktion: method_load *********************************
863
864         l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit 
865         eine schon existierende 'methodinfo'-Struktur aus.
866         Bei allen native-Methoden wird au"serdem gleich der richtige 
867         Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
868         Zeiger auf den Compiler 
869         
870 *******************************************************************************/
871
872 static void method_load (methodinfo *m, classinfo *c)
873 {
874         u4 attrnum,i,e;
875         
876 #ifdef STATISTICS
877         count_all_methods++;
878 #endif
879
880         m -> class = c;
881         
882         m -> flags = suck_u2 ();
883         m -> name =  class_getconstant (c, suck_u2(), CONSTANT_Utf8);
884         m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
885         
886         m -> jcode = NULL;
887         m -> exceptiontable = NULL;
888         m -> entrypoint = NULL;
889         m -> mcode = NULL;
890         m -> stubroutine = NULL;
891         
892         if (! (m->flags & ACC_NATIVE) ) {
893                 m -> stubroutine = createcompilerstub (m);
894                 }
895         else {
896
897                 functionptr f = native_findfunction 
898                        (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
899                 if (f) {
900 #ifdef OLD_COMPILER
901                 if (newcompiler)
902 #endif
903                         m -> stubroutine = createnativestub (f, m);
904 #ifdef OLD_COMPILER
905                 else
906                         m -> stubroutine = oldcreatenativestub (f, m);
907 #endif
908                         }
909                 }
910         
911         
912         attrnum = suck_u2();
913         for (i=0; i<attrnum; i++) {
914                 utf *aname;
915
916                 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
917
918                 if ( aname != utf_code)  {
919                         skipattributebody ();
920                         }
921                 else {
922                         if (m -> jcode) panic ("Two code-attributes for one method!");
923                         
924                         suck_u4();
925                         m -> maxstack = suck_u2();
926                         m -> maxlocals = suck_u2();
927                         m -> jcodelength = suck_u4();
928                         m -> jcode = MNEW (u1, m->jcodelength);
929                         suck_nbytes (m->jcode, m->jcodelength);
930                         m -> exceptiontablelength = suck_u2 ();
931                         m -> exceptiontable = 
932                            MNEW (exceptiontable, m->exceptiontablelength);
933
934 #ifdef STATISTICS
935         count_vmcode_len += m->jcodelength + 18;
936         count_extable_len += 8 * m->exceptiontablelength;
937 #endif
938
939                         for (e=0; e < m->exceptiontablelength; e++) {
940                                 u4 idx;
941                                 m -> exceptiontable[e].startpc = suck_u2();
942                                 m -> exceptiontable[e].endpc = suck_u2();
943                                 m -> exceptiontable[e].handlerpc = suck_u2();
944
945                                 idx = suck_u2();
946                                 if (!idx) m -> exceptiontable[e].catchtype = NULL;
947                                 else {
948                                         m -> exceptiontable[e].catchtype = 
949                                       class_getconstant (c, idx, CONSTANT_Class);
950                                         }
951                                 }                       
952
953                         skipattributes ( suck_u2() );
954                         }
955                         
956                 }
957
958 }
959
960 /********************* Funktion: method_free ***********************************
961
962         gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
963         wieder frei
964
965 *******************************************************************************/
966
967 static void method_free (methodinfo *m)
968 {
969         if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
970         if (m->exceptiontable) 
971                 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
972         if (m->mcode) CFREE (m->mcode, m->mcodelength);
973         if (m->stubroutine) {
974                 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
975                 else                       removecompilerstub (m->stubroutine);
976                 }
977 }
978
979
980 /************** Funktion: method_display  (nur zu Debug-Zwecken) **************/
981
982 void method_display (methodinfo *m)
983 {
984         printf ("   ");
985         printflags (m -> flags);
986         printf (" ");
987         utf_display (m -> name);
988         printf (" "); 
989         utf_display (m -> descriptor);
990         printf ("\n");
991 }
992
993
994 /******************** Funktion: method_canoverwrite ****************************
995
996         "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch 
997         ist (also mit einer Methodendefinition eine andere "uberschrieben 
998         werden kann).
999         
1000 *******************************************************************************/  
1001
1002 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1003 {
1004         if (m->name != old->name) return false;
1005         if (m->descriptor != old->descriptor) return false;
1006         if (m->flags & ACC_STATIC) return false;
1007         return true;
1008 }
1009
1010
1011
1012
1013 /******************************************************************************/
1014 /************************ Funktionen fuer Class *******************************/
1015 /******************************************************************************/
1016
1017
1018 /******************** function: class_getconstant ******************************
1019
1020         retrieves the value at position 'pos' of the constantpool of a class
1021         if the type of the value is other than 'ctype' the system is stopped
1022
1023 *******************************************************************************/
1024
1025 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
1026 {
1027         /* invalid position in constantpool */  
1028         if (pos >= c->cpcount) 
1029                 panic ("Attempt to access constant outside range");
1030
1031         /* check type of constantpool entry */
1032         if (c->cptags[pos] != ctype) {
1033                 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1034                  (int) ctype, (int) c->cptags[pos] );
1035                 error();
1036                 }
1037                 
1038         return c->cpinfos[pos];
1039 }
1040
1041
1042 /********************* Funktion: class_constanttype ****************************
1043
1044         Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer 
1045         Klasse hat.
1046         
1047 *******************************************************************************/
1048
1049 u4 class_constanttype (classinfo *c, u4 pos)
1050 {
1051         if (pos >= c->cpcount) 
1052                 panic ("Attempt to access constant outside range");
1053         return c->cptags[pos];
1054 }
1055
1056
1057 /******************** function: class_loadcpool ********************************
1058
1059         loads the constantpool of a class, 
1060         the entries are transformed into a simpler format 
1061         by resolving references
1062         (a detailed overview of the compact structures can be found in global.h)        
1063
1064 *******************************************************************************/
1065
1066 static void class_loadcpool (classinfo *c)
1067 {
1068
1069         /* The following structures are used to save information which cannot be 
1070            processed during the first pass. After the complete constantpool has 
1071            been traversed the references can be resolved. 
1072            (only in specific order)                                                */
1073         
1074         /* CONSTANT_Class_info entries */
1075         typedef struct forward_class {      
1076                 struct forward_class *next; 
1077                 u2 thisindex;               
1078                 u2 name_index;              
1079         } forward_class;                    
1080                                         
1081         /* CONSTANT_String */                                      
1082         typedef struct forward_string { 
1083                 struct forward_string *next; 
1084                 u2 thisindex;                
1085                 u2 string_index;
1086         } forward_string;
1087
1088         /* CONSTANT_NameAndType */
1089         typedef struct forward_nameandtype {
1090                 struct forward_nameandtype *next;
1091                 u2 thisindex;
1092                 u2 name_index;
1093                 u2 sig_index;
1094         } forward_nameandtype;
1095
1096         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1097         typedef struct forward_fieldmethint {   
1098                 struct forward_fieldmethint *next;
1099                 u2 thisindex;
1100                 u1 tag;
1101                 u2 class_index;
1102                 u2 nameandtype_index;
1103         } forward_fieldmethint;
1104
1105
1106         u4 idx;
1107         long int dumpsize = dump_size ();
1108
1109         forward_class *forward_classes = NULL;
1110         forward_string *forward_strings = NULL;
1111         forward_nameandtype *forward_nameandtypes = NULL;
1112         forward_fieldmethint *forward_fieldmethints = NULL;
1113
1114         /* number of entries in the constant_pool table  */
1115         u4 cpcount       = c -> cpcount = suck_u2();
1116         /* allocate memory */
1117         u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
1118         voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1119
1120 #ifdef STATISTICS
1121         count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1122 #endif
1123         
1124         /* initialize constantpool */
1125         for (idx=0; idx<cpcount; idx++) {
1126                 cptags[idx] = CONSTANT_UNUSED;
1127                 cpinfos[idx] = NULL;
1128                 }
1129
1130                         
1131                 /******* first pass *******/
1132                 /* entries which cannot be resolved now are written into 
1133                    temporary structures and traversed again later        */
1134                    
1135         idx = 1;
1136         while (idx < cpcount) {
1137                 /* get constant type */
1138                 u4 t = suck_u1 (); 
1139                 switch ( t ) {
1140
1141                         case CONSTANT_Class: { 
1142                                 forward_class *nfc = DNEW(forward_class);
1143
1144                                 nfc -> next = forward_classes;                                                                                  
1145                                 forward_classes = nfc;
1146
1147                                 nfc -> thisindex = idx;
1148                                 /* reference to CONSTANT_NameAndType */
1149                                 nfc -> name_index = suck_u2 (); 
1150
1151                                 idx++;
1152                                 break;
1153                                 }
1154                         
1155                         case CONSTANT_Fieldref:
1156                         case CONSTANT_Methodref:
1157                         case CONSTANT_InterfaceMethodref: { 
1158                                 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1159                                 
1160                                 nff -> next = forward_fieldmethints;
1161                                 forward_fieldmethints = nff;
1162
1163                                 nff -> thisindex = idx;
1164                                 /* constant type */
1165                                 nff -> tag = t;
1166                                 /* class or interface type that contains the declaration of the field or method */
1167                                 nff -> class_index = suck_u2 (); 
1168                                 /* name and descriptor of the field or method */
1169                                 nff -> nameandtype_index = suck_u2 ();
1170
1171                                 idx ++;
1172                                 break;
1173                                 }
1174                                 
1175                         case CONSTANT_String: {
1176                                 forward_string *nfs = DNEW (forward_string);
1177                                 
1178                                 nfs -> next = forward_strings;
1179                                 forward_strings = nfs;
1180                                 
1181                                 nfs -> thisindex = idx;
1182                                 /* reference to CONSTANT_Utf8_info with string characters */
1183                                 nfs -> string_index = suck_u2 ();
1184                                 
1185                                 idx ++;
1186                                 break;
1187                                 }
1188
1189                         case CONSTANT_NameAndType: {
1190                                 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1191                                 
1192                                 nfn -> next = forward_nameandtypes;
1193                                 forward_nameandtypes = nfn;
1194                                 
1195                                 nfn -> thisindex = idx;
1196                                 /* reference to CONSTANT_Utf8_info containing simple name */
1197                                 nfn -> name_index = suck_u2 ();
1198                                 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1199                                 nfn -> sig_index = suck_u2 ();
1200                                 
1201                                 idx ++;
1202                                 break;
1203                                 }
1204
1205                         case CONSTANT_Integer: {
1206                                 constant_integer *ci = NEW (constant_integer);
1207
1208 #ifdef STATISTICS
1209         count_const_pool_len += sizeof(constant_integer);
1210 #endif
1211
1212                                 ci -> value = suck_s4 ();
1213                                 cptags [idx] = CONSTANT_Integer;
1214                                 cpinfos [idx] = ci;
1215                                 idx ++;
1216                                 
1217                                 break;
1218                                 }
1219                                 
1220                         case CONSTANT_Float: {
1221                                 constant_float *cf = NEW (constant_float);
1222
1223 #ifdef STATISTICS
1224         count_const_pool_len += sizeof(constant_float);
1225 #endif
1226
1227                                 cf -> value = suck_float ();
1228                                 cptags [idx] = CONSTANT_Float;
1229                                 cpinfos[idx] = cf;
1230                                 idx ++;
1231                                 break;
1232                                 }
1233                                 
1234                         case CONSTANT_Long: {
1235                                 constant_long *cl = NEW(constant_long);
1236                                         
1237 #ifdef STATISTICS
1238         count_const_pool_len += sizeof(constant_long);
1239 #endif
1240
1241                                 cl -> value = suck_s8 ();
1242                                 cptags [idx] = CONSTANT_Long;
1243                                 cpinfos [idx] = cl;
1244                                 idx += 2;
1245                                 break;
1246                                 }
1247                         
1248                         case CONSTANT_Double: {
1249                                 constant_double *cd = NEW(constant_double);
1250                                 
1251 #ifdef STATISTICS
1252         count_const_pool_len += sizeof(constant_double);
1253 #endif
1254
1255                                 cd -> value = suck_double ();
1256                                 cptags [idx] = CONSTANT_Double;
1257                                 cpinfos [idx] = cd;
1258                                 idx += 2;
1259                                 break;
1260                                 }
1261                                 
1262                         case CONSTANT_Utf8: { 
1263
1264                                 /* number of bytes in the bytes array (not string-length) */
1265                                 u4 length = suck_u2();
1266                                 cptags [idx]  = CONSTANT_Utf8;
1267                                 /* insert utf-string into the utf-symboltable */
1268                                 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1269                                 /* skip bytes of the string */
1270                                 skip_nbytes(length);
1271                                 idx++;
1272                                 break;
1273                                 }
1274                                                                                 
1275                         default:
1276                                 sprintf (logtext, "Unkown constant type: %d",(int) t);
1277                                 error ();
1278                 
1279                         }  /* end switch */
1280                         
1281                 } /* end while */
1282                 
1283
1284
1285            /* resolve entries in temporary structures */
1286
1287         while (forward_classes) {
1288                 utf *name =
1289                   class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1290                 
1291                 if ( (name->blength>0) && (name->text[0]=='[') ) {
1292                         /* check validity of descriptor */
1293                         checkfielddescriptor (name->text, utf_end(name)); 
1294
1295                         cptags  [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1296                         cpinfos [forward_classes -> thisindex] = 
1297                            buildarraydescriptor(name->text, name->blength);
1298
1299                         }
1300                 else {                                  
1301                         cptags  [forward_classes -> thisindex] = CONSTANT_Class;
1302                         /* retrieve class from class-table */
1303                         cpinfos [forward_classes -> thisindex] = class_new (name);
1304                         }
1305                 forward_classes = forward_classes -> next;
1306                 
1307                 }
1308
1309         while (forward_strings) {
1310                 utf *text = 
1311                   class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1312         
1313                 /* resolve utf-string */                
1314                 cptags   [forward_strings -> thisindex] = CONSTANT_String;
1315                 cpinfos  [forward_strings -> thisindex] = text;
1316                 
1317                 forward_strings = forward_strings -> next;
1318                 }       
1319
1320         while (forward_nameandtypes) {
1321                 constant_nameandtype *cn = NEW (constant_nameandtype);  
1322
1323 #ifdef STATISTICS
1324                 count_const_pool_len += sizeof(constant_nameandtype);
1325 #endif
1326
1327                 /* resolve simple name and descriptor */
1328                 cn -> name = class_getconstant 
1329                    (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1330                 cn -> descriptor = class_getconstant
1331                    (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1332                  
1333                 cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1334                 cpinfos  [forward_nameandtypes -> thisindex] = cn;
1335                 
1336                 forward_nameandtypes = forward_nameandtypes -> next;
1337                 }
1338
1339
1340         while (forward_fieldmethints)  {
1341                 constant_nameandtype *nat;
1342                 constant_FMIref *fmi = NEW (constant_FMIref);
1343
1344 #ifdef STATISTICS
1345                 count_const_pool_len += sizeof(constant_FMIref);
1346 #endif
1347                 /* resolve simple name and descriptor */
1348                 nat = class_getconstant
1349                         (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1350
1351                 fmi -> class = class_getconstant 
1352                         (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1353                 fmi -> name = nat -> name;
1354                 fmi -> descriptor = nat -> descriptor;
1355
1356                 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1357                 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1358         
1359                 switch (forward_fieldmethints -> tag) {
1360                 case CONSTANT_Fieldref:  /* check validity of descriptor */
1361                                          checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1362                                          break;
1363                 case CONSTANT_InterfaceMethodref: 
1364                 case CONSTANT_Methodref: /* check validity of descriptor */
1365                                          checkmethoddescriptor (fmi->descriptor);
1366                                          break;
1367                 }               
1368         
1369                 forward_fieldmethints = forward_fieldmethints -> next;
1370
1371                 }
1372
1373
1374         dump_release (dumpsize);
1375 }
1376
1377
1378 /********************** Funktion: class_load ***********************************
1379
1380         l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
1381         'classinfo'-Struktur mu"s bereits angelegt worden sein.
1382         
1383         Die Superklasse und die Interfaces, die diese Klasse implementiert,
1384         m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die 
1385         Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
1386         
1387         Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
1388         und in die Liste 'unlinkedclasses' eingh"angt.
1389         
1390 *******************************************************************************/
1391
1392 static int class_load (classinfo *c)
1393 {
1394         u4 i;
1395         u4 mi,ma;
1396
1397 #ifdef STATISTICS
1398         count_class_loads++;
1399 #endif
1400
1401         /* output for debugging purposes */
1402         if (loadverbose) {              
1403                 sprintf (logtext, "Loading class: ");
1404                 utf_sprint (logtext+strlen(logtext), c->name );
1405                 dolog();
1406                 }
1407         
1408         /* load classdata, throw exception on error */
1409         if (!suck_start (c->name)) {
1410                 throw_classnotfoundexception();            
1411                 return false;
1412         }
1413         
1414         /* check signature */           
1415         if (suck_u4() != MAGIC) panic("Can not find class-file signature");     
1416         /* check version */
1417         mi = suck_u2(); 
1418         ma = suck_u2();
1419         if (ma != MAJOR_VERSION) {
1420                 sprintf (logtext, "Can only support major version %d, but not %d",
1421                                  MAJOR_VERSION, (int) ma);
1422                 error();
1423                 }
1424         if (mi > MINOR_VERSION)  {
1425                 sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
1426                 error();
1427                 }
1428
1429
1430         class_loadcpool (c);
1431         
1432         /* ACC flags */
1433         c -> flags = suck_u2 (); 
1434         /* this class */
1435         suck_u2 ();       
1436         
1437         /* retrieve superclass */
1438         if ( (i = suck_u2 () ) ) {
1439                 c -> super = class_getconstant (c, i, CONSTANT_Class);
1440                 }
1441         else {
1442                 c -> super = NULL;
1443                 }
1444                          
1445         /* retrieve interfaces */
1446         c -> interfacescount = suck_u2 ();
1447         c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1448         for (i=0; i < c -> interfacescount; i++) {
1449                 c -> interfaces [i] = 
1450                       class_getconstant (c, suck_u2(), CONSTANT_Class);
1451                 }
1452
1453         /* load fields */
1454         c -> fieldscount = suck_u2 ();
1455         c -> fields = MNEW (fieldinfo, c -> fieldscount);
1456         for (i=0; i < c -> fieldscount; i++) {
1457                 field_load (&(c->fields[i]), c);
1458                 }
1459
1460         /* load methods */
1461         c -> methodscount = suck_u2 ();
1462         c -> methods = MNEW (methodinfo, c -> methodscount);
1463         for (i=0; i < c -> methodscount; i++) {
1464                 method_load (&(c -> methods [i]), c);
1465                 }
1466
1467 #ifdef STATISTICS
1468         count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1469         count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1470         count_class_infos += sizeof(methodinfo) * c -> methodscount;
1471 #endif
1472
1473         /* load variable-length attribute structures */ 
1474         attribute_load (suck_u2(), c);
1475
1476         /* free memory */
1477         suck_stop ();
1478
1479         /* remove class from list of unloaded classes and 
1480            add to list of unlinked classes                */
1481         list_remove (&unloadedclasses, c);
1482         list_addlast (&unlinkedclasses, c);
1483
1484         return true;
1485 }
1486
1487
1488
1489 /************** interne Funktion: class_highestinterface ***********************
1490
1491         wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
1492         die Interfacetable einer Klasse sein mu"s.
1493
1494 *******************************************************************************/
1495
1496 static s4 class_highestinterface (classinfo *c) 
1497 {
1498         s4 h;
1499         s4 i;
1500         
1501         if ( ! (c->flags & ACC_INTERFACE) ) {
1502                 sprintf (logtext, "Interface-methods count requested for non-interface:  ");
1503         utf_sprint (logtext+strlen(logtext), c->name);
1504         error();
1505         }
1506     
1507     h = c->index;
1508         for (i=0; i<c->interfacescount; i++) {
1509                 s4 h2 = class_highestinterface (c->interfaces[i]);
1510                 if (h2>h) h=h2;
1511                 }
1512         return h;
1513 }
1514
1515
1516 /* class_addinterface **********************************************************
1517
1518         wird von der Funktion class_link ben"otigt, um eine Virtual Function 
1519         Table f"ur ein Interface (und alle weiteren von diesem Interface
1520         implementierten Interfaces) in eine Klasse einzutragen.
1521
1522 *******************************************************************************/        
1523
1524 static void class_addinterface (classinfo *c, classinfo *ic)
1525 {
1526         s4     j, m;
1527         s4     i     = ic->index;
1528         vftbl *vftbl = c->vftbl;
1529         
1530         if (i >= vftbl->interfacetablelength)
1531                 panic ("Inernal error: interfacetable overflow");
1532         if (vftbl->interfacetable[-i])
1533                 return;
1534
1535         if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
1536                 vftbl->interfacevftbllength[i] = 1;
1537                 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1538                 vftbl->interfacetable[-i][0] = NULL;
1539                 }
1540         else {
1541                 vftbl->interfacevftbllength[i] = ic->methodscount;
1542                 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
1543
1544 #ifdef STATISTICS
1545         count_vftbl_len += sizeof(methodptr) *
1546                                  (ic->methodscount + (ic->methodscount == 0));
1547 #endif
1548
1549                 for (j=0; j<ic->methodscount; j++) {
1550                         classinfo *sc = c;
1551                         while (sc) {
1552                                 for (m = 0; m < sc->methodscount; m++) {
1553                                         methodinfo *mi = &(sc->methods[m]);
1554                                         if (method_canoverwrite(mi, &(ic->methods[j]))) {
1555                                                 vftbl->interfacetable[-i][j] = 
1556                                                                           vftbl->table[mi->vftblindex];
1557                                                 goto foundmethod;
1558                                                 }
1559                                         }
1560                                 sc = sc->super;
1561                                 }
1562                          foundmethod: ;
1563                         }
1564                 }
1565
1566         for (j = 0; j < ic->interfacescount; j++) 
1567                 class_addinterface(c, ic->interfaces[j]);
1568 }
1569
1570
1571 /********************** Funktion: class_link ***********************************
1572
1573         versucht, eine Klasse in das System voll zu integrieren (linken). Dazu 
1574         m"ussen sowol die Superklasse, als auch alle implementierten
1575         Interfaces schon gelinkt sein.
1576         Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz 
1577         dieser Klasse, als auch die Virtual Function Tables f"ur normale
1578         Methoden als auch Interface-Methoden.
1579         
1580         Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
1581         der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
1582         eingetragen.
1583         Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
1584
1585         Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
1586                  eine Endlosschleife!!  (Da muss ich mir noch was einfallen lassen)
1587
1588 *******************************************************************************/
1589
1590 static void class_link (classinfo *c)
1591 {
1592         s4 supervftbllength;          /* vftbllegnth of super class               */
1593         s4 vftbllength;               /* vftbllength of current class             */
1594         s4 interfacetablelength;      /* interface table length                   */
1595         classinfo *super = c->super;  /* super class                              */
1596         classinfo *ic, *c2;           /* intermediate class variables             */
1597         vftbl *v;                     /* vftbl of current class                   */
1598         s4 i;                         /* interface/method/field counter           */                     
1599
1600
1601         /*  check if all superclasses are already linked, if not put c at end of
1602             unlinked list and return. Additionally initialize class fields.       */
1603
1604         /*  check interfaces */
1605
1606         for (i = 0; i < c->interfacescount; i++) {
1607                 ic = c->interfaces[i];
1608                 if (!ic->linked) {
1609                         list_remove(&unlinkedclasses, c);
1610                         list_addlast(&unlinkedclasses, c);
1611                         return; 
1612                         }
1613                 }
1614         
1615         /*  check super class */
1616
1617         if (super == NULL) {          /* class java.long.Object */
1618                 c->index = 0;
1619                 c->instancesize = sizeof(java_objectheader);
1620                 
1621                 vftbllength = supervftbllength = 0;
1622
1623                 c->finalizer = NULL;
1624                 }
1625         else {
1626                 if (!super->linked) {
1627                         list_remove(&unlinkedclasses, c);
1628                         list_addlast(&unlinkedclasses, c);
1629                         return; 
1630                         }
1631
1632                 if (c->flags & ACC_INTERFACE)
1633                         c->index = interfaceindex++;
1634                 else
1635                         c->index = super->index + 1;
1636                 
1637                 c->instancesize = super->instancesize;
1638                 
1639                 vftbllength = supervftbllength = super->vftbl->vftbllength;
1640                 
1641                 c->finalizer = super->finalizer;
1642                 }
1643
1644
1645         if (linkverbose) {
1646                 sprintf (logtext, "Linking Class: ");
1647                 utf_sprint (logtext+strlen(logtext), c->name );
1648                 dolog ();
1649                 }
1650
1651         /* compute vftbl length */
1652
1653         for (i = 0; i < c->methodscount; i++) {
1654                 methodinfo *m = &(c->methods[i]);
1655                         
1656                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1657                         classinfo *sc = super;
1658                         while (sc) {
1659                                 int j;
1660                                 for (j = 0; j < sc->methodscount; j++) {
1661                                         if (method_canoverwrite(m, &(sc->methods[j]))) {
1662                                                 m->vftblindex = sc->methods[j].vftblindex;
1663                                                 goto foundvftblindex;
1664                                                 }
1665                                         }
1666                                 sc = sc->super;
1667                                 }
1668                         m->vftblindex = (vftbllength++);
1669 foundvftblindex: ;
1670                         }
1671                 }       
1672         
1673 #ifdef STATISTICS
1674         count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1675 #endif
1676
1677         /* compute interfacetable length */
1678
1679         interfacetablelength = 0;
1680         c2 = c;
1681         while (c2) {
1682                 for (i = 0; i < c2->interfacescount; i++) {
1683                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1684                         if (h > interfacetablelength)
1685                                 interfacetablelength = h;
1686                         }
1687                 c2 = c2->super;
1688                 }
1689
1690         /* allocate virtual function table */
1691
1692         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1693                     (vftbllength - 1) + sizeof(methodptr*) *
1694                     (interfacetablelength - (interfacetablelength > 0)));
1695         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1696                                          (interfacetablelength > 1));
1697         c->header.vftbl = c->vftbl = v;
1698         v->class = c;
1699         v->vftbllength = vftbllength;
1700         v->interfacetablelength = interfacetablelength;
1701
1702         /* copy virtual function table of super class */
1703
1704         for (i = 0; i < supervftbllength; i++) 
1705            v->table[i] = super->vftbl->table[i];
1706         
1707         /* add method stubs into virtual function table */
1708
1709         for (i = 0; i < c->methodscount; i++) {
1710                 methodinfo *m = &(c->methods[i]);
1711                 if (!(m->flags & ACC_STATIC)) {
1712                         v->table[m->vftblindex] = m->stubroutine;
1713                         }
1714                 }
1715
1716         /* compute instance size and offset of each field */
1717         
1718         for (i = 0; i < c->fieldscount; i++) {
1719                 s4 dsize;
1720                 fieldinfo *f = &(c->fields[i]);
1721                 
1722                 if (!(f->flags & ACC_STATIC) ) {
1723                         dsize = desc_typesize (f->descriptor);
1724                         c->instancesize = ALIGN (c->instancesize, dsize);
1725                         f->offset = c->instancesize;
1726                         c->instancesize += dsize;
1727                         }
1728                 }
1729
1730         /* initialize interfacetable and interfacevftbllength */
1731         
1732         v->interfacevftbllength = MNEW (s4, interfacetablelength);
1733
1734 #ifdef STATISTICS
1735         count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1736 #endif
1737
1738         for (i = 0; i < interfacetablelength; i++) {
1739                 v->interfacevftbllength[i] = 0;
1740                 v->interfacetable[-i] = NULL;
1741                 }
1742         
1743         /* add interfaces */
1744         
1745         for (c2 = c; c2 != NULL; c2 = c2->super)
1746                 for (i = 0; i < c2->interfacescount; i++) {
1747                         class_addinterface (c, c2->interfaces[i]);
1748                         }
1749
1750         /* add finalizer method (not for java.lang.Object) */
1751
1752         if (super != NULL) {
1753                 methodinfo *fi;
1754                 static utf *finame = NULL;
1755                 static utf *fidesc = NULL;
1756
1757                 if (finame == NULL)
1758                         finame = utf_finalize;
1759                 if (fidesc == NULL)
1760                         fidesc = utf_fidesc;
1761
1762                 fi = class_findmethod (c, finame, fidesc);
1763                 if (fi != NULL) {
1764                         if (!(fi->flags & ACC_STATIC)) {
1765                                 c->finalizer = fi;
1766                                 }
1767                         }
1768                 }
1769
1770         /* final tasks */
1771
1772         c->linked = true;       
1773
1774         list_remove (&unlinkedclasses, c);
1775         list_addlast (&linkedclasses, c);
1776 }
1777
1778
1779 /******************* Funktion: class_freepool **********************************
1780
1781         Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
1782         wieder frei.
1783
1784 *******************************************************************************/
1785
1786 static void class_freecpool (classinfo *c)
1787 {
1788         u4 idx;
1789         u4 tag;
1790         voidptr info;
1791         
1792         for (idx=0; idx < c->cpcount; idx++) {
1793                 tag = c->cptags[idx];
1794                 info = c->cpinfos[idx];
1795                 
1796                 if (info != NULL) {
1797                         switch (tag) {
1798                         case CONSTANT_Fieldref:
1799                         case CONSTANT_Methodref:
1800                         case CONSTANT_InterfaceMethodref:
1801                                 FREE (info, constant_FMIref);
1802                                 break;
1803                         case CONSTANT_Integer:
1804                                 FREE (info, constant_integer);
1805                                 break;
1806                         case CONSTANT_Float:
1807                                 FREE (info, constant_float);
1808                                 break;
1809                         case CONSTANT_Long:
1810                                 FREE (info, constant_long);
1811                                 break;
1812                         case CONSTANT_Double:
1813                                 FREE (info, constant_double);
1814                                 break;
1815                         case CONSTANT_NameAndType:
1816                                 FREE (info, constant_nameandtype);
1817                                 break;
1818                         case CONSTANT_Arraydescriptor:
1819                                 freearraydescriptor (info);
1820                                 break;
1821                         }
1822                         }
1823                 }
1824
1825         MFREE (c -> cptags,  u1, c -> cpcount);
1826         MFREE (c -> cpinfos, voidptr, c -> cpcount);
1827 }
1828
1829
1830 /*********************** Funktion: class_free **********************************
1831
1832         Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
1833
1834 *******************************************************************************/
1835
1836 static void class_free (classinfo *c)
1837 {
1838         s4 i;
1839         vftbl *v;
1840                 
1841         class_freecpool (c);
1842
1843         MFREE (c->interfaces, classinfo*, c->interfacescount);
1844
1845         for (i = 0; i < c->fieldscount; i++)
1846                 field_free(&(c->fields[i]));
1847         MFREE (c->fields, fieldinfo, c->fieldscount);
1848         
1849         for (i = 0; i < c->methodscount; i++)
1850                 method_free(&(c->methods[i]));
1851         MFREE (c->methods, methodinfo, c->methodscount);
1852
1853         if ((v = c->vftbl) != NULL) {
1854                 for (i = 0; i < v->interfacetablelength; i++) {
1855                         MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1856                         }
1857                 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1858
1859                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1860                     sizeof(methodptr*) * (v->interfacetablelength -
1861                                          (v->interfacetablelength > 0));
1862                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1863                                              (v->interfacetablelength > 1));
1864                 mem_free (v, i);
1865                 }
1866
1867         if (c->innerclasscount)
1868                 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1869
1870         FREE (c, classinfo);
1871 }
1872
1873 /************************* Funktion: class_findfield ***************************
1874         
1875         sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
1876         Namen und Typ.
1877
1878 *******************************************************************************/
1879
1880
1881 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1882 {
1883         s4 i;
1884
1885         for (i = 0; i < c->fieldscount; i++) { 
1886                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
1887                         return &(c->fields[i]);                                                         
1888     }
1889
1890         panic ("Can not find field given in CONSTANT_Fieldref");
1891         return NULL;
1892 }
1893
1894
1895 /************************* Funktion: class_findmethod **************************
1896         
1897         sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1898         Namen und Typ.
1899         Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1900
1901 *******************************************************************************/
1902
1903 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1904 {
1905         s4 i;
1906         for (i = 0; i < c->methodscount; i++) {
1907                 if ((c->methods[i].name == name) && ((desc == NULL) ||
1908                                                    (c->methods[i].descriptor == desc)))
1909                         return &(c->methods[i]);
1910                 }
1911         return NULL;
1912 }
1913
1914 /************************* Funktion: class_findmethod_approx ******************
1915         
1916         sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1917         Namen und Typ.
1918         Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1919         beim Vergleichen des Descriptors wird der R"uckgabewert nicht betrachtet
1920
1921 *******************************************************************************/
1922
1923 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1924 {
1925         s4 i;
1926
1927         for (i = 0; i < c->methodscount; i++) 
1928                 if (c->methods[i].name == name) {
1929                         utf *meth_descr = c->methods[i].descriptor;
1930                         
1931                         if (desc == NULL) 
1932                                 /* ignore type */
1933                                 return &(c->methods[i]);
1934
1935                         if (desc->blength <= meth_descr->blength) {
1936                                            /* current position in utf text   */
1937                                            char *desc_utf_ptr = desc->text;      
1938                                            char *meth_utf_ptr = meth_descr->text;                                         
1939                                            /* points behind utf strings */
1940                                            char *desc_end = utf_end(desc);         
1941                                            char *meth_end = utf_end(meth_descr);   
1942                                            char ch;
1943
1944                                            /* compare argument types */
1945                                            while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1946
1947                                                    if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1948                                                            break; /* no match */
1949
1950                                                    if (ch==')')
1951                                                            return &(c->methods[i]);   /* all parameter types equal */
1952                                            }
1953                         }
1954                 }
1955
1956         return NULL;
1957 }
1958
1959 /***************** Funktion: class_resolvemethod_approx ***********************
1960         
1961         sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1962         (ohne Beachtung des R"uckgabewertes)
1963
1964 *******************************************************************************/
1965
1966 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1967 {
1968         while (c) {
1969                 /* search for method (ignore returntype) */
1970                 methodinfo *m = class_findmethod_approx (c, name, desc);
1971                 /* method found */
1972                 if (m) return m;
1973                 /* search superclass */
1974                 c = c->super;
1975                 }
1976         return NULL;
1977 }
1978
1979
1980 /************************* Funktion: class_resolvemethod ***********************
1981         
1982         sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1983
1984 *******************************************************************************/
1985
1986
1987 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
1988 {
1989         while (c) {
1990                 methodinfo *m = class_findmethod (c, name, desc);
1991                 if (m) return m;
1992                 /* search superclass */
1993                 c = c->super;
1994                 }
1995         return NULL;
1996 }
1997         
1998
1999
2000 /************************* Funktion: class_issubclass **************************
2001
2002         "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.            
2003         
2004 *******************************************************************************/
2005
2006 bool class_issubclass (classinfo *sub, classinfo *super)
2007 {
2008         for (;;) {
2009                 if (!sub) return false;
2010                 if (sub==super) return true;
2011                 sub = sub -> super;
2012                 }
2013 }
2014
2015
2016
2017 /****************** Initialisierungsfunktion f"ur eine Klasse ******************
2018
2019         In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
2020         Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
2021         Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
2022         wird.
2023
2024 *******************************************************************************/
2025
2026 #ifdef USE_THREADS
2027 extern int blockInts;
2028 #endif
2029
2030 void class_init (classinfo *c)
2031 {
2032         methodinfo *m;
2033         java_objectheader *exceptionptr;
2034         s4 i;
2035         int b;
2036
2037         if (!makeinitializations)
2038                 return;
2039         if (c->initialized)
2040                 return;
2041         c -> initialized = true;
2042         
2043 #ifdef STATISTICS
2044         count_class_inits++;
2045 #endif
2046
2047         if (c->super)
2048                 class_init (c->super);
2049         for (i=0; i < c->interfacescount; i++)
2050                 class_init(c->interfaces[i]);
2051
2052         m = class_findmethod (c, utf_clinit, utf_fidesc);
2053         if (!m) {
2054                 if (initverbose) {
2055                         sprintf (logtext, "Class ");
2056                         utf_sprint (logtext+strlen(logtext), c->name);
2057                         sprintf (logtext+strlen(logtext), " has no initializer");       
2058                         dolog ();
2059                         }
2060                 return;
2061                 }
2062                 
2063         if (! (m->flags & ACC_STATIC))
2064                 panic ("Class initializer is not static!");
2065         
2066         if (initverbose) {
2067                 sprintf (logtext, "Starting initializer for class: ");
2068                 utf_sprint (logtext+strlen(logtext), c->name);
2069                 dolog ();
2070         }
2071
2072 #ifdef USE_THREADS
2073         b = blockInts;
2074         blockInts = 0;
2075 #endif
2076
2077         exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2078
2079 #ifdef USE_THREADS
2080         assert(blockInts == 0);
2081         blockInts = b;
2082 #endif
2083
2084         if (exceptionptr) {     
2085                 printf ("#### Initializer of ");
2086                 utf_display (c->name);
2087                 printf (" has thrown: ");
2088                 utf_display (exceptionptr->vftbl->class->name);
2089                 printf ("\n");
2090                 fflush (stdout);
2091                 }
2092
2093         if (initverbose) {
2094                 sprintf (logtext, "Finished initializer for class: ");
2095                 utf_sprint (logtext+strlen(logtext), c->name);
2096                 dolog ();
2097         }
2098
2099         if (c->name == utf_systemclass) {
2100                 /* class java.lang.System requires explicit initialization */
2101                 
2102                 if (initverbose)
2103                         printf ("#### Initializing class System");
2104
2105                 /* find initializing method */     
2106                 m = class_findmethod (c, 
2107                                         utf_initsystemclass,
2108                                         utf_fidesc);
2109
2110                 if (!m) {
2111                         /* no method found */
2112                         log("initializeSystemClass failed");
2113                         return;
2114                 }
2115
2116                 #ifdef USE_THREADS
2117                         b = blockInts;
2118                         blockInts = 0;
2119                 #endif
2120
2121                 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2122
2123                 #ifdef USE_THREADS
2124                         assert(blockInts == 0);
2125                         blockInts = b;
2126                 #endif
2127
2128                 if (exceptionptr) {                     
2129                         printf ("#### initializeSystemClass has thrown: ");
2130                         utf_display (exceptionptr->vftbl->class->name);
2131                         printf ("\n");
2132                         fflush (stdout);                  
2133                 }
2134         }
2135 }
2136
2137
2138
2139
2140 /********* Funktion: class_showconstantpool   (nur f"ur Debug-Zwecke) *********/
2141
2142 void class_showconstantpool (classinfo *c) 
2143 {
2144         u4 i;
2145         voidptr e;
2146
2147         printf ("---- dump of constant pool ----\n");
2148
2149         for (i=0; i<c->cpcount; i++) {
2150                 printf ("#%d:  ", (int) i);
2151                 
2152                 e = c -> cpinfos [i];
2153                 if (e) {
2154                         
2155                         switch (c -> cptags [i]) {
2156                                 case CONSTANT_Class:
2157                                         printf ("Classreference -> ");
2158                                         utf_display ( ((classinfo*)e) -> name );
2159                                         break;
2160                                 
2161                                 case CONSTANT_Fieldref:
2162                                         printf ("Fieldref -> "); goto displayFMI;
2163                                 case CONSTANT_Methodref:
2164                                         printf ("Methodref -> "); goto displayFMI;
2165                                 case CONSTANT_InterfaceMethodref:
2166                                         printf ("InterfaceMethod -> "); goto displayFMI;
2167                                   displayFMI:
2168                                         {
2169                                         constant_FMIref *fmi = e;
2170                                         utf_display ( fmi->class->name );
2171                                         printf (".");
2172                                         utf_display ( fmi->name);
2173                                         printf (" ");
2174                                         utf_display ( fmi->descriptor );
2175                                     }
2176                                         break;
2177
2178                                 case CONSTANT_String:
2179                                         printf ("String -> ");
2180                                         utf_display (e);
2181                                         break;
2182                                 case CONSTANT_Integer:
2183                                         printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2184                                         break;
2185                                 case CONSTANT_Float:
2186                                         printf ("Float -> %f", ((constant_float*)e) -> value);
2187                                         break;
2188                                 case CONSTANT_Double:
2189                                         printf ("Double -> %f", ((constant_double*)e) -> value);
2190                                         break;
2191                                 case CONSTANT_Long:
2192                                         {
2193                                         u8 v = ((constant_long*)e) -> value;
2194 #if U8_AVAILABLE
2195                                         printf ("Long -> %ld", (long int) v);
2196 #else
2197                                         printf ("Long -> HI: %ld, LO: %ld\n", 
2198                                             (long int) v.high, (long int) v.low);
2199 #endif 
2200                                         }
2201                                         break;
2202                                 case CONSTANT_NameAndType:
2203                                         { constant_nameandtype *cnt = e;
2204                                           printf ("NameAndType: ");
2205                                           utf_display (cnt->name);
2206                                           printf (" ");
2207                                           utf_display (cnt->descriptor);
2208                                         }
2209                                         break;
2210                                 case CONSTANT_Utf8:
2211                                         printf ("Utf8 -> ");
2212                                         utf_display (e);
2213                                         break;
2214                                 case CONSTANT_Arraydescriptor:  {
2215                                         printf ("Arraydescriptor: ");
2216                                         displayarraydescriptor (e);
2217                                         }
2218                                         break;
2219                                 default: 
2220                                         panic ("Invalid type of ConstantPool-Entry");
2221                                 }
2222                                 
2223                         }
2224
2225                 printf ("\n");
2226                 }
2227         
2228 }
2229
2230
2231
2232 /********** Funktion: class_showmethods   (nur f"ur Debug-Zwecke) *************/
2233
2234 void class_showmethods (classinfo *c)
2235 {
2236         s4 i;
2237         
2238         printf ("--------- Fields and Methods ----------------\n");
2239         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
2240
2241         printf ("This: "); utf_display (c->name); printf ("\n");
2242         if (c->super) {
2243                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2244                 }
2245         printf ("Index: %d\n", c->index);
2246         
2247         printf ("interfaces:\n");       
2248         for (i=0; i < c-> interfacescount; i++) {
2249                 printf ("   ");
2250                 utf_display (c -> interfaces[i] -> name);
2251                 printf (" (%d)\n", c->interfaces[i] -> index);
2252                 }
2253
2254         printf ("fields:\n");           
2255         for (i=0; i < c -> fieldscount; i++) {
2256                 field_display (&(c -> fields[i]));
2257                 }
2258
2259         printf ("methods:\n");
2260         for (i=0; i < c -> methodscount; i++) {
2261                 methodinfo *m = &(c->methods[i]);
2262                 if ( !(m->flags & ACC_STATIC)) 
2263                         printf ("vftblindex: %d   ", m->vftblindex);
2264
2265                 method_display ( m );
2266
2267                 }
2268
2269         printf ("Virtual function table:\n");
2270         for (i=0; i<c->vftbl->vftbllength; i++) {
2271                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
2272                 }
2273
2274 }
2275
2276
2277
2278 /******************************************************************************/
2279 /******************* Funktionen fuer den Class-loader generell ****************/
2280 /******************************************************************************/
2281
2282 static int loader_inited = 0;
2283
2284 /********************* Funktion: loader_load ***********************************
2285
2286         l"adt und linkt die ge"unschte Klasse und alle davon 
2287         referenzierten Klassen und Interfaces
2288         Return: Einen Zeiger auf diese Klasse
2289
2290 *******************************************************************************/
2291
2292 classinfo *loader_load (utf *topname)
2293 {
2294         classinfo *top;
2295         classinfo *c;
2296         long int starttime=0,stoptime=0;
2297         
2298         intsDisable();                           /* schani */
2299
2300         if (getloadingtime)
2301                 starttime = getcputime();
2302
2303         top = class_new (topname);
2304
2305         /* load classes */
2306         while ( (c = list_first(&unloadedclasses)) ) {
2307                 if (!class_load (c)) {
2308                         list_remove (&unloadedclasses, c);
2309                         top=NULL;
2310                     }
2311         }
2312
2313         /* link classes */
2314         while ( (c = list_first(&unlinkedclasses)) ) {
2315                 class_link (c);
2316                 }
2317
2318         if (loader_inited)
2319                 loader_compute_subclasses();
2320
2321         /* measure time */
2322         if (getloadingtime) {
2323                 stoptime = getcputime();
2324                 loadingtime += (stoptime-starttime);
2325                 }
2326
2327         intsRestore();                          /* schani */
2328
2329         return top; 
2330 }
2331
2332
2333 /**************** function: create_primitive_classes ***************************
2334
2335         create classes representing primitive types 
2336
2337 ********************************************************************************/
2338
2339
2340 void create_primitive_classes()
2341 {  
2342         int i;
2343
2344         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2345                 /* create primitive class */
2346                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2347                 
2348                 /* prevent loader from loading primitive class */
2349                 list_remove (&unloadedclasses, c);
2350                 /* add to unlinked classes */
2351                 list_addlast (&unlinkedclasses, c);             
2352                 c -> super = class_java_lang_Object;
2353                 class_link (c);
2354
2355                 primitivetype_table[i].class_primitive = c;
2356
2357                 /* create class for wrapping the primitive type */
2358                 primitivetype_table[i].class_wrap =
2359                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
2360         }
2361 }
2362
2363 /***************** function: create_array_class ********************************
2364
2365         create class representing an array
2366
2367 ********************************************************************************/
2368
2369
2370 classinfo *create_array_class(utf *u)
2371 {  
2372         classinfo *c = class_new (u);
2373         /* prevent loader from loading the array class */
2374         list_remove (&unloadedclasses, c);
2375         /* add to unlinked classes */
2376         list_addlast (&unlinkedclasses, c);
2377         c -> super = class_java_lang_Object;
2378         class_link(c);
2379
2380         return c;
2381 }
2382
2383 /********************** Funktion: loader_init **********************************
2384
2385         Initialisiert alle Listen und l"adt alle Klassen, die vom System
2386         und vom Compiler direkt ben"otigt werden.
2387
2388 *******************************************************************************/
2389  
2390 void loader_init ()
2391 {
2392         utf *string_class;
2393         interfaceindex = 0;
2394         
2395         list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2396         list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2397         list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2398
2399         /* create utf-symbols for pointer comparison of frequently used strings */
2400         utf_innerclasses    = utf_new_char("InnerClasses");
2401         utf_constantvalue   = utf_new_char("ConstantValue");
2402         utf_code                = utf_new_char("Code");
2403         utf_finalize        = utf_new_char("finalize");
2404         utf_fidesc              = utf_new_char("()V");
2405         utf_clinit              = utf_new_char("<clinit>");
2406         utf_initsystemclass = utf_new_char("initializeSystemClass");
2407         utf_systemclass     = utf_new_char("java/lang/System");
2408
2409         /* create class for arrays */
2410         class_array = class_new ( utf_new_char ("The_Array_Class") );
2411         list_remove (&unloadedclasses, class_array);
2412
2413         /* create class for strings, load it after class Object was loaded */
2414         string_class = utf_new_char ("java/lang/String");
2415         class_java_lang_String = class_new(string_class);
2416         list_remove (&unloadedclasses, class_java_lang_String);
2417
2418         class_java_lang_Object = 
2419                 loader_load ( utf_new_char ("java/lang/Object") );
2420
2421         list_addlast(&unloadedclasses, class_java_lang_String);
2422
2423         class_java_lang_String = 
2424                 loader_load ( string_class );
2425         class_java_lang_ClassCastException = 
2426                 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2427         class_java_lang_NullPointerException = 
2428                 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2429         class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( 
2430              utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2431         class_java_lang_NegativeArraySizeException = loader_load ( 
2432              utf_new_char ("java/lang/NegativeArraySizeException") );
2433         class_java_lang_OutOfMemoryError = loader_load ( 
2434              utf_new_char ("java/lang/OutOfMemoryError") );
2435         class_java_lang_ArrayStoreException =
2436                 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2437         class_java_lang_ArithmeticException = 
2438                 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2439         class_java_lang_ThreadDeath =                             /* schani */
2440                 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2441
2442         /* link class for arrays */
2443         list_addlast (&unlinkedclasses, class_array);
2444         class_array -> super = class_java_lang_Object;
2445         class_link (class_array);
2446
2447         /* correct vftbl-entries (retarded loading of class java/lang/String) */
2448         stringtable_update(); 
2449
2450         /* create classes representing primitive types */
2451         create_primitive_classes();
2452                 
2453         proto_java_lang_ClassCastException = 
2454                 builtin_new(class_java_lang_ClassCastException);
2455         heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2456
2457         proto_java_lang_NullPointerException = 
2458                 builtin_new(class_java_lang_NullPointerException);
2459         heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2460
2461         proto_java_lang_ArrayIndexOutOfBoundsException = 
2462                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2463         heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2464
2465         proto_java_lang_NegativeArraySizeException = 
2466                 builtin_new(class_java_lang_NegativeArraySizeException);
2467         heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2468
2469         proto_java_lang_OutOfMemoryError = 
2470                 builtin_new(class_java_lang_OutOfMemoryError);
2471         heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2472
2473         proto_java_lang_ArithmeticException = 
2474                 builtin_new(class_java_lang_ArithmeticException);
2475         heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2476
2477         proto_java_lang_ArrayStoreException = 
2478                 builtin_new(class_java_lang_ArrayStoreException);
2479         heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2480
2481         proto_java_lang_ThreadDeath =                             /* schani */
2482                 builtin_new(class_java_lang_ThreadDeath);
2483         heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2484
2485         loader_inited = 1;
2486 }
2487
2488
2489
2490
2491 /********************* Funktion: loader_initclasses ****************************
2492
2493         initialisiert alle geladenen aber noch nicht initialisierten Klassen
2494
2495 *******************************************************************************/
2496
2497 void loader_initclasses ()
2498 {
2499         classinfo *c;
2500         
2501         intsDisable();                     /* schani */
2502
2503         if (makeinitializations) {
2504                 c = list_first (&linkedclasses);
2505                 while (c) {
2506                         class_init (c);
2507                         c = list_next (&linkedclasses, c);
2508                         }
2509                 }
2510
2511         intsRestore();                      /* schani */
2512 }
2513
2514 static s4 classvalue;
2515
2516 static void loader_compute_class_values (classinfo *c)
2517 {
2518         classinfo *subs;
2519
2520         c->vftbl->baseval = ++classvalue;
2521         subs = c->sub;
2522         while (subs != NULL) {
2523                 loader_compute_class_values(subs);
2524                 subs = subs->nextsub;
2525                 }
2526         c->vftbl->diffval = classvalue - c->vftbl->baseval;
2527 /*
2528         {
2529         int i;
2530         for (i = 0; i < c->index; i++)
2531                 printf(" ");
2532         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
2533         utf_display(c->name);
2534         printf("\n");
2535         }
2536 */
2537 }
2538
2539
2540 void loader_compute_subclasses ()
2541 {
2542         classinfo *c;
2543         
2544         intsDisable();                     /* schani */
2545
2546         c = list_first (&linkedclasses);
2547         while (c) {
2548                 if (!(c->flags & ACC_INTERFACE)) {
2549                         c->nextsub = 0;
2550                         c->sub = 0;
2551                         }
2552                 c = list_next (&linkedclasses, c);
2553                 }
2554
2555         c = list_first (&linkedclasses);
2556         while (c) {
2557                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2558                         c->nextsub = c->super->sub;
2559                         c->super->sub = c;
2560                         }
2561                 c = list_next (&linkedclasses, c);
2562                 }
2563
2564         classvalue = 0;
2565         loader_compute_class_values(class_java_lang_Object);
2566
2567         intsRestore();                      /* schani */
2568 }
2569
2570
2571
2572 /******************** function classloader_buffer ******************************
2573  
2574     sets buffer for reading classdata
2575
2576 *******************************************************************************/
2577
2578 void classload_buffer(u1 *buf, int len)
2579 {
2580         classbuffer        =  buf;
2581         classbuffer_size   =  len;
2582         classbuf_pos       =  buf - 1;
2583 }
2584
2585
2586 /******************** Funktion: loader_close ***********************************
2587
2588         gibt alle Resourcen wieder frei
2589         
2590 *******************************************************************************/
2591
2592 void loader_close ()
2593 {
2594         classinfo *c;
2595
2596         while ( (c=list_first(&unloadedclasses)) ) {
2597                 list_remove (&unloadedclasses,c);
2598                 class_free (c);
2599                 }
2600         while ( (c=list_first(&unlinkedclasses)) ) {
2601                 list_remove (&unlinkedclasses,c);
2602                 class_free (c);
2603                 }
2604         while ( (c=list_first(&linkedclasses)) ) {
2605                 list_remove (&linkedclasses,c);
2606                 class_free (c);
2607                 }
2608 }
2609
2610
2611 /*
2612  * These are local overrides for various environment variables in Emacs.
2613  * Please do not remove this and leave it at the end of the file, where
2614  * Emacs will automagically detect them.
2615  * ---------------------------------------------------------------------
2616  * Local variables:
2617  * mode: c
2618  * indent-tabs-mode: t
2619  * c-basic-offset: 4
2620  * tab-width: 4
2621  * End:
2622  */
2623