These should not reside in cvs.
[cacao.git] / loader.c
1 /* loader.c - class loader functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28    Changes: Andreas Krall
29             Roman Obermaiser
30             Mark Probst
31                         Edwin Steiner
32
33    $Id: loader.c 972 2004-03-24 22:48:01Z edwin $
34
35 */
36
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include <assert.h>
41 #include <sys/stat.h>
42 #include "global.h"
43 #include "loader.h"
44 #include "main.h"
45 #include "native.h"
46 #include "tables.h"
47 #include "builtin.h"
48 #include "jit.h"
49 #include "asmpart.h"
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
54 #include "nat/java_lang_Throwable.h"
55
56 #ifdef USE_ZLIB
57 #include "unzip.h"
58 #endif
59
60 #undef JOWENN_DEBUG
61 #undef JOWENN_DEBUG1
62 #undef JOWENN_DEBUG2
63
64 /* global variables ***********************************************************/
65
66 int count_class_infos = 0;      /* variables for measurements                 */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
74
75 static s4 interfaceindex;       /* sequential numbering of interfaces         */
76 static s4 classvalue;
77
78 list unloadedclasses;       /* list of all referenced but not loaded classes  */
79 list unlinkedclasses;       /* list of all loaded but not linked classes      */
80 list linkedclasses;         /* list of all completely linked classes          */
81
82
83 /* utf-symbols for pointer comparison of frequently used strings */
84
85 static utf *utf_innerclasses;           /* InnerClasses            */
86 static utf *utf_constantvalue;          /* ConstantValue           */
87 static utf *utf_code;                       /* Code                    */
88 static utf *utf_exceptions;             /* Exceptions                    */
89 static utf *utf_linenumbertable;                /* LineNumberTable                    */
90 static utf *utf_sourcefile;             /*SourceFile*/
91 static utf *utf_finalize;                   /* finalize                */
92 static utf *utf_fidesc;                     /* ()V changed             */
93 static utf *utf_init;                   /* <init>                  */
94 static utf *utf_clinit;                     /* <clinit>                */
95 static utf *utf_initsystemclass;        /* initializeSystemClass   */
96 static utf *utf_systemclass;            /* java/lang/System        */
97 static utf *utf_vmclassloader;      /* java/lang/VMClassLoader */
98 static utf *utf_vmclass;            /* java/lang/VMClassLoader */
99 static utf *utf_initialize;
100 static utf *utf_initializedesc;
101 static utf *utf_java_lang_Object;   /* java/lang/Object        */
102
103
104
105
106 utf* clinit_desc(){
107         return utf_fidesc;
108 }
109 utf* clinit_name(){
110         return utf_clinit;
111 }
112
113
114 /* important system classes ***************************************************/
115
116 classinfo *class_java_lang_Object;
117 classinfo *class_java_lang_String;
118
119 classinfo *class_java_lang_Throwable;
120 classinfo *class_java_lang_Cloneable;
121 classinfo *class_java_io_Serializable;
122
123 /* Pseudo classes for the typechecker */
124 classinfo *pseudo_class_Arraystub = NULL;
125 classinfo *pseudo_class_Null = NULL;
126 classinfo *pseudo_class_New = NULL;
127 vftbl *pseudo_class_Arraystub_vftbl = NULL;
128
129 /* stefan */
130 /* These are made static so they cannot be used for throwing in native */
131 /* functions.                                                          */
132 static classinfo *class_java_lang_ClassCastException;
133 static classinfo *class_java_lang_NullPointerException;
134 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
135 static classinfo *class_java_lang_NegativeArraySizeException;
136 static classinfo *class_java_lang_OutOfMemoryError;
137 static classinfo *class_java_lang_ArithmeticException;
138 static classinfo *class_java_lang_ArrayStoreException;
139 static classinfo *class_java_lang_ThreadDeath;
140
141 utf *array_packagename = NULL;
142
143 static int loader_inited = 0;
144
145
146 /********************************************************************
147    list of classpath entries (either filesystem directories or 
148    ZIP/JAR archives
149 ********************************************************************/
150 static classpath_info *classpath_entries=0;
151
152
153 /******************************************************************************
154
155    structure for primitive classes: contains the class for wrapping the 
156    primitive type, the primitive class, the name of the class for wrapping, 
157    the one character type signature and the name of the primitive class
158  
159  ******************************************************************************/
160
161 /* CAUTION: Don't change the order of the types. This table is indexed
162  * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
163  */
164 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { 
165         { NULL, NULL, "java/lang/Integer",   'I', "int"     , "[I", NULL, NULL },
166         { NULL, NULL, "java/lang/Long",      'J', "long"    , "[J", NULL, NULL },
167         { NULL, NULL, "java/lang/Float",     'F', "float"   , "[F", NULL, NULL },
168         { NULL, NULL, "java/lang/Double",    'D', "double"  , "[D", NULL, NULL },
169         { NULL, NULL, "java/lang/Byte",      'B', "byte"    , "[B", NULL, NULL },
170         { NULL, NULL, "java/lang/Character", 'C', "char"    , "[C", NULL, NULL },
171         { NULL, NULL, "java/lang/Short",     'S', "short"   , "[S", NULL, NULL },
172         { NULL, NULL, "java/lang/Boolean",   'Z', "boolean" , "[Z", NULL, NULL },
173         { NULL, NULL, "java/lang/Void",      'V', "void"    , NULL, NULL, NULL }
174 };
175
176
177 /* instances of important system classes **************************************/
178
179 java_objectheader *proto_java_lang_ClassCastException;
180 java_objectheader *proto_java_lang_NullPointerException;
181 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
182 java_objectheader *proto_java_lang_NegativeArraySizeException;
183 java_objectheader *proto_java_lang_OutOfMemoryError;
184 java_objectheader *proto_java_lang_ArithmeticException;
185 java_objectheader *proto_java_lang_ArrayStoreException;
186 java_objectheader *proto_java_lang_ThreadDeath;
187
188 /************* functions for reading classdata *********************************
189
190     getting classdata in blocks of variable size
191     (8,16,32,64-bit integer or float)
192
193 *******************************************************************************/
194
195 static char *classpath    = "";     /* searchpath for classfiles              */
196 static u1 *classbuffer    = NULL;   /* pointer to buffer with classfile-data  */
197 static u1 *classbuf_pos;            /* current position in classfile buffer   */
198 static int classbuffer_size;        /* size of classfile-data                 */
199
200 /* assert that at least <len> bytes are left to read */
201 /* <len> is limited to the range of non-negative s4 values */
202 #define ASSERT_LEFT(len)                                                                                                \
203         do {if ( ((s4)(len)) < 0                                                                                        \
204                          || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
205                         panic("Unexpected end of classfile"); } while(0)
206
207 /* transfer block of classfile data into a buffer */
208
209 #define suck_nbytes(buffer,len)                                         \
210         do {ASSERT_LEFT(len);                                                   \
211                 memcpy(buffer,classbuf_pos+1,len);                      \
212                 classbuf_pos+=len;} while (0)
213
214 /* skip block of classfile data */
215
216 #define skip_nbytes(len)                                                \
217         do {ASSERT_LEFT(len);                                           \
218                 classbuf_pos+=len;} while(0)
219
220
221 inline u1 suck_u1()
222 {
223         ASSERT_LEFT(1);
224         return *++classbuf_pos;
225 }
226
227
228 inline u2 suck_u2()
229 {
230         u1 a = suck_u1();
231         u1 b = suck_u1();
232         return ((u2) a << 8) + (u2) b;
233 }
234
235
236 inline u4 suck_u4()
237 {
238         u1 a = suck_u1();
239         u1 b = suck_u1();
240         u1 c = suck_u1();
241         u1 d = suck_u1();
242         return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
243 }
244
245 #define suck_s8() (s8) suck_u8()
246 #define suck_s2() (s2) suck_u2()
247 #define suck_s4() (s4) suck_u4()
248 #define suck_s1() (s1) suck_u1()
249
250
251 /* get u8 from classfile data */
252 static u8 suck_u8()
253 {
254 #if U8_AVAILABLE
255         u8 lo, hi;
256         hi = suck_u4();
257         lo = suck_u4();
258         return (hi << 32) + lo;
259 #else
260         u8 v;
261         v.high = suck_u4();
262         v.low = suck_u4();
263         return v;
264 #endif
265 }
266
267
268 /* get float from classfile data */
269 static float suck_float()
270 {
271         float f;
272
273 #if !WORDS_BIGENDIAN 
274                 u1 buffer[4];
275                 u2 i;
276                 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
277                 memcpy((u1*) (&f), buffer, 4);
278 #else 
279                 suck_nbytes((u1*) (&f), 4);
280 #endif
281
282         PANICIF (sizeof(float) != 4, "Incompatible float-format");
283         
284         return f;
285 }
286
287
288 /* get double from classfile data */
289 static double suck_double()
290 {
291         double d;
292
293 #if !WORDS_BIGENDIAN 
294                 u1 buffer[8];
295                 u2 i;   
296                 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
297                 memcpy((u1*) (&d), buffer, 8);
298 #else 
299                 suck_nbytes((u1*) (&d), 8);
300 #endif
301
302         PANICIF (sizeof(double) != 8, "Incompatible double-format" );
303         
304         return d;
305 }
306
307
308 /************************** function suck_init *********************************
309
310         called once at startup, sets the searchpath for the classfiles
311
312 *******************************************************************************/
313
314 void suck_init(char *cpath)
315 {
316         char *filename=0;
317         char *start;
318         char *end;
319         int isZip;
320         int filenamelen;
321         union classpath_info *tmp;
322         union classpath_info *insertAfter=0;
323         if (!cpath) return;
324         classpath   = cpath;
325         classbuffer = NULL;
326         
327         if (classpath_entries) panic("suck_init should be called only once");
328         for(start=classpath;(*start)!='\0';) {
329                 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
330                 if (start!=end) {
331                         isZip=0;
332                         filenamelen=(end-start);
333                         if  (filenamelen>3) {
334                                 if ( 
335                                         (
336                                                 (
337                                                         ((*(end-1))=='p') ||
338                                                         ((*(end-1))=='P')
339                                                 ) &&
340                                                 (
341                                                         ((*(end-2))=='i') ||
342                                                         ((*(end-2))=='I')
343                                                 ) &&
344                                                 (
345                                                         ((*(end-3))=='z') ||
346                                                         ((*(end-3))=='Z')
347                                                 )
348                                         ) ||
349                                         (
350                                                 (
351                                                         ((*(end-1))=='r') ||
352                                                         ((*(end-1))=='R')
353                                                 ) &&
354                                                 (
355                                                         ((*(end-2))=='a') ||
356                                                         ((*(end-2))=='A')
357                                                 ) &&
358                                                 (
359                                                         ((*(end-3))=='j') ||
360                                                         ((*(end-3))=='J')
361                                                 )
362                                         )
363                                 ) isZip=1;
364 #if 0
365                                 if ( 
366                                         (  (  (*(end - 1)) == 'p') || ( (*(end - 1))  == 'P')) &&
367                                      (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
368                                          (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z'))) 
369                                 ) {
370                                         isZip=1;
371                                 } else  if ( (( (*(end - 1)) == 'r') || ( (*(end - 1))  == 'R')) &&
372                                      ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
373                                          (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
374                                         isZip=1;
375                                 }
376 #endif
377                         }
378                         if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init"); 
379                         if (!filename)
380                                 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
381                         strncpy(filename,start,filenamelen);
382                         filename[filenamelen+1]='\0';
383                         tmp=0;
384
385                         if (isZip) {
386 #ifdef USE_ZLIB
387                                 unzFile uf=unzOpen(filename);
388                                 if (uf) {
389                                         tmp=(union classpath_info*)malloc(sizeof(classpath_info));
390                                         tmp->archive.type=CLASSPATH_ARCHIVE;
391                                         tmp->archive.uf=uf;
392                                         tmp->archive.next=0;
393                                         filename=0;
394                                 }
395 #else
396                                 panic("Zip/JAR not supported");
397 #endif
398                                 
399                         } else {
400                                 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
401                                 tmp->filepath.type=CLASSPATH_PATH;
402                                 tmp->filepath.next=0;
403                                 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
404                                         filename[filenamelen]='/';
405                                         filename[filenamelen+1]='\0';
406                                         filenamelen++;
407                                 }
408                         
409                                 tmp->filepath.filename=filename;
410                                 tmp->filepath.pathlen=filenamelen;                              
411                                 filename=0;
412                         }
413
414                 if (tmp) {
415                         if (insertAfter) {
416                                 insertAfter->filepath.next=tmp;
417                         } else {
418                                 classpath_entries=tmp;  
419                         }
420                         insertAfter=tmp;
421                 }
422         }
423                 if ((*end)==':') start=end+1; else start=end;
424         
425         
426         if (filename!=0) free(filename);
427 }
428
429 }
430
431 /************************** function suck_start ********************************
432
433         returns true if classbuffer is already loaded or a file for the
434         specified class has succussfully been read in. All directories of
435         the searchpath are used to find the classfile (<classname>.class).
436         Returns false if no classfile is found and writes an error message. 
437         
438 *******************************************************************************/
439
440 bool suck_start(utf *classname)
441 {
442         classpath_info *currPos;
443         char *utf_ptr;
444         char c;
445         char filename[CLASSPATH_MAXFILENAME+10];  /* room for '.class'                      */  
446         int  filenamelen=0;
447         FILE *classfile;
448         int  err;
449         struct stat buffer;
450
451         if (classbuffer) return true; /* classbuffer is already valid */
452
453         utf_ptr = classname->text;
454         while (utf_ptr < utf_end(classname)) {
455                 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
456                 c = *utf_ptr++;
457                 if ((c <= ' ' || c > 'z') && (c != '/'))     /* invalid character */
458                         c = '?';
459                 filename[filenamelen++] = c;
460         }
461         strcpy(filename + filenamelen, ".class");
462         filenamelen+=6;
463         for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
464 #ifdef USE_ZLIB
465                 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
466                         if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
467                                 unz_file_info file_info;
468                                 /*log_text("Class found in zip file");*/
469                                 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
470                                                 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
471                                         if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
472                                                 classbuffer_size = file_info.uncompressed_size;                         
473                                                 classbuffer      = MNEW(u1, classbuffer_size);
474                                                 classbuf_pos     = classbuffer - 1;
475                                                 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
476                                                 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
477                                                         unzCloseCurrentFile(currPos->archive.uf);
478                                                         return true;
479                                                 } else {
480                                                         MFREE(classbuffer, u1, classbuffer_size);
481                                                         log_text("Error while unzipping");
482                                                 }
483                                         } else log_text("Error while opening file in archive");
484                                 } else log_text("Error while retrieving fileinfo");
485                         }
486                         unzCloseCurrentFile(currPos->archive.uf);
487
488                 } else {
489 #endif
490                         if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
491                         strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
492                         classfile = fopen(currPos->filepath.filename, "r");
493                         if (classfile) {                                       /* file exists */
494
495                                 /* determine size of classfile */
496
497                                 /* dolog("File: %s",filename); */
498
499                                 err = stat(currPos->filepath.filename, &buffer);
500
501                                 if (!err) {                                /* read classfile data */                            
502                                         classbuffer_size = buffer.st_size;                              
503                                         classbuffer      = MNEW(u1, classbuffer_size);
504                                         classbuf_pos     = classbuffer - 1;
505                                         fread(classbuffer, 1, classbuffer_size, classfile);
506                                         fclose(classfile);
507                                         return true;
508                                 }
509                         }
510 #ifdef USE_ZLIB
511                 }
512 #endif
513         }
514
515         if (verbose) {
516                 dolog("Warning: Can not open class file '%s'", filename);
517         }
518
519         return false;
520
521 }
522
523 /************************** function suck_stop *********************************
524
525         frees memory for buffer with classfile data.
526         Caution: this function may only be called if buffer has been allocated
527                  by suck_start with reading a file
528         
529 *******************************************************************************/
530
531 void suck_stop()
532 {
533         /* determine amount of classdata not retrieved by suck-operations         */
534
535         int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
536
537         if (classdata_left > 0) {
538                 /* surplus */           
539                 dolog("There are %d extra bytes at end of classfile",
540                                 classdata_left);
541                 /* The JVM spec disallows extra bytes. */
542                 panic("Extra bytes at end of classfile");
543         }
544
545         /* free memory */
546
547         MFREE(classbuffer, u1, classbuffer_size);
548         classbuffer = NULL;
549 }
550
551
552 /******************************************************************************/
553 /******************* Some support functions ***********************************/
554 /******************************************************************************/
555
556 void fprintflags (FILE *fp, u2 f)
557 {
558    if ( f & ACC_PUBLIC )       fprintf (fp," PUBLIC");
559    if ( f & ACC_PRIVATE )      fprintf (fp," PRIVATE");
560    if ( f & ACC_PROTECTED )    fprintf (fp," PROTECTED");
561    if ( f & ACC_STATIC )       fprintf (fp," STATIC");
562    if ( f & ACC_FINAL )        fprintf (fp," FINAL");
563    if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
564    if ( f & ACC_VOLATILE )     fprintf (fp," VOLATILE");
565    if ( f & ACC_TRANSIENT )    fprintf (fp," TRANSIENT");
566    if ( f & ACC_NATIVE )       fprintf (fp," NATIVE");
567    if ( f & ACC_INTERFACE )    fprintf (fp," INTERFACE");
568    if ( f & ACC_ABSTRACT )     fprintf (fp," ABSTRACT");
569 }
570
571
572 /********** internal function: printflags  (only for debugging) ***************/
573
574 void printflags(u2 f)
575 {
576    if ( f & ACC_PUBLIC )       printf (" PUBLIC");
577    if ( f & ACC_PRIVATE )      printf (" PRIVATE");
578    if ( f & ACC_PROTECTED )    printf (" PROTECTED");
579    if ( f & ACC_STATIC )       printf (" STATIC");
580    if ( f & ACC_FINAL )        printf (" FINAL");
581    if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
582    if ( f & ACC_VOLATILE )     printf (" VOLATILE");
583    if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
584    if ( f & ACC_NATIVE )       printf (" NATIVE");
585    if ( f & ACC_INTERFACE )    printf (" INTERFACE");
586    if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
587 }
588
589
590 /************************* Function: skipattribute *****************************
591
592         skips a (1) 'attribute' structure in the class file
593
594 *******************************************************************************/
595
596 static void skipattribute()
597 {
598         u4 len;
599         suck_u2 ();
600         len = suck_u4();
601         skip_nbytes(len);       
602 }
603
604
605 /********************** Function: skipattributebody ****************************
606
607         skips an attribute after the 16 bit reference to attribute_name has already
608         been read
609         
610 *******************************************************************************/
611
612 static void skipattributebody()
613 {
614         u4 len;
615         len = suck_u4();
616         skip_nbytes(len);
617 }
618
619
620 /************************* Function: skipattributes ****************************
621
622         skips num attribute structures
623         
624 *******************************************************************************/
625
626 static void skipattributes(u4 num)
627 {
628         u4 i;
629         for (i = 0; i < num; i++)
630                 skipattribute();
631 }
632
633
634 /******************** function: innerclass_getconstant ************************
635
636     like class_getconstant, but if cptags is ZERO null is returned                                       
637         
638 *******************************************************************************/
639
640 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype) 
641 {
642         /* invalid position in constantpool */
643         if (pos >= c->cpcount)
644                 panic("Attempt to access constant outside range");
645
646         /* constantpool entry of type 0 */      
647         if (!c->cptags[pos])
648                 return NULL;
649
650         /* check type of constantpool entry */
651         if (c->cptags[pos] != ctype) {
652                 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
653                           (int) ctype, (int) c->cptags[pos] );
654         }
655                 
656         return c->cpinfos[pos];
657 }
658
659
660 /************************ function: attribute_load ****************************
661
662     read attributes from classfile
663         
664 *******************************************************************************/
665
666 static void attribute_load(u4 num, classinfo *c)
667 {
668         u4 i, j;
669
670         for (i = 0; i < num; i++) {
671                 /* retrieve attribute name */
672                 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
673
674                 if (aname == utf_innerclasses) {
675                         /* innerclasses attribute */
676
677                         if (c->innerclass != NULL)
678                                 panic("Class has more than one InnerClasses attribute");
679                                 
680                         /* skip attribute length */                                             
681                         suck_u4(); 
682                         /* number of records */
683                         c->innerclasscount = suck_u2();
684                         /* allocate memory for innerclass structure */
685                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
686
687                         for (j = 0; j < c->innerclasscount; j++) {
688                                 /*  The innerclass structure contains a class with an encoded name, 
689                                     its defining scope, its simple name  and a bitmask of the access flags. 
690                                     If an inner class is not a member, its outer_class is NULL, 
691                                     if a class is anonymous, its name is NULL.                              */
692                                                                 
693                                 innerclassinfo *info = c->innerclass + j;
694
695                                 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
696                                 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
697                                 info->name  = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8);        /* CONSTANT_Utf8_info index  */
698                                 info->flags = suck_u2();                                                  /* access_flags bitmask      */
699                         }
700                 } else if (aname==utf_sourcefile) {
701                         suck_u4();
702                         /*log_text("source file attribute found");*/
703                         c->sourcefile = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
704                 } else {
705                         /* unknown attribute */
706                         skipattributebody();
707                 }
708         }
709 }
710
711
712 /******************* function: checkfielddescriptor ****************************
713
714         checks whether a field-descriptor is valid and aborts otherwise
715         all referenced classes are inserted into the list of unloaded classes
716         
717 *******************************************************************************/
718
719 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
720 {
721         class_from_descriptor(utf_ptr,end_pos,NULL,
722                                                   CLASSLOAD_NEW
723                                                   | CLASSLOAD_NULLPRIMITIVE
724                                                   | CLASSLOAD_NOVOID
725                                                   | CLASSLOAD_CHECKEND);
726         
727         /* XXX use the following if -noverify */
728 #if 0
729         char *tstart;  /* pointer to start of classname */
730         char ch;
731         char *start = utf_ptr;
732
733         switch (*utf_ptr++) {
734           case 'B':
735           case 'C':
736           case 'I':
737           case 'S':
738           case 'Z':  
739           case 'J':  
740           case 'F':  
741           case 'D':
742                   /* primitive type */  
743                   break;
744                   
745           case '[':
746           case 'L':
747                   if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
748                           panic ("Ill formed descriptor");
749                   break;
750                   
751           default:   
752                   panic ("Ill formed descriptor");
753         }                       
754         
755         /* exceeding characters */              
756         if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
757 #endif
758 }
759
760
761 /******************* function checkmethoddescriptor ****************************
762
763     checks whether a method-descriptor is valid and aborts otherwise.
764     All referenced classes are inserted into the list of unloaded classes.
765
766     The number of arguments is returned. A long or double argument is counted
767     as two arguments.
768         
769 *******************************************************************************/
770
771 static int checkmethoddescriptor (utf *d)
772 {
773         char *utf_ptr = d->text;     /* current position in utf text   */
774         char *end_pos = utf_end(d);  /* points behind utf string       */
775         int argcount = 0;            /* number of arguments            */
776
777         /* method descriptor must start with parenthesis */
778         if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
779
780     /* check arguments */
781     while (utf_ptr != end_pos && *utf_ptr != ')') {
782                 /* We cannot count the this argument here because
783                  * we don't know if the method is static. */
784                 if (*utf_ptr == 'J' || *utf_ptr == 'D')
785                         argcount+=2;
786                 else
787                         argcount++;
788                 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
789                                                           CLASSLOAD_NEW
790                                                           | CLASSLOAD_NULLPRIMITIVE
791                                                           | CLASSLOAD_NOVOID);
792         }
793
794         if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
795     utf_ptr++; /* skip ')' */
796
797         class_from_descriptor(utf_ptr,end_pos,NULL,
798                                                   CLASSLOAD_NEW
799                                                   | CLASSLOAD_NULLPRIMITIVE
800                                                   | CLASSLOAD_CHECKEND);
801
802         if (argcount > 255)
803                 panic("Invalid method descriptor: too many arguments");
804
805         return argcount;
806
807         /* XXX use the following if -noverify */
808 #if 0
809         /* check arguments */
810         while ((c = *utf_ptr++) != ')') {
811                 start = utf_ptr-1;
812                 
813                 switch (c) {
814                 case 'B':
815                 case 'C':
816                 case 'I':
817                 case 'S':
818                 case 'Z':  
819                 case 'J':  
820                 case 'F':  
821                 case 'D':
822                         /* primitive type */  
823                         break;
824
825                 case '[':
826                 case 'L':
827                         if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
828                                 panic ("Ill formed method descriptor");
829                         break;
830                         
831                 default:   
832                         panic ("Ill formed methodtype-descriptor");
833                 }
834         }
835
836         /* check returntype */
837         if (*utf_ptr=='V') {
838                 /* returntype void */
839                 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
840         }
841         else
842                 /* treat as field-descriptor */
843                 checkfielddescriptor (utf_ptr,end_pos);
844 #endif
845 }
846
847
848 /***************** Function: print_arraydescriptor ****************************
849
850         Debugging helper for displaying an arraydescriptor
851         
852 *******************************************************************************/
853
854 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
855 {
856         if (!desc) {
857                 fprintf(file, "<NULL>");
858                 return;
859         }
860
861         fprintf(file, "{");
862         if (desc->componentvftbl) {
863                 if (desc->componentvftbl->class)
864                         utf_fprint(file, desc->componentvftbl->class->name);
865                 else
866                         fprintf(file, "<no classinfo>");
867         }
868         else
869                 fprintf(file, "0");
870                 
871         fprintf(file, ",");
872         if (desc->elementvftbl) {
873                 if (desc->elementvftbl->class)
874                         utf_fprint(file, desc->elementvftbl->class->name);
875                 else
876                         fprintf(file, "<no classinfo>");
877         }
878         else
879                 fprintf(file, "0");
880         fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
881                         desc->dataoffset, desc->componentsize);
882 }
883
884
885 /******************************************************************************/
886 /**************************  Functions for fields  ****************************/
887 /******************************************************************************/
888
889
890 /************************ Function: field_load *********************************
891
892         Load everything about a class field from the class file and fill a
893         'fieldinfo' structure. For static fields, space in the data segment is
894         allocated.
895
896 *******************************************************************************/
897
898 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
899
900 static void field_load(fieldinfo *f, classinfo *c)
901 {
902         u4 attrnum,i;
903         u4 jtype;
904         u4 pindex = field_load_NOVALUE;                               /* constantvalue_index */
905
906         f->flags = suck_u2();                                           /* ACC flags         */
907         f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);       /* name of field     */
908         f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
909         
910         if (opt_verify) {
911                 /* check name */
912                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
913                         panic("Field with invalid name");
914                 
915                 /* check flag consistency */
916                 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
917                 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
918                         panic("Field has invalid access flags");
919                 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
920                         panic("Field is declared final and volatile");
921                 if ((c->flags & ACC_INTERFACE) != 0) {
922                         if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
923                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
924                                 panic("Interface field is not declared static final public");
925                         if ((f->flags & ACC_TRANSIENT) != 0)
926                                 panic("Interface field declared transient");
927                 }
928
929                 /* check descriptor */
930                 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
931         }
932                 
933         f->type = jtype = desc_to_type(f->descriptor);                      /* data type         */
934         f->offset = 0;                                                            /* offset from start of object */
935         f->class = c;
936         f->xta = NULL;
937         
938         switch (f->type) {
939         case TYPE_INT:        f->value.i = 0; break;
940         case TYPE_FLOAT:      f->value.f = 0.0; break;
941         case TYPE_DOUBLE:     f->value.d = 0.0; break;
942         case TYPE_ADDRESS:    f->value.a = NULL; break;
943         case TYPE_LONG:
944 #if U8_AVAILABLE
945                 f->value.l = 0; break;
946 #else
947                 f->value.l.low = 0; f->value.l.high = 0; break;
948 #endif
949         }
950
951         /* read attributes */
952         attrnum = suck_u2();
953         for (i = 0; i < attrnum; i++) {
954                 utf *aname;
955
956                 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
957                 
958                 if (aname != utf_constantvalue) {
959                         /* unknown attribute */
960                         skipattributebody();
961
962                 } else {
963                         /* constant value attribute */
964
965                         if (pindex != field_load_NOVALUE)
966                                 panic("Field has more than one ConstantValue attribute");
967                         
968                         /* check attribute length */
969                         if (suck_u4() != 2)
970                                 panic("ConstantValue attribute has invalid length");
971                         
972                         /* index of value in constantpool */            
973                         pindex = suck_u2();
974                 
975                         /* initialize field with value from constantpool */             
976                         switch (jtype) {
977                         case TYPE_INT: {
978                                 constant_integer *ci = 
979                                         class_getconstant(c, pindex, CONSTANT_Integer);
980                                 f->value.i = ci->value;
981                         }
982                         break;
983                                         
984                         case TYPE_LONG: {
985                                 constant_long *cl = 
986                                         class_getconstant(c, pindex, CONSTANT_Long);
987                                 f->value.l = cl->value;
988                         }
989                         break;
990
991                         case TYPE_FLOAT: {
992                                 constant_float *cf = 
993                                         class_getconstant(c, pindex, CONSTANT_Float);
994                                 f->value.f = cf->value;
995                         }
996                         break;
997                                                                                         
998                         case TYPE_DOUBLE: {
999                                 constant_double *cd = 
1000                                         class_getconstant(c, pindex, CONSTANT_Double);
1001                                 f->value.d = cd->value;
1002                         }
1003                         break;
1004                                                 
1005                         case TYPE_ADDRESS: { 
1006                                 utf *u = class_getconstant(c, pindex, CONSTANT_String);
1007                                 /* create javastring from compressed utf8-string */                                     
1008                                 f->value.a = literalstring_new(u);
1009                         }
1010                         break;
1011         
1012                         default: 
1013                                 log_text ("Invalid Constant - Type");
1014                         }
1015                 }
1016         }
1017 }
1018
1019
1020 /********************** function: field_free **********************************/
1021
1022 static void field_free (fieldinfo *f)
1023 {
1024         /* empty */
1025 }
1026
1027
1028 /**************** Function: field_display (debugging only) ********************/
1029
1030 void field_display(fieldinfo *f)
1031 {
1032         printf("   ");
1033         printflags(f->flags);
1034         printf(" ");
1035         utf_display(f->name);
1036         printf(" ");
1037         utf_display(f->descriptor);     
1038         printf(" offset: %ld\n", (long int) (f->offset));
1039 }
1040
1041
1042 /******************************************************************************/
1043 /************************* Functions for methods ******************************/ 
1044 /******************************************************************************/
1045
1046
1047 /*********************** Function: method_load *********************************
1048
1049         Loads a method from the class file and fills an existing 'methodinfo'
1050         structure. For native methods, the function pointer field is set to the
1051         real function pointer, for JavaVM methods a pointer to the compiler is used
1052         preliminarily.
1053         
1054 *******************************************************************************/
1055
1056 static void method_load(methodinfo *m, classinfo *c)
1057 {
1058         u4 attrnum, i, e;
1059         int argcount;
1060         
1061 #ifdef STATISTICS
1062         count_all_methods++;
1063 #endif
1064         m->thrownexceptionscount=0;
1065         m->linenumbercount=0;
1066         m->linenumbers=0;
1067         m->class = c;
1068         
1069         m->flags = suck_u2();
1070         m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1071
1072         if (opt_verify) {
1073                 if (!is_valid_name_utf(m->name))
1074                         panic("Method with invalid name");
1075                 if (m->name->text[0] == '<'
1076                         && m->name != utf_init && m->name != utf_clinit)
1077                         panic("Method with invalid special name");
1078         }
1079         
1080         m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1081         argcount = checkmethoddescriptor(m->descriptor);
1082         if ((m->flags & ACC_STATIC) == 0)
1083                 argcount++; /* count the 'this' argument */
1084
1085         if (opt_verify) {
1086                 if (argcount > 255)
1087                         panic("Method has more than 255 arguments");
1088
1089                 /* check flag consistency */
1090                 if (m->name != utf_clinit) {
1091                         i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1092                         if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1093                                 panic("Method has invalid access flags");
1094                         if ((m->flags & ACC_ABSTRACT) != 0) {
1095                                 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1096                                                                  | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1097                                         panic("Abstract method has invalid flags set");
1098                         }
1099                         if ((c->flags & ACC_INTERFACE) != 0) {
1100                                 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1101                                         != (ACC_ABSTRACT | ACC_PUBLIC))
1102                                         panic("Interface method is not declared abstract and public");
1103                         }
1104                         if (m->name == utf_init) {
1105                                 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1106                                                                  | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1107                                         panic("Instance initialization method has invalid flags set");
1108                         }
1109                 }
1110         }
1111                 
1112         m->jcode = NULL;
1113         m->exceptiontable = NULL;
1114         m->entrypoint = NULL;
1115         m->mcode = NULL;
1116         m->stubroutine = NULL;
1117         m->methodUsed = NOTUSED;    
1118         m->monoPoly = MONO;    
1119         m->subRedefs = 0;
1120         m->subRedefsUsed = 0;
1121
1122         m->xta = NULL;
1123         
1124         if (!(m->flags & ACC_NATIVE)) {
1125                 m->stubroutine = createcompilerstub(m);
1126
1127         } else {
1128                 functionptr f = native_findfunction(c->name, m->name, m->descriptor, 
1129                                                                                         (m->flags & ACC_STATIC) != 0);
1130                 if (f) {
1131                         m->stubroutine = createnativestub(f, m);
1132                 }
1133         }
1134         
1135         
1136         attrnum = suck_u2();
1137         for (i = 0; i < attrnum; i++) {
1138                 utf *aname;
1139
1140                 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1141
1142                 if (aname != utf_code) {
1143                         if (aname == utf_exceptions) {
1144                                 u2 exceptionCount;
1145                                 u2 exceptionID;
1146                                 suck_u4(); /*length*/
1147                                 exceptionCount=suck_u2();
1148                                 m->thrownexceptionscount=exceptionCount;
1149                                 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1150                                 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1151                                         (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(),CONSTANT_Class);
1152                                 }
1153                         }
1154                         else
1155                         skipattributebody();
1156
1157                 } else {
1158                         u4 codelen;
1159                         if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1160                                 panic("Code attribute for native or abstract method");
1161                         
1162                         if (m->jcode)
1163                                 panic("Method has more than one Code attribute");
1164
1165                         suck_u4();
1166                         m->maxstack = suck_u2();
1167                         m->maxlocals = suck_u2();
1168                         if (m->maxlocals < argcount)
1169                                 panic("max_locals is smaller than the number of arguments");
1170                         
1171                         codelen = suck_u4();
1172                         if (codelen == 0)
1173                                 panic("bytecode has zero length");
1174                         if (codelen > 65536)
1175                                 panic("bytecode too long");
1176                         m->jcodelength = codelen;
1177                         m->jcode = MNEW(u1, m->jcodelength);
1178                         suck_nbytes(m->jcode, m->jcodelength);
1179                         m->exceptiontablelength = suck_u2();
1180                         m->exceptiontable = 
1181                                 MNEW(exceptiontable, m->exceptiontablelength);
1182
1183 #ifdef STATISTICS
1184                         count_vmcode_len += m->jcodelength + 18;
1185                         count_extable_len += 8 * m->exceptiontablelength;
1186 #endif
1187
1188                         for (e = 0; e < m->exceptiontablelength; e++) {
1189                                 u4 idx;
1190                                 m->exceptiontable[e].startpc = suck_u2();
1191                                 m->exceptiontable[e].endpc = suck_u2();
1192                                 m->exceptiontable[e].handlerpc = suck_u2();
1193
1194                                 idx = suck_u2();
1195                                 if (!idx) {
1196                                         m->exceptiontable[e].catchtype = NULL;
1197
1198                                 } else {
1199                                         m->exceptiontable[e].catchtype = 
1200                                       class_getconstant(c, idx, CONSTANT_Class);
1201                                 }
1202                         }                       
1203                         {
1204                                 u2 codeattrnum;
1205                                 for (codeattrnum=suck_u2();codeattrnum>0;codeattrnum--) {
1206                                         utf * caname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1207                                         if (caname==utf_linenumbertable) {
1208                                                 u2 lncid;
1209                                                 /*log_text("LineNumberTable found");*/
1210                                                 suck_u4();
1211                                                 m->linenumbercount=suck_u2();
1212                                                 /*printf("length:%d\n",m->linenumbercount);*/
1213                                                 m->linenumbers=MNEW(lineinfo,m->linenumbercount);
1214                                                 for (lncid=0;lncid<m->linenumbercount;lncid++) {
1215                                                         m->linenumbers[lncid].start_pc=suck_u2();
1216                                                         m->linenumbers[lncid].line_number=suck_u2();
1217                                                 }
1218                                                 codeattrnum--;
1219                                                 skipattributes(codeattrnum);
1220                                                 break;
1221                                         } else skipattributebody();
1222                                         
1223                                 }                               
1224                         }
1225                 }
1226         }
1227
1228         if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1229                 panic("Method missing Code attribute");
1230 }
1231
1232
1233 /********************* Function: method_free ***********************************
1234
1235         frees all memory that was allocated for this method
1236
1237 *******************************************************************************/
1238
1239 static void method_free(methodinfo *m)
1240 {
1241         if (m->jcode)
1242                 MFREE(m->jcode, u1, m->jcodelength);
1243
1244         if (m->exceptiontable)
1245                 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1246
1247         if (m->mcode)
1248                 CFREE(m->mcode, m->mcodelength);
1249
1250         if (m->stubroutine) {
1251                 if (m->flags & ACC_NATIVE) {
1252                         removenativestub(m->stubroutine);
1253
1254                 } else {
1255                         removecompilerstub(m->stubroutine);
1256                 }
1257         }
1258 }
1259
1260
1261 /************** Function: method_display  (debugging only) **************/
1262
1263 void method_display(methodinfo *m)
1264 {
1265         printf("   ");
1266         printflags(m->flags);
1267         printf(" ");
1268         utf_display(m->name);
1269         printf(" "); 
1270         utf_display(m->descriptor);
1271         printf("\n");
1272 }
1273
1274 /************** Function: method_display_flags_last  (debugging only) **************/
1275
1276 void method_display_flags_last(methodinfo *m)
1277 {
1278         printf(" ");
1279         utf_display(m->name);
1280         printf(" ");
1281         utf_display(m->descriptor);
1282         printf("   ");
1283         printflags(m->flags);
1284         printf("\n");
1285 }
1286
1287
1288 /******************** Function: method_canoverwrite ****************************
1289
1290         Check if m and old are identical with respect to type and name. This means
1291         that old can be overwritten with m.
1292         
1293 *******************************************************************************/  
1294
1295 static bool method_canoverwrite(methodinfo *m, methodinfo *old)
1296 {
1297         if (m->name != old->name) return false;
1298         if (m->descriptor != old->descriptor) return false;
1299         if (m->flags & ACC_STATIC) return false;
1300         return true;
1301 }
1302
1303
1304
1305
1306 /******************************************************************************/
1307 /************************ Functions for class *********************************/
1308 /******************************************************************************/
1309
1310
1311 /******************** function:: class_getconstant ******************************
1312
1313         retrieves the value at position 'pos' of the constantpool of a class
1314         if the type of the value is other than 'ctype' the system is stopped
1315
1316 *******************************************************************************/
1317
1318 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1319 {
1320         /* invalid position in constantpool */
1321         /* (pos == 0 is caught by type comparison) */
1322         if (pos >= c->cpcount)
1323                 panic("Attempt to access constant outside range");
1324
1325         /* check type of constantpool entry */
1326
1327         if (c->cptags[pos] != ctype) {
1328                 class_showconstantpool(c);
1329                 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1330                           (int) ctype, (int) c->cptags[pos]);
1331         }
1332                 
1333         return c->cpinfos[pos];
1334 }
1335
1336
1337 /********************* Function: class_constanttype ****************************
1338
1339         Determines the type of a class entry in the ConstantPool
1340         
1341 *******************************************************************************/
1342
1343 u4 class_constanttype(classinfo *c, u4 pos)
1344 {
1345         if (pos >= c->cpcount)
1346                 panic("Attempt to access constant outside range");
1347
1348         return c->cptags[pos];
1349 }
1350
1351
1352 /******************** function: class_loadcpool ********************************
1353
1354         loads the constantpool of a class, 
1355         the entries are transformed into a simpler format 
1356         by resolving references
1357         (a detailed overview of the compact structures can be found in global.h)        
1358
1359 *******************************************************************************/
1360
1361 static void class_loadcpool(classinfo *c)
1362 {
1363
1364         /* The following structures are used to save information which cannot be 
1365            processed during the first pass. After the complete constantpool has 
1366            been traversed the references can be resolved. 
1367            (only in specific order)                                                */
1368         
1369         /* CONSTANT_Class_info entries */
1370         typedef struct forward_class {      
1371                 struct forward_class *next; 
1372                 u2 thisindex;               
1373                 u2 name_index;              
1374         } forward_class;                    
1375                                         
1376         /* CONSTANT_String */                                      
1377         typedef struct forward_string { 
1378                 struct forward_string *next; 
1379                 u2 thisindex;                
1380                 u2 string_index;
1381         } forward_string;
1382
1383         /* CONSTANT_NameAndType */
1384         typedef struct forward_nameandtype {
1385                 struct forward_nameandtype *next;
1386                 u2 thisindex;
1387                 u2 name_index;
1388                 u2 sig_index;
1389         } forward_nameandtype;
1390
1391         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1392         typedef struct forward_fieldmethint {   
1393                 struct forward_fieldmethint *next;
1394                 u2 thisindex;
1395                 u1 tag;
1396                 u2 class_index;
1397                 u2 nameandtype_index;
1398         } forward_fieldmethint;
1399
1400
1401         u4 idx;
1402         long int dumpsize = dump_size ();
1403
1404         forward_class *forward_classes = NULL;
1405         forward_string *forward_strings = NULL;
1406         forward_nameandtype *forward_nameandtypes = NULL;
1407         forward_fieldmethint *forward_fieldmethints = NULL;
1408
1409         /* number of entries in the constant_pool table plus one */
1410         u4 cpcount       = c->cpcount = suck_u2();
1411
1412         /* allocate memory */
1413         u1 *cptags       = c->cptags  = MNEW(u1, cpcount);
1414         voidptr *cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1415
1416         if (!cpcount)
1417                 panic("Invalid constant_pool_count (0)");
1418         
1419 #ifdef STATISTICS
1420         count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1421 #endif
1422         
1423         /* initialize constantpool */
1424         for (idx = 0; idx < cpcount; idx++) {
1425                 cptags[idx] = CONSTANT_UNUSED;
1426                 cpinfos[idx] = NULL;
1427         }
1428
1429                         
1430         /******* first pass *******/
1431         /* entries which cannot be resolved now are written into 
1432            temporary structures and traversed again later        */
1433                    
1434         idx = 1;
1435         while (idx < cpcount) {
1436                 /* get constant type */
1437                 u4 t = suck_u1();
1438
1439                 switch (t) {
1440                         case CONSTANT_Class: { 
1441                                 forward_class *nfc = DNEW(forward_class);
1442
1443                                 nfc -> next = forward_classes;                                                                                  
1444                                 forward_classes = nfc;
1445
1446                                 nfc -> thisindex = idx;
1447                                 /* reference to CONSTANT_NameAndType */
1448                                 nfc -> name_index = suck_u2 (); 
1449
1450                                 idx++;
1451                                 break;
1452                                 }
1453                         
1454                         case CONSTANT_Fieldref:
1455                         case CONSTANT_Methodref:
1456                         case CONSTANT_InterfaceMethodref: { 
1457                                 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1458                                 
1459                                 nff -> next = forward_fieldmethints;
1460                                 forward_fieldmethints = nff;
1461
1462                                 nff -> thisindex = idx;
1463                                 /* constant type */
1464                                 nff -> tag = t;
1465                                 /* class or interface type that contains the declaration of the field or method */
1466                                 nff -> class_index = suck_u2 (); 
1467                                 /* name and descriptor of the field or method */
1468                                 nff -> nameandtype_index = suck_u2 ();
1469
1470                                 idx ++;
1471                                 break;
1472                                 }
1473                                 
1474                         case CONSTANT_String: {
1475                                 forward_string *nfs = DNEW(forward_string);
1476                                 
1477                                 nfs->next = forward_strings;
1478                                 forward_strings = nfs;
1479                                 
1480                                 nfs->thisindex = idx;
1481                                 /* reference to CONSTANT_Utf8_info with string characters */
1482                                 nfs->string_index = suck_u2();
1483                                 
1484                                 idx ++;
1485                                 break;
1486                                 }
1487
1488                         case CONSTANT_NameAndType: {
1489                                 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1490                                 
1491                                 nfn -> next = forward_nameandtypes;
1492                                 forward_nameandtypes = nfn;
1493                                 
1494                                 nfn -> thisindex = idx;
1495                                 /* reference to CONSTANT_Utf8_info containing simple name */
1496                                 nfn -> name_index = suck_u2 ();
1497                                 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1498                                 nfn -> sig_index = suck_u2 ();
1499                                 
1500                                 idx ++;
1501                                 break;
1502                                 }
1503
1504                         case CONSTANT_Integer: {
1505                                 constant_integer *ci = NEW (constant_integer);
1506
1507 #ifdef STATISTICS
1508         count_const_pool_len += sizeof(constant_integer);
1509 #endif
1510
1511                                 ci -> value = suck_s4 ();
1512                                 cptags [idx] = CONSTANT_Integer;
1513                                 cpinfos [idx] = ci;
1514                                 idx ++;
1515                                 
1516                                 break;
1517                                 }
1518                                 
1519                         case CONSTANT_Float: {
1520                                 constant_float *cf = NEW (constant_float);
1521
1522 #ifdef STATISTICS
1523         count_const_pool_len += sizeof(constant_float);
1524 #endif
1525
1526                                 cf -> value = suck_float ();
1527                                 cptags [idx] = CONSTANT_Float;
1528                                 cpinfos[idx] = cf;
1529                                 idx ++;
1530                                 break;
1531                                 }
1532                                 
1533                         case CONSTANT_Long: {
1534                                 constant_long *cl = NEW(constant_long);
1535                                         
1536 #ifdef STATISTICS
1537         count_const_pool_len += sizeof(constant_long);
1538 #endif
1539
1540                                 cl -> value = suck_s8 ();
1541                                 cptags [idx] = CONSTANT_Long;
1542                                 cpinfos [idx] = cl;
1543                                 idx += 2;
1544                                 if (idx > cpcount)
1545                                         panic("Long constant exceeds constant pool");
1546                                 break;
1547                                 }
1548                         
1549                         case CONSTANT_Double: {
1550                                 constant_double *cd = NEW(constant_double);
1551                                 
1552 #ifdef STATISTICS
1553         count_const_pool_len += sizeof(constant_double);
1554 #endif
1555
1556                                 cd -> value = suck_double ();
1557                                 cptags [idx] = CONSTANT_Double;
1558                                 cpinfos [idx] = cd;
1559                                 idx += 2;
1560                                 if (idx > cpcount)
1561                                         panic("Double constant exceeds constant pool");
1562                                 break;
1563                                 }
1564                                 
1565                         case CONSTANT_Utf8: { 
1566
1567                                 /* number of bytes in the bytes array (not string-length) */
1568                                 u4 length = suck_u2();
1569                                 cptags [idx]  = CONSTANT_Utf8;
1570                                 /* validate the string */
1571                                 ASSERT_LEFT(length);
1572                                 if (opt_verify &&
1573                                         !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1574                                 {
1575                                         dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1576                                         panic("Invalid UTF-8 string");
1577                                 }
1578                                 /* insert utf-string into the utf-symboltable */
1579                                 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1580                                 /* skip bytes of the string */
1581                                 skip_nbytes(length);
1582                                 idx++;
1583                                 break;
1584                                 }
1585                                                                                 
1586                         default:
1587                                 error ("Unkown constant type: %d",(int) t);
1588                 
1589                         }  /* end switch */
1590                         
1591                 } /* end while */
1592                 
1593
1594
1595            /* resolve entries in temporary structures */
1596
1597         while (forward_classes) {
1598                 utf *name =
1599                   class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1600
1601                 if (opt_verify && !is_valid_name_utf(name))
1602                         panic("Class reference with invalid name");
1603
1604                 cptags  [forward_classes -> thisindex] = CONSTANT_Class;
1605                 /* retrieve class from class-table */
1606                 cpinfos [forward_classes -> thisindex] = class_new (name);
1607
1608                 forward_classes = forward_classes -> next;
1609                 
1610                 }
1611
1612         while (forward_strings) {
1613                 utf *text = 
1614                   class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1615 /*
1616                 log_text("forward_string:");
1617                 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1618                 utf_display(text);
1619                 log_text("\n------------------"); */
1620                 /* resolve utf-string */                
1621                 cptags   [forward_strings -> thisindex] = CONSTANT_String;
1622                 cpinfos  [forward_strings -> thisindex] = text;
1623                 
1624                 forward_strings = forward_strings -> next;
1625                 }       
1626
1627         while (forward_nameandtypes) {
1628                 constant_nameandtype *cn = NEW (constant_nameandtype);  
1629
1630 #ifdef STATISTICS
1631                 count_const_pool_len += sizeof(constant_nameandtype);
1632 #endif
1633
1634                 /* resolve simple name and descriptor */
1635                 cn -> name = class_getconstant 
1636                    (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1637                 cn -> descriptor = class_getconstant
1638                    (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1639
1640                 if (opt_verify) {
1641                         /* check name */
1642                         if (!is_valid_name_utf(cn->name))
1643                                 panic("NameAndType with invalid name");
1644                         /* disallow referencing <clinit> among others */
1645                         if (cn->name->text[0] == '<' && cn->name != utf_init)
1646                                 panic("NameAndType with invalid special name");
1647                 }
1648
1649                 cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1650                 cpinfos  [forward_nameandtypes -> thisindex] = cn;
1651                 
1652                 forward_nameandtypes = forward_nameandtypes -> next;
1653                 }
1654
1655
1656         while (forward_fieldmethints)  {
1657                 constant_nameandtype *nat;
1658                 constant_FMIref *fmi = NEW (constant_FMIref);
1659
1660 #ifdef STATISTICS
1661                 count_const_pool_len += sizeof(constant_FMIref);
1662 #endif
1663                 /* resolve simple name and descriptor */
1664                 nat = class_getconstant
1665                         (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1666
1667 #ifdef JOWENN_DEBUG
1668                 log_text("trying to resolve:");
1669                 log_text(nat->name->text);
1670                 switch(forward_fieldmethints ->tag) {
1671                 case CONSTANT_Fieldref: 
1672                                 log_text("CONSTANT_Fieldref");
1673                                 break;
1674                 case CONSTANT_InterfaceMethodref: 
1675                                 log_text("CONSTANT_InterfaceMethodref");
1676                                 break;
1677                 case CONSTANT_Methodref: 
1678                                 log_text("CONSTANT_Methodref");
1679                                 break;
1680                 }
1681 #endif
1682                 fmi -> class = class_getconstant 
1683                         (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1684                 fmi -> name = nat -> name;
1685                 fmi -> descriptor = nat -> descriptor;
1686
1687                 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1688                 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1689         
1690                 switch (forward_fieldmethints -> tag) {
1691                 case CONSTANT_Fieldref:  /* check validity of descriptor */
1692                                          checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1693                                          break;
1694                 case CONSTANT_InterfaceMethodref: 
1695                 case CONSTANT_Methodref: /* check validity of descriptor */
1696                                          checkmethoddescriptor (fmi->descriptor);
1697                                          break;
1698                 }               
1699         
1700                 forward_fieldmethints = forward_fieldmethints -> next;
1701
1702                 }
1703
1704 /*      class_showconstantpool(c); */
1705
1706         dump_release(dumpsize);
1707 }
1708
1709
1710 /********************** Function: class_load ***********************************
1711         
1712         Loads everything interesting about a class from the class file. The
1713         'classinfo' structure must have been allocated previously.
1714
1715         The super class and the interfaces implemented by this class need not be
1716         loaded. The link is set later by the function 'class_link'.
1717
1718         The loaded class is removed from the list 'unloadedclasses' and added to
1719         the list 'unlinkedclasses'.
1720         
1721 *******************************************************************************/
1722
1723 static int class_load(classinfo *c)
1724 {
1725         u4 i;
1726         u4 mi,ma;
1727
1728 #ifdef STATISTICS
1729         count_class_loads++;
1730 #endif
1731
1732         /* output for debugging purposes */
1733         if (loadverbose) {              
1734                 char logtext[MAXLOGTEXT];
1735                 sprintf(logtext, "Loading class: ");
1736                 utf_sprint(logtext + strlen(logtext), c->name);
1737                 log_text(logtext);
1738         }
1739         
1740         /* load classdata, throw exception on error */
1741
1742         if (!suck_start(c->name)) {
1743                 throw_noclassdeffounderror_message(c->name);
1744                 return false;
1745         }
1746         
1747         /* check signature */
1748         if (suck_u4() != MAGIC)
1749                 panic("Can not find class-file signature");
1750
1751         /* check version */
1752         mi = suck_u2();
1753         ma = suck_u2();
1754 #if 0
1755         if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1756                 error("File version %d.%d is not supported", (int) ma, (int) mi);
1757         }
1758 #endif
1759
1760         class_loadcpool(c);
1761         /*JOWENN*/
1762         c->erroneous_state = 0;
1763         c->initializing_thread = 0;     
1764         /*JOWENN*/
1765         c->classUsed = NOTUSED; /* not used initially CO-RT */
1766         c->impldBy = NULL;
1767
1768         /* ACC flags */
1769         c->flags = suck_u2(); 
1770         /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1771
1772         /* check ACC flags consistency */
1773         if ((c->flags & ACC_INTERFACE) != 0) {
1774                 if ((c->flags & ACC_ABSTRACT) == 0) {
1775                         /* We work around this because interfaces in JDK 1.1 are
1776                          * not declared abstract. */
1777
1778                         c->flags |= ACC_ABSTRACT;
1779                         /* panic("Interface class not declared abstract"); */
1780                 }
1781                 if ((c->flags & (ACC_FINAL)) != 0)
1782                         panic("Interface class has invalid flags");
1783                 if ((c->flags & (ACC_SUPER)) != 0)
1784                         c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1785         }
1786         if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1787                 panic("Class is declared both abstract and final");
1788
1789         /* this class */
1790         i = suck_u2();
1791         if (class_getconstant(c, i, CONSTANT_Class) != c) {
1792 /*              char message[MAXLOGTEXT]; */
1793 /*              utf_sprint(message, c->name); */
1794 /*              sprintf(message + strlen(message), " (wrong name: "); */
1795 /*              utf_sprint(message + strlen(message), class_getconstant(c, i, CONSTANT_Class)); */
1796 /*              sprintf(message + strlen(message), ")"); */
1797
1798 /*              *exceptionptr = new_exception_message("java/lang/NoClassDefFoundError", */
1799 /*                                                                                        message); */
1800 /*              return false; */
1801                 panic("Invalid this_class in class file");
1802         }
1803         
1804         /* retrieve superclass */
1805         if ((i = suck_u2())) {
1806                 c->super = class_getconstant(c, i, CONSTANT_Class);
1807
1808                 /* java.lang.Object may not have a super class. */
1809                 if (c->name == utf_java_lang_Object)
1810                         panic("java.lang.Object with super class");
1811
1812                 /* Interfaces must have j.l.O as super class. */
1813                 if ((c->flags & ACC_INTERFACE) != 0
1814                         && c->super->name != utf_java_lang_Object)
1815                 {
1816                         panic("Interface with super class other than java.lang.Object");
1817                 }
1818         } else {
1819                 c->super = NULL;
1820
1821                 /* This is only allowed for java.lang.Object. */
1822                 if (c->name != utf_java_lang_Object)
1823                         panic("Class (not java.lang.Object) without super class");
1824         }
1825                          
1826         /* retrieve interfaces */
1827         c->interfacescount = suck_u2();
1828         c->interfaces = MNEW(classinfo*, c->interfacescount);
1829         for (i = 0; i < c->interfacescount; i++) {
1830                 c->interfaces[i] =
1831                         class_getconstant(c, suck_u2(), CONSTANT_Class);
1832         }
1833
1834         /* load fields */
1835         c->fieldscount = suck_u2();
1836 /*      utf_display(c->name);
1837         printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1838
1839         c->fields = GCNEW(fieldinfo, c->fieldscount);
1840         for (i = 0; i < c->fieldscount; i++) {
1841                 field_load(&(c->fields[i]), c);
1842         }
1843
1844         /* load methods */
1845         c->methodscount = suck_u2();
1846         c->methods = MNEW(methodinfo, c->methodscount);
1847         for (i = 0; i < c->methodscount; i++) {
1848                 method_load(&(c->methods[i]), c);
1849         }
1850
1851         /* Check if all fields and methods can be uniquely
1852          * identified by (name,descriptor). */
1853         if (opt_verify) {
1854                 /* We use a hash table here to avoid making the
1855                  * average case quadratic in # of methods, fields.
1856                  */
1857                 static int shift = 0;
1858                 u2 *hashtab;
1859                 u2 *next; /* for chaining colliding hash entries */
1860                 size_t len;
1861                 size_t hashlen;
1862                 u2 index;
1863                 u2 old;
1864
1865                 /* Allocate hashtable */
1866                 len = c->methodscount;
1867                 if (len < c->fieldscount) len = c->fieldscount;
1868                 hashlen = 5 * len;
1869                 hashtab = MNEW(u2,(hashlen + len));
1870                 next = hashtab + hashlen;
1871
1872                 /* Determine bitshift (to get good hash values) */
1873                 if (!shift) {
1874                         len = sizeof(utf);
1875                         while (len) {
1876                                 len >>= 1;
1877                                 shift++;
1878                         }
1879                 }
1880
1881                 /* Check fields */
1882                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
1883                 for (i = 0; i < c->fieldscount; ++i) {
1884                         fieldinfo *fi = c->fields + i;
1885                         /* It's ok if we lose bits here */
1886                         index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1887                                   % hashlen;
1888                         if ((old = hashtab[index]) != 0) {
1889                                 old--;
1890                                 /* dolog("HASHHIT %d --> %d",index,old); */
1891                                 next[i] = old;
1892                                 do {
1893                                         /* dolog("HASHCHECK %d",old); */
1894                                         if (c->fields[old].name == fi->name
1895                                                 && c->fields[old].descriptor == fi->descriptor)
1896                                         {
1897                                                 dolog("Duplicate field (%d,%d):",i,old);
1898                                                 log_utf(fi->name); log_utf(fi->descriptor);
1899                                                 panic("Fields with same name and descriptor");
1900                                         }
1901                                 } while ((old = next[old]) != 0);
1902                         }
1903                         /* else dolog("HASHLUCKY"); */
1904                         hashtab[index] = i+1;
1905                 }
1906                 
1907                 /* Check methods */
1908                 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1909                 for (i = 0; i < c->methodscount; ++i) {
1910                         methodinfo *mi = c->methods + i;
1911                         /* It's ok if we lose bits here */
1912                         index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1913                                   % hashlen;
1914                         if ((old = hashtab[index]) != 0) {
1915                                 old--;
1916                                 /* dolog("HASHHIT %d --> %d",index,old); */
1917                                 next[i] = old;
1918                                 do {
1919                                         /* dolog("HASHCHECK %d",old); */
1920                                         if (c->methods[old].name == mi->name
1921                                                 && c->methods[old].descriptor == mi->descriptor)
1922                                         {
1923                                                 dolog("Duplicate method (%d,%d):",i,old);
1924                                                 log_utf(mi->name); log_utf(mi->descriptor);
1925                                                 panic("Methods with same name and descriptor");
1926                                         }
1927                                 } while ((old = next[old]) != 0);
1928                         }
1929                         /* else dolog("HASHLUCKY"); */
1930                         hashtab[index] = i+1;
1931                 }
1932                 
1933                 MFREE(hashtab,u2,(hashlen + len));
1934         }
1935
1936 #ifdef STATISTICS
1937         count_class_infos += sizeof(classinfo*) * c->interfacescount;
1938         count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1939         count_class_infos += sizeof(methodinfo) * c->methodscount;
1940 #endif
1941
1942         /* load variable-length attribute structures */ 
1943         attribute_load(suck_u2(), c);
1944
1945         /* free memory */
1946         suck_stop();
1947
1948         /* remove class from list of unloaded classes and 
1949            add to list of unlinked classes                */
1950         list_remove(&unloadedclasses, c);
1951         list_addlast(&unlinkedclasses, c);
1952
1953         c->loaded = true;
1954
1955         return true;
1956 }
1957
1958
1959
1960 /************** internal Function: class_highestinterface ***********************
1961
1962         Used by the function class_link to determine the amount of memory needed
1963         for the interface table.
1964
1965 *******************************************************************************/
1966
1967 static s4 class_highestinterface(classinfo *c) 
1968 {
1969         s4 h;
1970         s4 i;
1971         
1972         if (!(c->flags & ACC_INTERFACE)) {
1973                 char logtext[MAXLOGTEXT];
1974                 sprintf(logtext, "Interface-methods count requested for non-interface:  ");
1975         utf_sprint(logtext + strlen(logtext), c->name);
1976         error("%s",logtext);
1977         }
1978     
1979     h = c->index;
1980         for (i = 0; i < c->interfacescount; i++) {
1981                 s4 h2 = class_highestinterface(c->interfaces[i]);
1982                 if (h2 > h) h = h2;
1983         }
1984
1985         return h;
1986 }
1987
1988
1989 /* class_addinterface **********************************************************
1990
1991         Is needed by class_link for adding a VTBL to a class. All interfaces
1992         implemented by ic are added as well.
1993
1994 *******************************************************************************/        
1995
1996 static void class_addinterface (classinfo *c, classinfo *ic)
1997 {
1998         s4     j, m;
1999         s4     i     = ic->index;
2000         vftbl *vftbl = c->vftbl;
2001         
2002         if (i >= vftbl->interfacetablelength)
2003                 panic ("Inernal error: interfacetable overflow");
2004         if (vftbl->interfacetable[-i])
2005                 return;
2006
2007         if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
2008                 vftbl->interfacevftbllength[i] = 1;
2009                 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
2010                 vftbl->interfacetable[-i][0] = NULL;
2011                 }
2012         else {
2013                 vftbl->interfacevftbllength[i] = ic->methodscount;
2014                 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
2015
2016 #ifdef STATISTICS
2017         count_vftbl_len += sizeof(methodptr) *
2018                                  (ic->methodscount + (ic->methodscount == 0));
2019 #endif
2020
2021                 for (j=0; j<ic->methodscount; j++) {
2022                         classinfo *sc = c;
2023                         while (sc) {
2024                                 for (m = 0; m < sc->methodscount; m++) {
2025                                         methodinfo *mi = &(sc->methods[m]);
2026                                         if (method_canoverwrite(mi, &(ic->methods[j]))) {
2027                                                 vftbl->interfacetable[-i][j] = 
2028                                                                           vftbl->table[mi->vftblindex];
2029                                                 goto foundmethod;
2030                                                 }
2031                                         }
2032                                 sc = sc->super;
2033                                 }
2034                          foundmethod: ;
2035                         }
2036                 }
2037
2038         for (j = 0; j < ic->interfacescount; j++) 
2039                 class_addinterface(c, ic->interfaces[j]);
2040 }
2041
2042
2043 /******************* Function: class_new_array *********************************
2044
2045     This function is called by class_new to setup an array class.
2046
2047 *******************************************************************************/
2048
2049 void class_new_array(classinfo *c)
2050 {
2051         classinfo *comp = NULL;
2052         methodinfo *clone;
2053         int namelen;
2054
2055         /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
2056
2057         /* Array classes are not loaded from classfiles. */
2058         list_remove(&unloadedclasses, c);
2059
2060         /* Check array class name */
2061         namelen = c->name->blength;
2062         if (namelen < 2 || c->name->text[0] != '[')
2063                 panic("Invalid array class name");
2064
2065         /* Check the component type */
2066         switch (c->name->text[1]) {
2067           case '[':
2068                   /* c is an array of arrays. We have to create the component class. */
2069                   comp = class_new(utf_new(c->name->text + 1,namelen - 1));
2070                   break;
2071
2072           case 'L':
2073                   /* c is an array of objects. */
2074                   if (namelen < 4 || c->name->text[namelen - 1] != ';')
2075                           panic("Invalid array class name");
2076                   comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2077                   break;
2078         }
2079
2080         /* Setup the array class */
2081         c->super = class_java_lang_Object;
2082         c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2083
2084     c->interfacescount = 2;
2085     c->interfaces = MNEW(classinfo*,2);
2086     c->interfaces[0] = class_java_lang_Cloneable;
2087     c->interfaces[1] = class_java_io_Serializable;
2088
2089         c->methodscount = 1;
2090         c->methods = MNEW (methodinfo, c->methodscount);
2091
2092         clone = c->methods;
2093         memset(clone, 0, sizeof(methodinfo));
2094         clone->flags = ACC_PUBLIC;
2095         clone->name = utf_new_char("clone");
2096         clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2097         clone->class = c;
2098         clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2099         clone->monoPoly = MONO;
2100
2101         /* XXX: field: length? */
2102
2103         /* The array class has to be linked */
2104         list_addlast(&unlinkedclasses,c);
2105         
2106         /*
2107      * Array classes which are created after the other classes have been
2108      * loaded and linked are linked explicitely.
2109      */
2110         c->loaded=true;
2111      
2112         if (loader_inited)
2113                 loader_load(c->name); /* XXX handle errors */
2114 }
2115
2116
2117 /****************** Function: class_link_array *********************************
2118
2119     This function is called by class_link to create the
2120     arraydescriptor for an array class.
2121
2122     This function returns NULL if the array cannot be linked because
2123     the component type has not been linked yet.
2124
2125 *******************************************************************************/
2126
2127 static arraydescriptor *class_link_array(classinfo *c)
2128 {
2129         classinfo *comp = NULL;
2130         int namelen = c->name->blength;
2131         arraydescriptor *desc;
2132         vftbl *compvftbl;
2133
2134         /* Check the component type */
2135         switch (c->name->text[1]) {
2136           case '[':
2137                   /* c is an array of arrays. */
2138                   comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2139                   if (!comp) panic("Could not find component array class.");
2140                   break;
2141
2142           case 'L':
2143                   /* c is an array of objects. */
2144                   comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2145                   if (!comp) panic("Could not find component class.");
2146                   break;
2147         }
2148
2149         /* If the component type has not been linked return NULL */
2150         if (comp && !comp->linked)
2151                 return NULL;
2152
2153         /* Allocate the arraydescriptor */
2154         desc = NEW(arraydescriptor);
2155
2156         if (comp) {
2157                 /* c is an array of references */
2158                 desc->arraytype = ARRAYTYPE_OBJECT;
2159                 desc->componentsize = sizeof(void*);
2160                 desc->dataoffset = OFFSET(java_objectarray,data);
2161                 
2162                 compvftbl = comp->vftbl;
2163                 if (!compvftbl)
2164                         panic("Component class has no vftbl");
2165                 desc->componentvftbl = compvftbl;
2166                 
2167                 if (compvftbl->arraydesc) {
2168                         desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2169                         if (compvftbl->arraydesc->dimension >= 255)
2170                                 panic("Creating array of dimension >255");
2171                         desc->dimension = compvftbl->arraydesc->dimension + 1;
2172                         desc->elementtype = compvftbl->arraydesc->elementtype;
2173                 }
2174                 else {
2175                         desc->elementvftbl = compvftbl;
2176                         desc->dimension = 1;
2177                         desc->elementtype = ARRAYTYPE_OBJECT;
2178                 }
2179
2180         } else {
2181                 /* c is an array of a primitive type */
2182                 switch (c->name->text[1]) {
2183                 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2184                         desc->dataoffset = OFFSET(java_booleanarray,data);
2185                         desc->componentsize = sizeof(u1);
2186                         break;
2187
2188                 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2189                         desc->dataoffset = OFFSET(java_bytearray,data);
2190                         desc->componentsize = sizeof(u1);
2191                         break;
2192
2193                 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2194                         desc->dataoffset = OFFSET(java_chararray,data);
2195                         desc->componentsize = sizeof(u2);
2196                         break;
2197
2198                 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2199                         desc->dataoffset = OFFSET(java_doublearray,data);
2200                         desc->componentsize = sizeof(double);
2201                         break;
2202
2203                 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2204                         desc->dataoffset = OFFSET(java_floatarray,data);
2205                         desc->componentsize = sizeof(float);
2206                         break;
2207
2208                 case 'I': desc->arraytype = ARRAYTYPE_INT;
2209                         desc->dataoffset = OFFSET(java_intarray,data);
2210                         desc->componentsize = sizeof(s4);
2211                         break;
2212
2213                 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2214                         desc->dataoffset = OFFSET(java_longarray,data);
2215                         desc->componentsize = sizeof(s8);
2216                         break;
2217
2218                 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2219                         desc->dataoffset = OFFSET(java_shortarray,data);
2220                         desc->componentsize = sizeof(s2);
2221                         break;
2222
2223                 default:
2224                         panic("Invalid array class name");
2225                 }
2226                 
2227                 desc->componentvftbl = NULL;
2228                 desc->elementvftbl = NULL;
2229                 desc->dimension = 1;
2230                 desc->elementtype = desc->arraytype;
2231         }
2232
2233         return desc;
2234 }
2235
2236
2237 /********************** Function: class_link ***********************************
2238
2239         Tries to link a class. The super class and every implemented interface must
2240         already have been linked. The function calculates the length in bytes that
2241         an instance of this class requires as well as the VTBL for methods and
2242         interface methods.
2243         
2244         If the class can be linked, it is removed from the list 'unlinkedclasses'
2245         and added to 'linkedclasses'. Otherwise, it is moved to the end of
2246         'unlinkedclasses'.
2247
2248         Attention: If cyclical class definitions are encountered, the program gets
2249         into an infinite loop (we'll have to work that out)
2250
2251 *******************************************************************************/
2252
2253 void class_link(classinfo *c)
2254 {
2255         s4 supervftbllength;          /* vftbllegnth of super class               */
2256         s4 vftbllength;               /* vftbllength of current class             */
2257         s4 interfacetablelength;      /* interface table length                   */
2258         classinfo *super = c->super;  /* super class                              */
2259         classinfo *ic, *c2;           /* intermediate class variables             */
2260         vftbl *v;                     /* vftbl of current class                   */
2261         s4 i;                         /* interface/method/field counter           */
2262         arraydescriptor *arraydesc = NULL;  /* descriptor for array classes       */
2263
2264
2265         /*  check if all superclasses are already linked, if not put c at end of
2266             unlinked list and return. Additionally initialize class fields.       */
2267
2268         /*  check interfaces */
2269
2270         for (i = 0; i < c->interfacescount; i++) {
2271                 ic = c->interfaces[i];
2272                 if (!ic->linked) {
2273                         list_remove(&unlinkedclasses, c);
2274                         list_addlast(&unlinkedclasses, c);
2275                         return; 
2276                 }
2277                 if ((ic->flags & ACC_INTERFACE) == 0) {
2278                         dolog("Specified interface is not declared as interface:");
2279                         log_utf(ic->name);
2280                         dolog("in");
2281                         log_utf(c->name);
2282                         panic("Specified interface is not declared as interface");
2283                 }
2284         }
2285         
2286         /*  check super class */
2287
2288         if (super == NULL) {          /* class java.lang.Object */
2289                 c->index = 0;
2290         c->classUsed = USED;     /* Object class is always used CO-RT*/
2291                 c->impldBy = NULL;
2292                 c->instancesize = sizeof(java_objectheader);
2293                 
2294                 vftbllength = supervftbllength = 0;
2295
2296                 c->finalizer = NULL;
2297
2298         } else {
2299                 if (!super->linked) {
2300                         list_remove(&unlinkedclasses, c);
2301                         list_addlast(&unlinkedclasses, c);
2302                         return; 
2303                 }
2304
2305                 if (super->flags & ACC_INTERFACE)
2306                         panic("Interface specified as super class");
2307
2308                 /* handle array classes */
2309                 /* The component class must have been linked already. */
2310                 if (c->name->text[0] == '[')
2311                         if ((arraydesc = class_link_array(c)) == NULL) {
2312                                 list_remove(&unlinkedclasses, c);
2313                                 list_addlast(&unlinkedclasses, c);
2314                                 return; 
2315                         }
2316
2317                 /* Don't allow extending final classes */
2318                 if (super->flags & ACC_FINAL)
2319                         panic("Trying to extend final class");
2320                 
2321                 if (c->flags & ACC_INTERFACE)
2322                         c->index = interfaceindex++;
2323                 else
2324                         c->index = super->index + 1;
2325                 
2326                 c->instancesize = super->instancesize;
2327                 
2328                 vftbllength = supervftbllength = super->vftbl->vftbllength;
2329                 
2330                 c->finalizer = super->finalizer;
2331         }
2332
2333
2334         if (linkverbose) {
2335                 char logtext[MAXLOGTEXT];
2336                 sprintf(logtext, "Linking Class: ");
2337                 utf_sprint(logtext + strlen(logtext), c->name );
2338                 log_text(logtext);
2339         }
2340
2341         /* compute vftbl length */
2342
2343         for (i = 0; i < c->methodscount; i++) {
2344                 methodinfo *m = &(c->methods[i]);
2345                         
2346                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2347                         classinfo *sc = super;
2348                         while (sc) {
2349                                 int j;
2350                                 for (j = 0; j < sc->methodscount; j++) {
2351                                         if (method_canoverwrite(m, &(sc->methods[j]))) {
2352                                                 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2353                                                         goto notfoundvftblindex;
2354                                                 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2355                                                         log_utf(c->name);
2356                                                         log_utf(sc->name);
2357                                                         log_utf(sc->methods[j].name);
2358                                                         log_utf(sc->methods[j].descriptor);
2359                                                         panic("Trying to overwrite final method");
2360                                                 }
2361                                                 m->vftblindex = sc->methods[j].vftblindex;
2362                                                 goto foundvftblindex;
2363                                         }
2364                                 }
2365                                 sc = sc->super;
2366                         }
2367                 notfoundvftblindex:
2368                         m->vftblindex = (vftbllength++);
2369                 foundvftblindex: ;
2370                 }
2371         }       
2372         
2373 #ifdef STATISTICS
2374         count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2375 #endif
2376
2377         /* compute interfacetable length */
2378
2379         interfacetablelength = 0;
2380         c2 = c;
2381         while (c2) {
2382                 for (i = 0; i < c2->interfacescount; i++) {
2383                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2384                         if (h > interfacetablelength)
2385                                 interfacetablelength = h;
2386                 }
2387                 c2 = c2->super;
2388         }
2389
2390         /* allocate virtual function table */
2391
2392         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2393                                                    (vftbllength - 1) + sizeof(methodptr*) *
2394                                                    (interfacetablelength - (interfacetablelength > 0)));
2395         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2396                                   (interfacetablelength > 1));
2397         c->header.vftbl = c->vftbl = v;
2398         v->class = c;
2399         v->vftbllength = vftbllength;
2400         v->interfacetablelength = interfacetablelength;
2401         v->arraydesc = arraydesc;
2402
2403         /* store interface index in vftbl */
2404         if (c->flags & ACC_INTERFACE)
2405                 v->baseval = -(c->index);
2406
2407         /* copy virtual function table of super class */
2408
2409         for (i = 0; i < supervftbllength; i++) 
2410                 v->table[i] = super->vftbl->table[i];
2411         
2412         /* add method stubs into virtual function table */
2413
2414         for (i = 0; i < c->methodscount; i++) {
2415                 methodinfo *m = &(c->methods[i]);
2416                 if (!(m->flags & ACC_STATIC)) {
2417                         v->table[m->vftblindex] = m->stubroutine;
2418                 }
2419         }
2420
2421         /* compute instance size and offset of each field */
2422         
2423         for (i = 0; i < c->fieldscount; i++) {
2424                 s4 dsize;
2425                 fieldinfo *f = &(c->fields[i]);
2426                 
2427                 if (!(f->flags & ACC_STATIC) ) {
2428                         dsize = desc_typesize(f->descriptor);
2429                         c->instancesize = ALIGN(c->instancesize, dsize);
2430                         f->offset = c->instancesize;
2431                         c->instancesize += dsize;
2432                 }
2433         }
2434
2435         /* initialize interfacetable and interfacevftbllength */
2436         
2437         v->interfacevftbllength = MNEW(s4, interfacetablelength);
2438
2439 #ifdef STATISTICS
2440         count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2441 #endif
2442
2443         for (i = 0; i < interfacetablelength; i++) {
2444                 v->interfacevftbllength[i] = 0;
2445                 v->interfacetable[-i] = NULL;
2446         }
2447         
2448         /* add interfaces */
2449         
2450         for (c2 = c; c2 != NULL; c2 = c2->super)
2451                 for (i = 0; i < c2->interfacescount; i++) {
2452                         class_addinterface(c, c2->interfaces[i]);
2453                 }
2454
2455         /* add finalizer method (not for java.lang.Object) */
2456
2457         if (super != NULL) {
2458                 methodinfo *fi;
2459                 static utf *finame = NULL;
2460                 static utf *fidesc = NULL;
2461
2462                 if (finame == NULL)
2463                         finame = utf_finalize;
2464                 if (fidesc == NULL)
2465                         fidesc = utf_fidesc;
2466
2467                 fi = class_findmethod(c, finame, fidesc);
2468                 if (fi != NULL) {
2469                         if (!(fi->flags & ACC_STATIC)) {
2470                                 c->finalizer = fi;
2471                         }
2472                 }
2473         }
2474
2475         /* final tasks */
2476
2477         c->linked = true;       
2478
2479         list_remove(&unlinkedclasses, c);
2480         list_addlast(&linkedclasses, c);
2481 }
2482
2483
2484 /******************* Function: class_freepool **********************************
2485
2486         Frees all resources used by this classes Constant Pool.
2487
2488 *******************************************************************************/
2489
2490 static void class_freecpool (classinfo *c)
2491 {
2492         u4 idx;
2493         u4 tag;
2494         voidptr info;
2495         
2496         for (idx=0; idx < c->cpcount; idx++) {
2497                 tag = c->cptags[idx];
2498                 info = c->cpinfos[idx];
2499                 
2500                 if (info != NULL) {
2501                         switch (tag) {
2502                         case CONSTANT_Fieldref:
2503                         case CONSTANT_Methodref:
2504                         case CONSTANT_InterfaceMethodref:
2505                                 FREE (info, constant_FMIref);
2506                                 break;
2507                         case CONSTANT_Integer:
2508                                 FREE (info, constant_integer);
2509                                 break;
2510                         case CONSTANT_Float:
2511                                 FREE (info, constant_float);
2512                                 break;
2513                         case CONSTANT_Long:
2514                                 FREE (info, constant_long);
2515                                 break;
2516                         case CONSTANT_Double:
2517                                 FREE (info, constant_double);
2518                                 break;
2519                         case CONSTANT_NameAndType:
2520                                 FREE (info, constant_nameandtype);
2521                                 break;
2522                         }
2523                         }
2524                 }
2525
2526         MFREE (c -> cptags,  u1, c -> cpcount);
2527         MFREE (c -> cpinfos, voidptr, c -> cpcount);
2528 }
2529
2530
2531 /*********************** Function: class_free **********************************
2532
2533         Frees all resources used by the class.
2534
2535 *******************************************************************************/
2536
2537 static void class_free(classinfo *c)
2538 {
2539         s4 i;
2540         vftbl *v;
2541                 
2542         class_freecpool(c);
2543
2544         MFREE(c->interfaces, classinfo*, c->interfacescount);
2545
2546         for (i = 0; i < c->fieldscount; i++)
2547                 field_free(&(c->fields[i]));
2548         
2549         for (i = 0; i < c->methodscount; i++)
2550                 method_free(&(c->methods[i]));
2551         MFREE(c->methods, methodinfo, c->methodscount);
2552
2553         if ((v = c->vftbl) != NULL) {
2554                 if (v->arraydesc)
2555                         mem_free(v->arraydesc,sizeof(arraydescriptor));
2556                 
2557                 for (i = 0; i < v->interfacetablelength; i++) {
2558                         MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2559                 }
2560                 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2561
2562                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2563                     sizeof(methodptr*) * (v->interfacetablelength -
2564                                          (v->interfacetablelength > 0));
2565                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2566                                              (v->interfacetablelength > 1));
2567                 mem_free(v, i);
2568         }
2569
2570         if (c->innerclasscount)
2571                 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2572
2573         /*      if (c->classvftbl)
2574                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2575         
2576         GCFREE(c);
2577 }
2578
2579
2580 /************************* Function: class_findfield ***************************
2581         
2582         Searches a 'classinfo' structure for a field having the given name and
2583         type.
2584
2585 *******************************************************************************/
2586
2587 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2588 {
2589         s4 i;
2590         
2591         for (i = 0; i < c->fieldscount; i++) { 
2592                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
2593                         return &(c->fields[i]);                                                         
2594     }
2595
2596         panic("Can not find field given in CONSTANT_Fieldref");
2597
2598         /* keep compiler happy */
2599         return NULL;
2600 }
2601
2602
2603 /****************** Function: class_resolvefield_int ***************************
2604
2605     This is an internally used helper function. Do not use this directly.
2606
2607         Tries to resolve a field having the given name and type.
2608     If the field cannot be resolved, NULL is returned.
2609
2610 *******************************************************************************/
2611
2612 static
2613 fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2614 {
2615         s4 i;
2616         fieldinfo *fi;
2617
2618         /* search for field in class c */
2619         for (i = 0; i < c->fieldscount; i++) { 
2620                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
2621                         return &(c->fields[i]);                                                         
2622     }
2623
2624         /* try superinterfaces recursively */
2625         for (i=0; i<c->interfacescount; ++i) {
2626                 fi = class_resolvefield_int(c->interfaces[i],name,desc);
2627                 if (fi)
2628                         return fi;
2629         }
2630
2631         /* try superclass */
2632         if (c->super)
2633                 return class_resolvefield_int(c->super,name,desc);
2634
2635         /* not found */
2636         return NULL;
2637 }
2638
2639
2640 /********************* Function: class_resolvefield ***************************
2641         
2642         Resolves a reference from REFERER to a field with NAME and DESC in class C.
2643     If the field cannot be resolved this function panics.
2644
2645 *******************************************************************************/
2646
2647 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2648                                                           classinfo *referer)
2649 {
2650         fieldinfo *fi;
2651
2652         /* XXX resolve class c */
2653         /* XXX check access from REFERER to C */
2654         
2655         fi = class_resolvefield_int(c,name,desc);
2656
2657         if (!fi) {
2658                 log_utf(c->name);
2659                 log_utf(name);
2660                 log_utf(desc);
2661                 panic("Cannot find field given in CONSTANT_Fieldref");
2662                 /* XXX should throw NoSuchFieldError */
2663         }
2664
2665         /* XXX check access rights */
2666
2667         return fi;
2668 }
2669
2670
2671 /************************* Function: class_findmethod **************************
2672         
2673         Searches a 'classinfo' structure for a method having the given name and
2674         type and returns the index in the class info structure.
2675         If type is NULL, it is ignored.
2676
2677 *******************************************************************************/
2678
2679 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2680 {
2681         s4 i;
2682         //#define JOWENN_DEBUG1
2683         //#define JOWENN_DEBUG2
2684 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2685         char *buffer;                   
2686         int buffer_len, pos;
2687 #endif
2688
2689 #ifdef JOWENN_DEBUG1
2690
2691         buffer_len = 
2692                 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2693         
2694         buffer = MNEW(char, buffer_len);
2695
2696         strcpy(buffer, "class_findmethod: method:");
2697         utf_sprint(buffer + strlen(buffer), name);
2698         strcpy(buffer + strlen(buffer), ", desc: ");
2699         utf_sprint(buffer + strlen(buffer), desc);
2700         strcpy(buffer + strlen(buffer), ", classname: ");
2701         utf_sprint(buffer + strlen(buffer), c->name);
2702         
2703         log_text(buffer);       
2704
2705         MFREE(buffer, char, buffer_len);
2706 #endif  
2707         for (i = 0; i < c->methodscount; i++) {
2708 #ifdef JOWENN_DEBUG2
2709                 buffer_len = 
2710                         utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2711         
2712                 buffer = MNEW(char, buffer_len);
2713
2714                 strcpy(buffer, "class_findmethod: comparing to method:");
2715                 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2716                 strcpy(buffer + strlen(buffer), ", desc: ");
2717                 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2718         
2719                 log_text(buffer);       
2720
2721                 MFREE(buffer, char, buffer_len);
2722 #endif  
2723                 
2724                 
2725                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2726                                                                                          (c->methods[i].descriptor == desc))) {
2727                         return i;
2728                 }
2729         }
2730
2731 #ifdef JOWENN_DEBUG2    
2732         class_showconstantpool(c);
2733         log_text("class_findmethod: returning NULL");
2734 #endif
2735
2736         return -1;
2737 }
2738
2739
2740 /************************* Function: class_findmethod **************************
2741         
2742         Searches a 'classinfo' structure for a method having the given name and
2743         type.
2744         If type is NULL, it is ignored.
2745
2746 *******************************************************************************/
2747
2748 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2749 {
2750 #if 0
2751         s4 i;
2752 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2753         char *buffer;                   
2754         int buffer_len, pos;
2755 #endif
2756 #ifdef JOWENN_DEBUG1
2757
2758         buffer_len = 
2759                 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2760         
2761         buffer = MNEW(char, buffer_len);
2762
2763         strcpy(buffer, "class_findmethod: method:");
2764         utf_sprint(buffer + strlen(buffer), name);
2765         strcpy(buffer + strlen(buffer), ", desc: ");
2766         utf_sprint(buffer + strlen(buffer), desc);
2767         strcpy(buffer + strlen(buffer), ", classname: ");
2768         utf_sprint(buffer + strlen(buffer), c->name);
2769         
2770         log_text(buffer);       
2771
2772         MFREE(buffer, char, buffer_len);
2773 #endif  
2774         for (i = 0; i < c->methodscount; i++) {
2775 #ifdef JOWENN_DEBUG2
2776                 buffer_len = 
2777                         utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2778         
2779                 buffer = MNEW(char, buffer_len);
2780
2781                 strcpy(buffer, "class_findmethod: comparing to method:");
2782                 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2783                 strcpy(buffer + strlen(buffer), ", desc: ");
2784                 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2785         
2786                 log_text(buffer);       
2787
2788                 MFREE(buffer, char, buffer_len);
2789 #endif  
2790                 
2791                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2792                                                                                          (c->methods[i].descriptor == desc))) {
2793                         return &(c->methods[i]);
2794                 }
2795         }
2796 #ifdef JOWENN_DEBUG2    
2797         class_showconstantpool(c);
2798         log_text("class_findmethod: returning NULL");
2799 #endif
2800         return NULL;
2801 #endif
2802
2803         s4 idx=class_findmethodIndex(c, name, desc);
2804 /*      if (idx==-1) log_text("class_findmethod: method not found");*/
2805         if (idx == -1) return NULL;
2806
2807         return &(c->methods[idx]);
2808 }
2809
2810
2811 /*********************** Function: class_fetchmethod **************************
2812         
2813     like class_findmethod, but aborts with an error if the method is not found
2814
2815 *******************************************************************************/
2816
2817 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2818 {
2819         methodinfo *mi;
2820         mi = class_findmethod(c, name, desc);
2821
2822         if (!mi) {
2823                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2824                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2825                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2826                 panic("Method not found");
2827         }
2828
2829         return mi;
2830 }
2831
2832
2833 /*********************** Function: class_findmethod_w**************************
2834
2835     like class_findmethod, but logs a warning if the method is not found
2836
2837 *******************************************************************************/
2838
2839 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2840 {
2841         methodinfo *mi;
2842         mi = class_findmethod(c, name, desc);
2843
2844         if (!mi) {
2845                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2846                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2847                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2848
2849                 if ( c->flags & ACC_PUBLIC )       log_plain(" PUBLIC ");
2850                 if ( c->flags & ACC_PRIVATE )      log_plain(" PRIVATE ");
2851                 if ( c->flags & ACC_PROTECTED )    log_plain(" PROTECTED ");
2852                 if ( c->flags & ACC_STATIC )       log_plain(" STATIC ");
2853                 if ( c->flags & ACC_FINAL )        log_plain(" FINAL ");
2854                 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2855                 if ( c->flags & ACC_VOLATILE )     log_plain(" VOLATILE ");
2856                 if ( c->flags & ACC_TRANSIENT )    log_plain(" TRANSIENT ");
2857                 if ( c->flags & ACC_NATIVE )       log_plain(" NATIVE ");
2858                 if ( c->flags & ACC_INTERFACE )    log_plain(" INTERFACE ");
2859                 if ( c->flags & ACC_ABSTRACT )     log_plain(" ABSTRACT ");
2860
2861                 log_plain(from); 
2862                 log_plain(" : WARNING: Method not found");log_nl( );
2863         }
2864
2865         return mi;
2866 }
2867
2868
2869 /************************* Function: class_findmethod_approx ******************
2870         
2871         like class_findmethod but ignores the return value when comparing the
2872         descriptor.
2873
2874 *******************************************************************************/
2875
2876 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2877 {
2878         s4 i;
2879
2880         for (i = 0; i < c->methodscount; i++) {
2881                 if (c->methods[i].name == name) {
2882                         utf *meth_descr = c->methods[i].descriptor;
2883                         
2884                         if (desc == NULL) 
2885                                 /* ignore type */
2886                                 return &(c->methods[i]);
2887
2888                         if (desc->blength <= meth_descr->blength) {
2889                                 /* current position in utf text   */
2890                                 char *desc_utf_ptr = desc->text;      
2891                                 char *meth_utf_ptr = meth_descr->text;                                    
2892                                 /* points behind utf strings */
2893                                 char *desc_end = utf_end(desc);         
2894                                 char *meth_end = utf_end(meth_descr);   
2895                                 char ch;
2896
2897                                 /* compare argument types */
2898                                 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2899
2900                                         if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2901                                                 break; /* no match */
2902
2903                                         if (ch == ')')
2904                                                 return &(c->methods[i]);   /* all parameter types equal */
2905                                 }
2906                         }
2907                 }
2908         }
2909
2910         return NULL;
2911 }
2912
2913
2914 /***************** Function: class_resolvemethod_approx ***********************
2915         
2916         Searches a class and every super class for a method (without paying
2917         attention to the return value)
2918
2919 *******************************************************************************/
2920
2921 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2922 {
2923         while (c) {
2924                 /* search for method (ignore returntype) */
2925                 methodinfo *m = class_findmethod_approx(c, name, desc);
2926                 /* method found */
2927                 if (m) return m;
2928                 /* search superclass */
2929                 c = c->super;
2930         }
2931
2932         return NULL;
2933 }
2934
2935
2936 /************************* Function: class_resolvemethod ***********************
2937         
2938         Searches a class and every super class for a method.
2939
2940 *******************************************************************************/
2941
2942 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2943 {
2944         while (c) {
2945                 methodinfo *m = class_findmethod(c, name, desc);
2946                 if (m) return m;
2947                 /* search superclass */
2948                 c = c->super;
2949         }
2950
2951         return NULL;
2952 }
2953
2954
2955 /****************** Function: class_resolveinterfacemethod_int ****************
2956
2957     Internally used helper function. Do not use this directly.
2958
2959 *******************************************************************************/
2960
2961 static
2962 methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
2963 {
2964         methodinfo *mi;
2965         int i;
2966         
2967         mi = class_findmethod(c,name,desc);
2968         if (mi)
2969                 return mi;
2970
2971         /* try the superinterfaces */
2972         for (i=0; i<c->interfacescount; ++i) {
2973                 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
2974                 if (mi)
2975                         return mi;
2976         }
2977         
2978         return NULL;
2979 }
2980
2981 /******************** Function: class_resolveinterfacemethod ******************
2982
2983     Resolves a reference from REFERER to a method with NAME and DESC in
2984     interface C.
2985
2986 *******************************************************************************/
2987
2988 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2989                                                                                  classinfo *referer)
2990 {
2991         methodinfo *mi;
2992
2993         /* XXX resolve class c */
2994         /* XXX check access from REFERER to C */
2995         
2996         if ((c->flags & ACC_INTERFACE) == 0)
2997                 return NULL; /* should throw IncompatibleClassChangeError */
2998
2999         mi = class_resolveinterfacemethod_int(c,name,desc);
3000         if (mi)
3001                 goto found;
3002
3003         /* try class java.lang.Object */
3004         mi = class_findmethod(class_java_lang_Object,name,desc);
3005         if (mi)
3006                 goto found;
3007
3008         return NULL; /* should throw NoSuchMethodError */
3009
3010  found:
3011         return mi;
3012 }
3013
3014 /********************* Function: class_resolveclassmethod *********************
3015         
3016     Resolves a reference from REFERER to a method with NAME and DESC in
3017     class C.
3018
3019 *******************************************************************************/
3020
3021 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3022                                                                          classinfo *referer)
3023 {
3024         methodinfo *mi;
3025         int i;
3026         classinfo *cls;
3027         
3028         /* XXX resolve class c */
3029         /* XXX check access from REFERER to C */
3030         
3031         if ((c->flags & ACC_INTERFACE) != 0)
3032                 return NULL; /* should throw IncompatibleClassChangeError */
3033
3034         /* try class c and its superclasses */
3035         cls = c;
3036         do {
3037                 mi = class_findmethod(cls,name,desc);
3038                 if (mi)
3039                         goto found;
3040         } while ((cls = cls->super) != NULL); /* try the superclass */
3041
3042         /* try the superinterfaces */
3043         for (i=0; i<c->interfacescount; ++i) {
3044                 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3045                 if (mi)
3046                         goto found;
3047         }
3048         
3049         return NULL; /* should throw NoSuchMethodError */
3050
3051  found:
3052         if ((mi->flags & ACC_ABSTRACT) != 0 &&
3053                 (c->flags & ACC_ABSTRACT) == 0)
3054                 return NULL; /* should throw AbstractMethodError */
3055
3056         /* XXX check access rights */
3057
3058         return mi;
3059 }
3060
3061
3062 /************************* Function: class_issubclass **************************
3063
3064         Checks if sub is a descendant of super.
3065         
3066 *******************************************************************************/
3067
3068 bool class_issubclass(classinfo *sub, classinfo *super)
3069 {
3070         for (;;) {
3071                 if (!sub) return false;
3072                 if (sub == super) return true;
3073                 sub = sub->super;
3074         }
3075 }
3076
3077
3078 /****************** Initialization function for classes ******************
3079
3080         In Java, every class can have a static initialization function. This
3081         function has to be called BEFORE calling other methods or accessing static
3082         variables.
3083
3084 *******************************************************************************/
3085
3086 void class_init(classinfo *c)
3087 {
3088         methodinfo *m;
3089         native_stackframeinfo **info;
3090         s4 i;
3091 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3092         int b;
3093 #endif
3094
3095         if (!makeinitializations)
3096                 return;
3097         if (c->initialized)
3098                 return;
3099
3100         c->initialized = true;
3101
3102 #ifdef STATISTICS
3103         count_class_inits++;
3104 #endif
3105
3106         /* initialize super class */
3107         if (c->super) {
3108                 if (initverbose) {
3109                         char logtext[MAXLOGTEXT];
3110                         sprintf(logtext, "Initialize super class ");
3111                         utf_sprint(logtext + strlen(logtext), c->super->name);
3112                         sprintf(logtext + strlen(logtext), " from ");
3113                         utf_sprint(logtext + strlen(logtext), c->name);
3114                         log_text(logtext);
3115                 }
3116                 class_init(c->super);
3117         }
3118
3119         /* initialize interface classes */
3120         for (i = 0; i < c->interfacescount; i++) {
3121                 if (initverbose) {
3122                         char logtext[MAXLOGTEXT];
3123                         sprintf(logtext, "Initialize interface class ");
3124                         utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
3125                         sprintf(logtext + strlen(logtext), " from ");
3126                         utf_sprint(logtext + strlen(logtext), c->name);
3127                         log_text(logtext);
3128                 }
3129                 class_init(c->interfaces[i]);  /* real */
3130         }
3131
3132         m = class_findmethod(c, utf_clinit, utf_fidesc);
3133         if (!m) {
3134                 if (initverbose) {
3135                         char logtext[MAXLOGTEXT];
3136                         sprintf(logtext, "Class ");
3137                         utf_sprint(logtext + strlen(logtext), c->name);
3138                         sprintf(logtext + strlen(logtext), " has no initializer");
3139                         log_text(logtext);
3140                 }
3141                 /*              goto callinitialize;*/
3142                 return;
3143         }
3144
3145         if (!(m->flags & ACC_STATIC))
3146                 panic("Class initializer is not static!");
3147
3148         if (initverbose) {
3149                 char logtext[MAXLOGTEXT];
3150                 sprintf(logtext, "Starting initializer for class: ");
3151                 utf_sprint(logtext + strlen(logtext), c->name);
3152                 log_text(logtext);
3153         }
3154
3155 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3156         b = blockInts;
3157         blockInts = 0;
3158 #endif
3159
3160         /* now call the initializer */
3161         asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3162
3163 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3164         assert(blockInts == 0);
3165         blockInts = b;
3166 #endif
3167
3168         /* we have to throw an exception */
3169         if (*exceptionptr) {
3170                 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
3171                 printf("Caused by: ");
3172                 utf_display((*exceptionptr)->vftbl->class->name);
3173
3174                 /* do we have a detail message? */
3175                 if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
3176                         printf(": ");
3177                         utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
3178                 }
3179
3180                 printf("\n");
3181                 fflush(stdout);
3182                 exit(1);
3183         }
3184
3185         if (initverbose) {
3186                 char logtext[MAXLOGTEXT];
3187                 sprintf(logtext, "Finished initializer for class: ");
3188                 utf_sprint(logtext + strlen(logtext), c->name);
3189                 log_text(logtext);
3190         }
3191
3192         if (c->name == utf_systemclass) {
3193                 /* class java.lang.System requires explicit initialization */
3194
3195                 if (initverbose)
3196                         printf("#### Initializing class System");
3197
3198                 /* find initializing method */
3199                 m = class_findmethod(c,
3200                                                          utf_initsystemclass,
3201                                                          utf_fidesc);
3202
3203                 if (!m) {
3204                         /* no method found */
3205                         /* printf("initializeSystemClass failed"); */
3206                         return;
3207                 }
3208
3209 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3210                 b = blockInts;
3211                 blockInts = 0;
3212 #endif
3213
3214                 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3215
3216 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3217                 assert(blockInts == 0);
3218                 blockInts = b;
3219 #endif
3220
3221                 if (*exceptionptr) {
3222                         printf("#### initializeSystemClass has thrown: ");
3223                         utf_display((*exceptionptr)->vftbl->class->name);
3224                         printf("\n");
3225                         fflush(stdout);
3226                 }
3227         }
3228 }
3229
3230
3231 /********* Function: find_class_method_constant *********/
3232
3233 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)  
3234 {
3235         u4 i;
3236         voidptr e;
3237
3238         for (i=0; i<c->cpcount; i++) {
3239                 
3240                 e = c -> cpinfos [i];
3241                 if (e) {
3242                         
3243                         switch (c -> cptags [i]) {
3244                         case CONSTANT_Methodref:
3245                                 {
3246                                         constant_FMIref *fmi = e;
3247                                         if (       (fmi->class->name == c1)  
3248                                                            && (fmi->name == m1)
3249                                                            && (fmi->descriptor == d1)) {
3250                                         
3251                                                 return i;
3252                                         }
3253                                 }
3254                                 break;
3255
3256                         case CONSTANT_InterfaceMethodref:
3257                                 {
3258                                         constant_FMIref *fmi = e;
3259                                         if (       (fmi->class->name == c1)  
3260                                                            && (fmi->name == m1)
3261                                                            && (fmi->descriptor == d1)) {
3262
3263                                                 return i;
3264                                         }
3265                                 }
3266                                 break;
3267                         }
3268                 }
3269         }
3270
3271         return -1;
3272 }
3273
3274
3275 void class_showconstanti(classinfo *c, int ii) 
3276 {
3277         u4 i = ii;
3278         voidptr e;
3279                 
3280         e = c->cpinfos [i];
3281         printf ("#%d:  ", (int) i);
3282         if (e) {
3283                 switch (c->cptags [i]) {
3284                 case CONSTANT_Class:
3285                         printf("Classreference -> ");
3286                         utf_display(((classinfo*)e)->name);
3287                         break;
3288                                 
3289                 case CONSTANT_Fieldref:
3290                         printf("Fieldref -> "); goto displayFMIi;
3291                 case CONSTANT_Methodref:
3292                         printf("Methodref -> "); goto displayFMIi;
3293                 case CONSTANT_InterfaceMethodref:
3294                         printf("InterfaceMethod -> "); goto displayFMIi;
3295                 displayFMIi:
3296                         {
3297                                 constant_FMIref *fmi = e;
3298                                 utf_display(fmi->class->name);
3299                                 printf(".");
3300                                 utf_display(fmi->name);
3301                                 printf(" ");
3302                                 utf_display(fmi->descriptor);
3303                         }
3304                         break;
3305
3306                 case CONSTANT_String:
3307                         printf("String -> ");
3308                         utf_display(e);
3309                         break;
3310                 case CONSTANT_Integer:
3311                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3312                         break;
3313                 case CONSTANT_Float:
3314                         printf("Float -> %f", ((constant_float*)e)->value);
3315                         break;
3316                 case CONSTANT_Double:
3317                         printf("Double -> %f", ((constant_double*)e)->value);
3318                         break;
3319                 case CONSTANT_Long:
3320                         {
3321                                 u8 v = ((constant_long*)e)->value;
3322 #if U8_AVAILABLE
3323                                 printf("Long -> %ld", (long int) v);
3324 #else
3325                                 printf("Long -> HI: %ld, LO: %ld\n", 
3326                                             (long int) v.high, (long int) v.low);
3327 #endif 
3328                         }
3329                         break;
3330                 case CONSTANT_NameAndType:
3331                         { 
3332                                 constant_nameandtype *cnt = e;
3333                                 printf("NameAndType: ");
3334                                 utf_display(cnt->name);
3335                                 printf(" ");
3336                                 utf_display(cnt->descriptor);
3337                         }
3338                         break;
3339                 case CONSTANT_Utf8:
3340                         printf("Utf8 -> ");
3341                         utf_display(e);
3342                         break;
3343                 default: 
3344                         panic("Invalid type of ConstantPool-Entry");
3345                 }
3346         }
3347         printf("\n");
3348 }
3349
3350
3351 void class_showconstantpool (classinfo *c) 
3352 {
3353         u4 i;
3354         voidptr e;
3355
3356         printf ("---- dump of constant pool ----\n");
3357
3358         for (i=0; i<c->cpcount; i++) {
3359                 printf ("#%d:  ", (int) i);
3360                 
3361                 e = c -> cpinfos [i];
3362                 if (e) {
3363                         
3364                         switch (c -> cptags [i]) {
3365                         case CONSTANT_Class:
3366                                 printf ("Classreference -> ");
3367                                 utf_display ( ((classinfo*)e) -> name );
3368                                 break;
3369                                 
3370                         case CONSTANT_Fieldref:
3371                                 printf ("Fieldref -> "); goto displayFMI;
3372                         case CONSTANT_Methodref:
3373                                 printf ("Methodref -> "); goto displayFMI;
3374                         case CONSTANT_InterfaceMethodref:
3375                                 printf ("InterfaceMethod -> "); goto displayFMI;
3376                         displayFMI:
3377                                 {
3378                                         constant_FMIref *fmi = e;
3379                                         utf_display ( fmi->class->name );
3380                                         printf (".");
3381                                         utf_display ( fmi->name);
3382                                         printf (" ");
3383                                         utf_display ( fmi->descriptor );
3384                                 }
3385                                 break;
3386
3387                         case CONSTANT_String:
3388                                 printf ("String -> ");
3389                                 utf_display (e);
3390                                 break;
3391                         case CONSTANT_Integer:
3392                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3393                                 break;
3394                         case CONSTANT_Float:
3395                                 printf ("Float -> %f", ((constant_float*)e) -> value);
3396                                 break;
3397                         case CONSTANT_Double:
3398                                 printf ("Double -> %f", ((constant_double*)e) -> value);
3399                                 break;
3400                         case CONSTANT_Long:
3401                                 {
3402                                         u8 v = ((constant_long*)e) -> value;
3403 #if U8_AVAILABLE
3404                                         printf ("Long -> %ld", (long int) v);
3405 #else
3406                                         printf ("Long -> HI: %ld, LO: %ld\n", 
3407                                                         (long int) v.high, (long int) v.low);
3408 #endif 
3409                                 }
3410                                 break;
3411                         case CONSTANT_NameAndType:
3412                                 {
3413                                         constant_nameandtype *cnt = e;
3414                                         printf ("NameAndType: ");
3415                                         utf_display (cnt->name);
3416                                         printf (" ");
3417                                         utf_display (cnt->descriptor);
3418                                 }
3419                                 break;
3420                         case CONSTANT_Utf8:
3421                                 printf ("Utf8 -> ");
3422                                 utf_display (e);
3423                                 break;
3424                         default: 
3425                                 panic ("Invalid type of ConstantPool-Entry");
3426                         }
3427                 }
3428
3429                 printf ("\n");
3430         }
3431 }
3432
3433
3434
3435 /********** Function: class_showmethods   (debugging only) *************/
3436
3437 void class_showmethods (classinfo *c)
3438 {
3439         s4 i;
3440         
3441         printf ("--------- Fields and Methods ----------------\n");
3442         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
3443
3444         printf ("This: "); utf_display (c->name); printf ("\n");
3445         if (c->super) {
3446                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3447                 }
3448         printf ("Index: %d\n", c->index);
3449         
3450         printf ("interfaces:\n");       
3451         for (i=0; i < c-> interfacescount; i++) {
3452                 printf ("   ");
3453                 utf_display (c -> interfaces[i] -> name);
3454                 printf (" (%d)\n", c->interfaces[i] -> index);
3455                 }
3456
3457         printf ("fields:\n");           
3458         for (i=0; i < c -> fieldscount; i++) {
3459                 field_display (&(c -> fields[i]));
3460                 }
3461
3462         printf ("methods:\n");
3463         for (i=0; i < c -> methodscount; i++) {
3464                 methodinfo *m = &(c->methods[i]);
3465                 if ( !(m->flags & ACC_STATIC)) 
3466                         printf ("vftblindex: %d   ", m->vftblindex);
3467
3468                 method_display ( m );
3469
3470                 }
3471
3472         printf ("Virtual function table:\n");
3473         for (i=0; i<c->vftbl->vftbllength; i++) {
3474                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
3475                 }
3476
3477 }
3478
3479
3480
3481 /******************************************************************************/
3482 /******************* General functions for the class loader *******************/
3483 /******************************************************************************/
3484
3485 /********************* Function: loader_load ***********************************
3486
3487         Loads and links the class desired class and each class and interface
3488         referenced by it.
3489         Returns: a pointer to this class
3490
3491 *******************************************************************************/
3492
3493 static int loader_load_running = 0;
3494
3495 classinfo *loader_load(utf *topname)
3496 {
3497         classinfo *top;
3498         classinfo *c;
3499         s8 starttime = 0;
3500         s8 stoptime = 0;
3501         classinfo *notlinkable;
3502
3503 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3504         pthread_mutex_lock(&compiler_mutex);
3505 #endif
3506
3507         /* avoid recursive calls */
3508         if (loader_load_running)
3509                 return class_new(topname);
3510
3511         loader_load_running++;
3512         
3513 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3514         intsDisable();
3515 #endif
3516
3517         if (getloadingtime)
3518                 starttime = getcputime();
3519
3520         top = class_new(topname);
3521
3522         /* load classes */
3523         while ((c = list_first(&unloadedclasses))) {
3524                 if (!class_load(c)) {
3525                         if (linkverbose)
3526                                 dolog("Failed to load class");
3527                         list_remove(&unloadedclasses, c);
3528                         top = NULL;
3529                 }
3530         }
3531
3532         /* link classes */
3533         if (linkverbose)
3534                 dolog("Linking...");
3535
3536         /* Added a hack to break infinite linking loops. A better
3537          * linking algorithm would be nice. -Edwin */
3538         notlinkable = NULL;
3539         while ((c = list_first(&unlinkedclasses))) {
3540                 class_link(c);
3541                 if (!c->linked) {
3542                         if (!notlinkable)
3543                                 notlinkable = c;
3544                         else if (notlinkable == c) {
3545                                 /* We tried to link this class for the second time and
3546                                  * no other classes were linked in between, so we are
3547                                  * caught in a loop.
3548                                  */
3549                                 if (linkverbose)
3550                                         dolog("Cannot resolve linking dependencies");
3551                                 top = NULL;
3552                                 if (!*exceptionptr)
3553                                         throw_linkageerror_message(c->name);
3554                                 break;
3555                         }
3556
3557                 } else
3558                         notlinkable = NULL;
3559         }
3560         if (linkverbose)
3561                 dolog("Linking done.");
3562
3563         if (loader_inited)
3564                 loader_compute_subclasses();
3565
3566         /* measure time */
3567         if (getloadingtime) {
3568                 stoptime = getcputime();
3569                 loadingtime += (stoptime - starttime);
3570         }
3571
3572
3573         loader_load_running--;
3574         
3575         /* check if a former loader_load call tried to load/link the class and 
3576            failed. This is needed because the class didn't appear in the 
3577            undloadclasses or unlinkedclasses list during this class. */
3578         if (top) {
3579                 if (!top->loaded) {
3580                         if (linkverbose) dolog("Failed to load class (former call)");
3581                         throw_noclassdeffounderror_message(top->name);
3582                         top = NULL;
3583                         
3584                 } else if (!top->linked) {
3585                         if (linkverbose)
3586                                 dolog("Failed to link class (former call)");
3587                         throw_linkageerror_message(top->name);
3588                         top = NULL;
3589                 }
3590         }
3591
3592 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3593         intsRestore();
3594 #endif
3595         
3596 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3597         pthread_mutex_unlock(&compiler_mutex);
3598 #endif
3599
3600         /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3601         
3602         return top; 
3603 }
3604
3605
3606 /****************** Function: loader_load_sysclass ****************************
3607
3608         Loads and links the class desired class and each class and interface
3609         referenced by it.
3610
3611     The pointer to the classinfo is stored in *top if top != NULL.
3612     The pointer is also returned.
3613
3614     If the class could not be loaded the function aborts with an error.
3615
3616 *******************************************************************************/
3617
3618 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3619 {
3620         classinfo *cls;
3621
3622         if ((cls = loader_load(topname)) == NULL) {
3623                 log_plain("Could not load important system class: ");
3624                 log_plain_utf(topname);
3625                 log_nl();
3626                 panic("Could not load important system class");
3627         }
3628
3629         if (top) *top = cls;
3630
3631         return cls;
3632 }
3633
3634
3635 /**************** function: create_primitive_classes ***************************
3636
3637         create classes representing primitive types 
3638
3639 ********************************************************************************/
3640
3641 void create_primitive_classes()
3642 {  
3643         int i;
3644
3645         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3646                 /* create primitive class */
3647                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3648                 c -> classUsed = NOTUSED; /* not used initially CO-RT */                
3649                 c -> impldBy = NULL;
3650                 
3651                 /* prevent loader from loading primitive class */
3652                 list_remove (&unloadedclasses, c);
3653                 c->loaded=true;
3654                 /* add to unlinked classes */
3655                 list_addlast (&unlinkedclasses, c);             
3656 /*JOWENN primitive types don't have objects as super class              c -> super = class_java_lang_Object; */
3657                 class_link (c);
3658
3659                 primitivetype_table[i].class_primitive = c;
3660
3661                 /* create class for wrapping the primitive type */
3662                 primitivetype_table[i].class_wrap =
3663                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
3664                 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3665                 primitivetype_table[i].class_wrap  -> impldBy = NULL;
3666
3667                 /* create the primitive array class */
3668                 if (primitivetype_table[i].arrayname) {
3669                         c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3670                         primitivetype_table[i].arrayclass = c;
3671                         c->loaded=true;
3672                         if (!c->linked) class_link(c);
3673                         primitivetype_table[i].arrayvftbl = c->vftbl;
3674                 }
3675         }
3676 }
3677
3678 /**************** function: class_primitive_from_sig ***************************
3679
3680         return the primitive class indicated by the given signature character
3681
3682     If the descriptor does not indicate a valid primitive type the
3683     return value is NULL.
3684
3685 ********************************************************************************/
3686
3687 classinfo *class_primitive_from_sig(char sig)
3688 {
3689         switch (sig) {
3690           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3691           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3692           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3693           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3694           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3695           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3696           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3697           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3698           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3699         }
3700         return NULL;
3701 }
3702
3703 /****************** function: class_from_descriptor ****************************
3704
3705     return the class indicated by the given descriptor
3706
3707     utf_ptr....first character of descriptor
3708     end_ptr....first character after the end of the string
3709     next.......if non-NULL, *next is set to the first character after
3710                the descriptor. (Undefined if an error occurs.)
3711
3712     mode.......a combination (binary or) of the following flags:
3713
3714                (Flags marked with * are the default settings.)
3715
3716                What to do if a reference type descriptor is parsed successfully:
3717
3718                    CLASSLOAD_SKIP...skip it and return something != NULL
3719                                  * CLASSLOAD_NEW....get classinfo * via class_new
3720                    CLASSLOAD_LOAD...get classinfo * via loader_load
3721
3722                How to handle primitive types:
3723
3724                              * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3725                    CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3726
3727                How to handle "V" descriptors:
3728
3729                              * CLASSLOAD_VOID.....handle it like other primitive types
3730                    CLASSLOAD_NOVOID...treat it as an error
3731
3732                How to deal with extra characters after the end of the
3733                descriptor:
3734
3735                              * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3736                    CLASSLOAD_CHECKEND.....treat them as an error
3737
3738                How to deal with errors:
3739
3740                              * CLASSLOAD_PANIC....abort execution with an error message
3741                    CLASSLOAD_NOPANIC..return NULL on error
3742
3743 ********************************************************************************/
3744
3745 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3746                                                                  char **next, int mode)
3747 {
3748         char *start = utf_ptr;
3749         bool error = false;
3750         utf *name;
3751
3752         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3753
3754         if (mode & CLASSLOAD_CHECKEND)
3755                 error |= (utf_ptr != end_ptr);
3756         
3757         if (!error) {
3758                 if (next) *next = utf_ptr;
3759                 
3760                 switch (*start) {
3761                   case 'V':
3762                           if (mode & CLASSLOAD_NOVOID)
3763                                   break;
3764                           /* FALLTHROUGH! */
3765                   case 'I':
3766                   case 'J':
3767                   case 'F':
3768                   case 'D':
3769                   case 'B':
3770                   case 'C':
3771                   case 'S':
3772                   case 'Z':
3773                           return (mode & CLASSLOAD_NULLPRIMITIVE)
3774                                   ? NULL
3775                                   : class_primitive_from_sig(*start);
3776                           
3777                   case 'L':
3778                           start++;
3779                           utf_ptr--;
3780                           /* FALLTHROUGH! */
3781                   case '[':
3782                           if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3783                           name = utf_new(start, utf_ptr - start);
3784                           return (mode & CLASSLOAD_LOAD)
3785                                   ? loader_load(name) : class_new(name); /* XXX handle errors */
3786                 }
3787         }
3788
3789         /* An error occurred */
3790         if (mode & CLASSLOAD_NOPANIC)
3791                 return NULL;
3792
3793         log_plain("Invalid descriptor at beginning of '");
3794         log_plain_utf(utf_new(start, end_ptr - start));
3795         log_plain("'");
3796         log_nl();
3797                                                   
3798         panic("Invalid descriptor");
3799
3800         /* keep compiler happy */
3801         return NULL;
3802 }
3803
3804
3805 /******************* function: type_from_descriptor ****************************
3806
3807     return the basic type indicated by the given descriptor
3808
3809     This function parses a descriptor and returns its basic type as
3810     TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3811
3812     cls...if non-NULL the referenced variable is set to the classinfo *
3813           returned by class_from_descriptor.
3814
3815     For documentation of the arguments utf_ptr, end_ptr, next and mode
3816     see class_from_descriptor. The only difference is that
3817     type_from_descriptor always uses CLASSLOAD_PANIC.
3818
3819 ********************************************************************************/
3820
3821 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3822                                                  char **next, int mode)
3823 {
3824         classinfo *mycls;
3825         if (!cls) cls = &mycls;
3826         *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3827         switch (*utf_ptr) {
3828           case 'B': 
3829           case 'C':
3830           case 'I':
3831           case 'S':  
3832           case 'Z':
3833                   return TYPE_INT;
3834           case 'D':
3835                   return TYPE_DOUBLE;
3836           case 'F':
3837                   return TYPE_FLOAT;
3838           case 'J':
3839                   return TYPE_LONG;
3840           case 'V':
3841                   return TYPE_VOID;
3842         }
3843         return TYPE_ADDRESS;
3844 }
3845
3846
3847
3848 /*************** function: create_system_exception_classes *******************************
3849
3850         create system exception classes needed by default 
3851
3852 ********************************************************************************/
3853
3854 static void create_system_exception_classes()
3855 {
3856         if (verbose)
3857                 log_text("loader_init:  create_system_exception_classs: loader_load: java/lang/ClassCastException");
3858
3859         loader_load_sysclass(&class_java_lang_ClassCastException,
3860                                                  utf_new_char("java/lang/ClassCastException"));
3861         loader_load_sysclass(&class_java_lang_NullPointerException,
3862                                                  utf_new_char("java/lang/NullPointerException"));
3863         loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3864                                                  utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
3865         loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3866                                                  utf_new_char("java/lang/NegativeArraySizeException"));
3867         loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3868                                                  utf_new_char("java/lang/OutOfMemoryError"));
3869         loader_load_sysclass(&class_java_lang_ArrayStoreException,
3870                                                  utf_new_char("java/lang/ArrayStoreException"));
3871         loader_load_sysclass(&class_java_lang_ArithmeticException,
3872                                                  utf_new_char("java/lang/ArithmeticException"));
3873         loader_load_sysclass(&class_java_lang_ThreadDeath,
3874                                                  utf_new_char("java/lang/ThreadDeath"));
3875 }
3876
3877
3878 /*************** function: create_system_exception_classes *******************************
3879
3880         create system exception proto classes needed by default 
3881
3882 ********************************************************************************/
3883
3884 static void create_system_exception_proto_classes()
3885 {
3886
3887         if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3888         proto_java_lang_ClassCastException =
3889                 builtin_new(class_java_lang_ClassCastException);
3890
3891         if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3892
3893         proto_java_lang_NullPointerException =
3894                 builtin_new(class_java_lang_NullPointerException);
3895         if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3896
3897         proto_java_lang_ArrayIndexOutOfBoundsException =
3898                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3899
3900         proto_java_lang_NegativeArraySizeException =
3901                 builtin_new(class_java_lang_NegativeArraySizeException);
3902
3903         proto_java_lang_OutOfMemoryError =
3904                 builtin_new(class_java_lang_OutOfMemoryError);
3905
3906         proto_java_lang_ArithmeticException =
3907                 builtin_new(class_java_lang_ArithmeticException);
3908
3909         proto_java_lang_ArrayStoreException =
3910                 builtin_new(class_java_lang_ArrayStoreException);
3911
3912         proto_java_lang_ThreadDeath =
3913                 builtin_new(class_java_lang_ThreadDeath);
3914
3915
3916 }
3917
3918
3919
3920 /*************** function: create_pseudo_classes *******************************
3921
3922         create pseudo classes used by the typechecker
3923
3924 ********************************************************************************/
3925
3926 static void create_pseudo_classes()
3927 {
3928     /* pseudo class for Arraystubs (extends java.lang.Object) */
3929     
3930     pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3931     list_remove(&unloadedclasses, pseudo_class_Arraystub);
3932
3933     pseudo_class_Arraystub->super = class_java_lang_Object;
3934     pseudo_class_Arraystub->interfacescount = 2;
3935     pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3936     pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3937     pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3938
3939     list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3940     class_link(pseudo_class_Arraystub);
3941
3942         pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3943
3944     /* pseudo class representing the null type */
3945     
3946     pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3947     list_remove(&unloadedclasses, pseudo_class_Null);
3948
3949     pseudo_class_Null->super = class_java_lang_Object;
3950
3951     list_addlast(&unlinkedclasses, pseudo_class_Null);
3952     class_link(pseudo_class_Null);      
3953
3954     /* pseudo class representing new uninitialized objects */
3955     
3956     pseudo_class_New = class_new(utf_new_char("$NEW$"));
3957     list_remove(&unloadedclasses, pseudo_class_New);
3958
3959     pseudo_class_New->super = class_java_lang_Object;
3960
3961     list_addlast(&unlinkedclasses, pseudo_class_New);
3962     class_link(pseudo_class_New);       
3963 }
3964
3965
3966 /********************** Function: loader_init **********************************
3967
3968         Initializes all lists and loads all classes required for the system or the
3969         compiler.
3970
3971 *******************************************************************************/
3972  
3973 void loader_init(u1 *stackbottom)
3974 {
3975         interfaceindex = 0;
3976         
3977         list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3978         list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3979         list_init(&linkedclasses, OFFSET(classinfo, listnode));
3980
3981         /* create utf-symbols for pointer comparison of frequently used strings */
3982         utf_innerclasses    = utf_new_char("InnerClasses");
3983         utf_constantvalue   = utf_new_char("ConstantValue");
3984         utf_code                = utf_new_char("Code");
3985         utf_exceptions          = utf_new_char("Exceptions");
3986         utf_linenumbertable     = utf_new_char("LineNumberTable");
3987         utf_sourcefile          = utf_new_char("SourceFile");
3988         utf_finalize        = utf_new_char("finalize");
3989         utf_fidesc              = utf_new_char("()V");
3990         utf_init                = utf_new_char("<init>");
3991         utf_clinit              = utf_new_char("<clinit>");
3992         utf_initsystemclass = utf_new_char("initializeSystemClass");
3993         utf_systemclass     = utf_new_char("java/lang/System");
3994         utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
3995         utf_initialize      = utf_new_char("initialize");
3996         utf_initializedesc  = utf_new_char("(I)V");
3997
3998         utf_vmclass         = utf_new_char("java/lang/VMClass");
3999         utf_java_lang_Object= utf_new_char("java/lang/Object");
4000
4001         array_packagename   = utf_new_char("<the array package>");
4002
4003         /* create some important classes */
4004         /* These classes have to be created now because the classinfo
4005          * pointers are used in the loading code.
4006          */
4007         class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
4008         class_java_lang_String = class_new(utf_new_char("java/lang/String"));
4009         class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
4010         class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
4011
4012         if (verbose) log_text("loader_init: java/lang/Object");
4013         /* load the classes which were created above */
4014         loader_load_sysclass(NULL, class_java_lang_Object->name);
4015
4016         loader_inited = 1; /*JOWENN*/
4017
4018         loader_load_sysclass(&class_java_lang_Throwable,
4019                                                  utf_new_char("java/lang/Throwable"));
4020
4021         create_system_exception_classes();
4022
4023         /* create classes representing primitive types */
4024         create_primitive_classes();
4025
4026         /* create classes used by the typechecker */
4027         create_pseudo_classes();
4028
4029         /* correct vftbl-entries (retarded loading of class java/lang/String) */
4030         stringtable_update();
4031
4032 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4033         if (stackbottom!=0)
4034                 initLocks();
4035 #endif
4036         create_system_exception_proto_classes();
4037
4038         loader_inited = 1;
4039 }
4040
4041
4042 /********************* Function: loader_initclasses ****************************
4043
4044         Initializes all loaded but uninitialized classes
4045
4046 *******************************************************************************/
4047
4048 #if 0
4049 /* XXX TWISTI: i think we do not need this */
4050 void loader_initclasses ()
4051 {
4052         classinfo *c;
4053         
4054 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4055         pthread_mutex_lock(&compiler_mutex);
4056 #endif
4057
4058         intsDisable();                     /* schani */
4059
4060         if (makeinitializations) {
4061                 c = list_first(&linkedclasses);
4062                 while (c) {
4063                         class_init(c);
4064                         c = list_next(&linkedclasses, c);
4065                 }
4066         }
4067
4068         intsRestore();                      /* schani */
4069         
4070 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4071         pthread_mutex_unlock(&compiler_mutex);
4072 #endif
4073 }
4074 #endif
4075
4076
4077 static void loader_compute_class_values(classinfo *c)
4078 {
4079         classinfo *subs;
4080
4081         c->vftbl->baseval = ++classvalue;
4082
4083         subs = c->sub;
4084         while (subs != NULL) {
4085                 loader_compute_class_values(subs);
4086                 subs = subs->nextsub;
4087         }
4088         c->vftbl->diffval = classvalue - c->vftbl->baseval;
4089         
4090 /*      
4091         {
4092         int i;
4093         for (i = 0; i < c->index; i++)
4094                 printf(" ");
4095         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
4096         utf_display(c->name);
4097         printf("\n");
4098         }
4099 */      
4100 }
4101
4102
4103 void loader_compute_subclasses()
4104 {
4105         classinfo *c;
4106         
4107 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4108         intsDisable();                     /* schani */
4109 #endif
4110
4111         c = list_first(&linkedclasses);
4112         while (c) {
4113                 if (!(c->flags & ACC_INTERFACE)) {
4114                         c->nextsub = 0;
4115                         c->sub = 0;
4116                 }
4117                 c = list_next(&linkedclasses, c);
4118         }
4119
4120         c = list_first(&linkedclasses);
4121         while (c) {
4122                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4123                         c->nextsub = c->super->sub;
4124                         c->super->sub = c;
4125                 }
4126                 c = list_next(&linkedclasses, c);
4127         }
4128
4129         classvalue = 0;
4130 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4131         cast_lock();
4132 #endif
4133         loader_compute_class_values(class_java_lang_Object);
4134 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4135         cast_unlock();
4136 #endif
4137
4138 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4139         intsRestore();                      /* schani */
4140 #endif
4141 }
4142
4143
4144 /******************** function classloader_buffer ******************************
4145  
4146     sets buffer for reading classdata
4147
4148 *******************************************************************************/
4149
4150 void classload_buffer(u1 *buf, int len)
4151 {
4152         classbuffer      = buf;
4153         classbuffer_size = len;
4154         classbuf_pos     = buf - 1;
4155 }
4156
4157
4158 /******************** Function: loader_close ***********************************
4159
4160         Frees all resources
4161         
4162 *******************************************************************************/
4163
4164 void loader_close()
4165 {
4166         classinfo *c;
4167
4168         while ((c = list_first(&unloadedclasses))) {
4169                 list_remove(&unloadedclasses, c);
4170 /*              class_free(c); */
4171         }
4172         while ((c = list_first(&unlinkedclasses))) {
4173                 list_remove(&unlinkedclasses, c);
4174 /*              class_free(c); */
4175         }
4176         while ((c = list_first(&linkedclasses))) {
4177                 list_remove(&linkedclasses, c);
4178 /*              class_free(c); */
4179         }
4180 }
4181
4182
4183 /*
4184  * These are local overrides for various environment variables in Emacs.
4185  * Please do not remove this and leave it at the end of the file, where
4186  * Emacs will automagically detect them.
4187  * ---------------------------------------------------------------------
4188  * Local variables:
4189  * mode: c
4190  * indent-tabs-mode: t
4191  * c-basic-offset: 4
4192  * tab-width: 4
4193  * End:
4194  */