Native threads almost working
[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 991 2004-03-29 11:22:34Z stefan $
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         s4 i;
3090 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3091         int b;
3092 #endif
3093
3094         if (!makeinitializations)
3095                 return;
3096         if (c->initialized)
3097                 return;
3098
3099         c->initialized = true;
3100
3101 #ifdef STATISTICS
3102         count_class_inits++;
3103 #endif
3104
3105         /* initialize super class */
3106         if (c->super) {
3107                 if (initverbose) {
3108                         char logtext[MAXLOGTEXT];
3109                         sprintf(logtext, "Initialize super class ");
3110                         utf_sprint(logtext + strlen(logtext), c->super->name);
3111                         sprintf(logtext + strlen(logtext), " from ");
3112                         utf_sprint(logtext + strlen(logtext), c->name);
3113                         log_text(logtext);
3114                 }
3115                 class_init(c->super);
3116         }
3117
3118         /* initialize interface classes */
3119         for (i = 0; i < c->interfacescount; i++) {
3120                 if (initverbose) {
3121                         char logtext[MAXLOGTEXT];
3122                         sprintf(logtext, "Initialize interface class ");
3123                         utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
3124                         sprintf(logtext + strlen(logtext), " from ");
3125                         utf_sprint(logtext + strlen(logtext), c->name);
3126                         log_text(logtext);
3127                 }
3128                 class_init(c->interfaces[i]);  /* real */
3129         }
3130
3131         m = class_findmethod(c, utf_clinit, utf_fidesc);
3132         if (!m) {
3133                 if (initverbose) {
3134                         char logtext[MAXLOGTEXT];
3135                         sprintf(logtext, "Class ");
3136                         utf_sprint(logtext + strlen(logtext), c->name);
3137                         sprintf(logtext + strlen(logtext), " has no initializer");
3138                         log_text(logtext);
3139                 }
3140                 /*              goto callinitialize;*/
3141                 return;
3142         }
3143
3144         if (!(m->flags & ACC_STATIC))
3145                 panic("Class initializer is not static!");
3146
3147         if (initverbose) {
3148                 char logtext[MAXLOGTEXT];
3149                 sprintf(logtext, "Starting initializer for class: ");
3150                 utf_sprint(logtext + strlen(logtext), c->name);
3151                 log_text(logtext);
3152         }
3153
3154 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3155         b = blockInts;
3156         blockInts = 0;
3157 #endif
3158
3159         /* now call the initializer */
3160         asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3161
3162 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3163         assert(blockInts == 0);
3164         blockInts = b;
3165 #endif
3166
3167         /* we have to throw an exception */
3168         if (*exceptionptr) {
3169                 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
3170                 printf("Caused by: ");
3171                 utf_display((*exceptionptr)->vftbl->class->name);
3172
3173                 /* do we have a detail message? */
3174                 if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
3175                         printf(": ");
3176                         utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
3177                 }
3178
3179                 printf("\n");
3180                 fflush(stdout);
3181                 exit(1);
3182         }
3183
3184         if (initverbose) {
3185                 char logtext[MAXLOGTEXT];
3186                 sprintf(logtext, "Finished initializer for class: ");
3187                 utf_sprint(logtext + strlen(logtext), c->name);
3188                 log_text(logtext);
3189         }
3190
3191         if (c->name == utf_systemclass) {
3192                 /* class java.lang.System requires explicit initialization */
3193
3194                 if (initverbose)
3195                         printf("#### Initializing class System");
3196
3197                 /* find initializing method */
3198                 m = class_findmethod(c,
3199                                                          utf_initsystemclass,
3200                                                          utf_fidesc);
3201
3202                 if (!m) {
3203                         /* no method found */
3204                         /* printf("initializeSystemClass failed"); */
3205                         return;
3206                 }
3207
3208 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3209                 b = blockInts;
3210                 blockInts = 0;
3211 #endif
3212
3213                 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3214
3215 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3216                 assert(blockInts == 0);
3217                 blockInts = b;
3218 #endif
3219
3220                 if (*exceptionptr) {
3221                         printf("#### initializeSystemClass has thrown: ");
3222                         utf_display((*exceptionptr)->vftbl->class->name);
3223                         printf("\n");
3224                         fflush(stdout);
3225                 }
3226         }
3227 }
3228
3229
3230 /********* Function: find_class_method_constant *********/
3231
3232 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)  
3233 {
3234         u4 i;
3235         voidptr e;
3236
3237         for (i=0; i<c->cpcount; i++) {
3238                 
3239                 e = c -> cpinfos [i];
3240                 if (e) {
3241                         
3242                         switch (c -> cptags [i]) {
3243                         case CONSTANT_Methodref:
3244                                 {
3245                                         constant_FMIref *fmi = e;
3246                                         if (       (fmi->class->name == c1)  
3247                                                            && (fmi->name == m1)
3248                                                            && (fmi->descriptor == d1)) {
3249                                         
3250                                                 return i;
3251                                         }
3252                                 }
3253                                 break;
3254
3255                         case CONSTANT_InterfaceMethodref:
3256                                 {
3257                                         constant_FMIref *fmi = e;
3258                                         if (       (fmi->class->name == c1)  
3259                                                            && (fmi->name == m1)
3260                                                            && (fmi->descriptor == d1)) {
3261
3262                                                 return i;
3263                                         }
3264                                 }
3265                                 break;
3266                         }
3267                 }
3268         }
3269
3270         return -1;
3271 }
3272
3273
3274 void class_showconstanti(classinfo *c, int ii) 
3275 {
3276         u4 i = ii;
3277         voidptr e;
3278                 
3279         e = c->cpinfos [i];
3280         printf ("#%d:  ", (int) i);
3281         if (e) {
3282                 switch (c->cptags [i]) {
3283                 case CONSTANT_Class:
3284                         printf("Classreference -> ");
3285                         utf_display(((classinfo*)e)->name);
3286                         break;
3287                                 
3288                 case CONSTANT_Fieldref:
3289                         printf("Fieldref -> "); goto displayFMIi;
3290                 case CONSTANT_Methodref:
3291                         printf("Methodref -> "); goto displayFMIi;
3292                 case CONSTANT_InterfaceMethodref:
3293                         printf("InterfaceMethod -> "); goto displayFMIi;
3294                 displayFMIi:
3295                         {
3296                                 constant_FMIref *fmi = e;
3297                                 utf_display(fmi->class->name);
3298                                 printf(".");
3299                                 utf_display(fmi->name);
3300                                 printf(" ");
3301                                 utf_display(fmi->descriptor);
3302                         }
3303                         break;
3304
3305                 case CONSTANT_String:
3306                         printf("String -> ");
3307                         utf_display(e);
3308                         break;
3309                 case CONSTANT_Integer:
3310                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3311                         break;
3312                 case CONSTANT_Float:
3313                         printf("Float -> %f", ((constant_float*)e)->value);
3314                         break;
3315                 case CONSTANT_Double:
3316                         printf("Double -> %f", ((constant_double*)e)->value);
3317                         break;
3318                 case CONSTANT_Long:
3319                         {
3320                                 u8 v = ((constant_long*)e)->value;
3321 #if U8_AVAILABLE
3322                                 printf("Long -> %ld", (long int) v);
3323 #else
3324                                 printf("Long -> HI: %ld, LO: %ld\n", 
3325                                             (long int) v.high, (long int) v.low);
3326 #endif 
3327                         }
3328                         break;
3329                 case CONSTANT_NameAndType:
3330                         { 
3331                                 constant_nameandtype *cnt = e;
3332                                 printf("NameAndType: ");
3333                                 utf_display(cnt->name);
3334                                 printf(" ");
3335                                 utf_display(cnt->descriptor);
3336                         }
3337                         break;
3338                 case CONSTANT_Utf8:
3339                         printf("Utf8 -> ");
3340                         utf_display(e);
3341                         break;
3342                 default: 
3343                         panic("Invalid type of ConstantPool-Entry");
3344                 }
3345         }
3346         printf("\n");
3347 }
3348
3349
3350 void class_showconstantpool (classinfo *c) 
3351 {
3352         u4 i;
3353         voidptr e;
3354
3355         printf ("---- dump of constant pool ----\n");
3356
3357         for (i=0; i<c->cpcount; i++) {
3358                 printf ("#%d:  ", (int) i);
3359                 
3360                 e = c -> cpinfos [i];
3361                 if (e) {
3362                         
3363                         switch (c -> cptags [i]) {
3364                         case CONSTANT_Class:
3365                                 printf ("Classreference -> ");
3366                                 utf_display ( ((classinfo*)e) -> name );
3367                                 break;
3368                                 
3369                         case CONSTANT_Fieldref:
3370                                 printf ("Fieldref -> "); goto displayFMI;
3371                         case CONSTANT_Methodref:
3372                                 printf ("Methodref -> "); goto displayFMI;
3373                         case CONSTANT_InterfaceMethodref:
3374                                 printf ("InterfaceMethod -> "); goto displayFMI;
3375                         displayFMI:
3376                                 {
3377                                         constant_FMIref *fmi = e;
3378                                         utf_display ( fmi->class->name );
3379                                         printf (".");
3380                                         utf_display ( fmi->name);
3381                                         printf (" ");
3382                                         utf_display ( fmi->descriptor );
3383                                 }
3384                                 break;
3385
3386                         case CONSTANT_String:
3387                                 printf ("String -> ");
3388                                 utf_display (e);
3389                                 break;
3390                         case CONSTANT_Integer:
3391                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3392                                 break;
3393                         case CONSTANT_Float:
3394                                 printf ("Float -> %f", ((constant_float*)e) -> value);
3395                                 break;
3396                         case CONSTANT_Double:
3397                                 printf ("Double -> %f", ((constant_double*)e) -> value);
3398                                 break;
3399                         case CONSTANT_Long:
3400                                 {
3401                                         u8 v = ((constant_long*)e) -> value;
3402 #if U8_AVAILABLE
3403                                         printf ("Long -> %ld", (long int) v);
3404 #else
3405                                         printf ("Long -> HI: %ld, LO: %ld\n", 
3406                                                         (long int) v.high, (long int) v.low);
3407 #endif 
3408                                 }
3409                                 break;
3410                         case CONSTANT_NameAndType:
3411                                 {
3412                                         constant_nameandtype *cnt = e;
3413                                         printf ("NameAndType: ");
3414                                         utf_display (cnt->name);
3415                                         printf (" ");
3416                                         utf_display (cnt->descriptor);
3417                                 }
3418                                 break;
3419                         case CONSTANT_Utf8:
3420                                 printf ("Utf8 -> ");
3421                                 utf_display (e);
3422                                 break;
3423                         default: 
3424                                 panic ("Invalid type of ConstantPool-Entry");
3425                         }
3426                 }
3427
3428                 printf ("\n");
3429         }
3430 }
3431
3432
3433
3434 /********** Function: class_showmethods   (debugging only) *************/
3435
3436 void class_showmethods (classinfo *c)
3437 {
3438         s4 i;
3439         
3440         printf ("--------- Fields and Methods ----------------\n");
3441         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
3442
3443         printf ("This: "); utf_display (c->name); printf ("\n");
3444         if (c->super) {
3445                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3446                 }
3447         printf ("Index: %d\n", c->index);
3448         
3449         printf ("interfaces:\n");       
3450         for (i=0; i < c-> interfacescount; i++) {
3451                 printf ("   ");
3452                 utf_display (c -> interfaces[i] -> name);
3453                 printf (" (%d)\n", c->interfaces[i] -> index);
3454                 }
3455
3456         printf ("fields:\n");           
3457         for (i=0; i < c -> fieldscount; i++) {
3458                 field_display (&(c -> fields[i]));
3459                 }
3460
3461         printf ("methods:\n");
3462         for (i=0; i < c -> methodscount; i++) {
3463                 methodinfo *m = &(c->methods[i]);
3464                 if ( !(m->flags & ACC_STATIC)) 
3465                         printf ("vftblindex: %d   ", m->vftblindex);
3466
3467                 method_display ( m );
3468
3469                 }
3470
3471         printf ("Virtual function table:\n");
3472         for (i=0; i<c->vftbl->vftbllength; i++) {
3473                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
3474                 }
3475
3476 }
3477
3478
3479
3480 /******************************************************************************/
3481 /******************* General functions for the class loader *******************/
3482 /******************************************************************************/
3483
3484 /********************* Function: loader_load ***********************************
3485
3486         Loads and links the class desired class and each class and interface
3487         referenced by it.
3488         Returns: a pointer to this class
3489
3490 *******************************************************************************/
3491
3492 static int loader_load_running = 0;
3493
3494 classinfo *loader_load(utf *topname)
3495 {
3496         classinfo *top;
3497         classinfo *c;
3498         s8 starttime = 0;
3499         s8 stoptime = 0;
3500         classinfo *notlinkable;
3501
3502         /* avoid recursive calls */
3503         if (loader_load_running)
3504                 return class_new(topname);
3505
3506 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3507         compiler_lock();
3508 #endif
3509
3510         loader_load_running++;
3511         
3512 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3513         intsDisable();
3514 #endif
3515
3516         if (getloadingtime)
3517                 starttime = getcputime();
3518
3519         top = class_new(topname);
3520
3521         /* load classes */
3522         while ((c = list_first(&unloadedclasses))) {
3523                 if (!class_load(c)) {
3524                         if (linkverbose)
3525                                 dolog("Failed to load class");
3526                         list_remove(&unloadedclasses, c);
3527                         top = NULL;
3528                 }
3529         }
3530
3531         /* link classes */
3532         if (linkverbose)
3533                 dolog("Linking...");
3534
3535         /* Added a hack to break infinite linking loops. A better
3536          * linking algorithm would be nice. -Edwin */
3537         notlinkable = NULL;
3538         while ((c = list_first(&unlinkedclasses))) {
3539                 class_link(c);
3540                 if (!c->linked) {
3541                         if (!notlinkable)
3542                                 notlinkable = c;
3543                         else if (notlinkable == c) {
3544                                 /* We tried to link this class for the second time and
3545                                  * no other classes were linked in between, so we are
3546                                  * caught in a loop.
3547                                  */
3548                                 if (linkverbose)
3549                                         dolog("Cannot resolve linking dependencies");
3550                                 top = NULL;
3551                                 if (!*exceptionptr)
3552                                         throw_linkageerror_message(c->name);
3553                                 break;
3554                         }
3555
3556                 } else
3557                         notlinkable = NULL;
3558         }
3559         if (linkverbose)
3560                 dolog("Linking done.");
3561
3562         if (loader_inited)
3563                 loader_compute_subclasses();
3564
3565         /* measure time */
3566         if (getloadingtime) {
3567                 stoptime = getcputime();
3568                 loadingtime += (stoptime - starttime);
3569         }
3570
3571
3572         loader_load_running--;
3573         
3574         /* check if a former loader_load call tried to load/link the class and 
3575            failed. This is needed because the class didn't appear in the 
3576            undloadclasses or unlinkedclasses list during this class. */
3577         if (top) {
3578                 if (!top->loaded) {
3579                         if (linkverbose) dolog("Failed to load class (former call)");
3580                         throw_noclassdeffounderror_message(top->name);
3581                         top = NULL;
3582                         
3583                 } else if (!top->linked) {
3584                         if (linkverbose)
3585                                 dolog("Failed to link class (former call)");
3586                         throw_linkageerror_message(top->name);
3587                         top = NULL;
3588                 }
3589         }
3590
3591 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3592         intsRestore();
3593 #endif
3594         
3595 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3596         compiler_unlock();
3597 #endif
3598
3599         /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3600         
3601         return top; 
3602 }
3603
3604
3605 /****************** Function: loader_load_sysclass ****************************
3606
3607         Loads and links the class desired class and each class and interface
3608         referenced by it.
3609
3610     The pointer to the classinfo is stored in *top if top != NULL.
3611     The pointer is also returned.
3612
3613     If the class could not be loaded the function aborts with an error.
3614
3615 *******************************************************************************/
3616
3617 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3618 {
3619         classinfo *cls;
3620
3621         if ((cls = loader_load(topname)) == NULL) {
3622                 log_plain("Could not load important system class: ");
3623                 log_plain_utf(topname);
3624                 log_nl();
3625                 panic("Could not load important system class");
3626         }
3627
3628         if (top) *top = cls;
3629
3630         return cls;
3631 }
3632
3633
3634 /**************** function: create_primitive_classes ***************************
3635
3636         create classes representing primitive types 
3637
3638 ********************************************************************************/
3639
3640 void create_primitive_classes()
3641 {  
3642         int i;
3643
3644         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3645                 /* create primitive class */
3646                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3647                 c -> classUsed = NOTUSED; /* not used initially CO-RT */                
3648                 c -> impldBy = NULL;
3649                 
3650                 /* prevent loader from loading primitive class */
3651                 list_remove (&unloadedclasses, c);
3652                 c->loaded=true;
3653                 /* add to unlinked classes */
3654                 list_addlast (&unlinkedclasses, c);             
3655 /*JOWENN primitive types don't have objects as super class              c -> super = class_java_lang_Object; */
3656                 class_link (c);
3657
3658                 primitivetype_table[i].class_primitive = c;
3659
3660                 /* create class for wrapping the primitive type */
3661                 primitivetype_table[i].class_wrap =
3662                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
3663                 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3664                 primitivetype_table[i].class_wrap  -> impldBy = NULL;
3665
3666                 /* create the primitive array class */
3667                 if (primitivetype_table[i].arrayname) {
3668                         c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3669                         primitivetype_table[i].arrayclass = c;
3670                         c->loaded=true;
3671                         if (!c->linked) class_link(c);
3672                         primitivetype_table[i].arrayvftbl = c->vftbl;
3673                 }
3674         }
3675 }
3676
3677 /**************** function: class_primitive_from_sig ***************************
3678
3679         return the primitive class indicated by the given signature character
3680
3681     If the descriptor does not indicate a valid primitive type the
3682     return value is NULL.
3683
3684 ********************************************************************************/
3685
3686 classinfo *class_primitive_from_sig(char sig)
3687 {
3688         switch (sig) {
3689           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3690           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3691           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3692           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3693           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3694           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3695           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3696           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3697           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3698         }
3699         return NULL;
3700 }
3701
3702 /****************** function: class_from_descriptor ****************************
3703
3704     return the class indicated by the given descriptor
3705
3706     utf_ptr....first character of descriptor
3707     end_ptr....first character after the end of the string
3708     next.......if non-NULL, *next is set to the first character after
3709                the descriptor. (Undefined if an error occurs.)
3710
3711     mode.......a combination (binary or) of the following flags:
3712
3713                (Flags marked with * are the default settings.)
3714
3715                What to do if a reference type descriptor is parsed successfully:
3716
3717                    CLASSLOAD_SKIP...skip it and return something != NULL
3718                                  * CLASSLOAD_NEW....get classinfo * via class_new
3719                    CLASSLOAD_LOAD...get classinfo * via loader_load
3720
3721                How to handle primitive types:
3722
3723                              * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3724                    CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3725
3726                How to handle "V" descriptors:
3727
3728                              * CLASSLOAD_VOID.....handle it like other primitive types
3729                    CLASSLOAD_NOVOID...treat it as an error
3730
3731                How to deal with extra characters after the end of the
3732                descriptor:
3733
3734                              * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3735                    CLASSLOAD_CHECKEND.....treat them as an error
3736
3737                How to deal with errors:
3738
3739                              * CLASSLOAD_PANIC....abort execution with an error message
3740                    CLASSLOAD_NOPANIC..return NULL on error
3741
3742 ********************************************************************************/
3743
3744 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3745                                                                  char **next, int mode)
3746 {
3747         char *start = utf_ptr;
3748         bool error = false;
3749         utf *name;
3750
3751         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3752
3753         if (mode & CLASSLOAD_CHECKEND)
3754                 error |= (utf_ptr != end_ptr);
3755         
3756         if (!error) {
3757                 if (next) *next = utf_ptr;
3758                 
3759                 switch (*start) {
3760                   case 'V':
3761                           if (mode & CLASSLOAD_NOVOID)
3762                                   break;
3763                           /* FALLTHROUGH! */
3764                   case 'I':
3765                   case 'J':
3766                   case 'F':
3767                   case 'D':
3768                   case 'B':
3769                   case 'C':
3770                   case 'S':
3771                   case 'Z':
3772                           return (mode & CLASSLOAD_NULLPRIMITIVE)
3773                                   ? NULL
3774                                   : class_primitive_from_sig(*start);
3775                           
3776                   case 'L':
3777                           start++;
3778                           utf_ptr--;
3779                           /* FALLTHROUGH! */
3780                   case '[':
3781                           if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3782                           name = utf_new(start, utf_ptr - start);
3783                           return (mode & CLASSLOAD_LOAD)
3784                                   ? loader_load(name) : class_new(name); /* XXX handle errors */
3785                 }
3786         }
3787
3788         /* An error occurred */
3789         if (mode & CLASSLOAD_NOPANIC)
3790                 return NULL;
3791
3792         log_plain("Invalid descriptor at beginning of '");
3793         log_plain_utf(utf_new(start, end_ptr - start));
3794         log_plain("'");
3795         log_nl();
3796                                                   
3797         panic("Invalid descriptor");
3798
3799         /* keep compiler happy */
3800         return NULL;
3801 }
3802
3803
3804 /******************* function: type_from_descriptor ****************************
3805
3806     return the basic type indicated by the given descriptor
3807
3808     This function parses a descriptor and returns its basic type as
3809     TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3810
3811     cls...if non-NULL the referenced variable is set to the classinfo *
3812           returned by class_from_descriptor.
3813
3814     For documentation of the arguments utf_ptr, end_ptr, next and mode
3815     see class_from_descriptor. The only difference is that
3816     type_from_descriptor always uses CLASSLOAD_PANIC.
3817
3818 ********************************************************************************/
3819
3820 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3821                                                  char **next, int mode)
3822 {
3823         classinfo *mycls;
3824         if (!cls) cls = &mycls;
3825         *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3826         switch (*utf_ptr) {
3827           case 'B': 
3828           case 'C':
3829           case 'I':
3830           case 'S':  
3831           case 'Z':
3832                   return TYPE_INT;
3833           case 'D':
3834                   return TYPE_DOUBLE;
3835           case 'F':
3836                   return TYPE_FLOAT;
3837           case 'J':
3838                   return TYPE_LONG;
3839           case 'V':
3840                   return TYPE_VOID;
3841         }
3842         return TYPE_ADDRESS;
3843 }
3844
3845
3846
3847 /*************** function: create_system_exception_classes *******************************
3848
3849         create system exception classes needed by default 
3850
3851 ********************************************************************************/
3852
3853 static void create_system_exception_classes()
3854 {
3855         if (verbose)
3856                 log_text("loader_init:  create_system_exception_classs: loader_load: java/lang/ClassCastException");
3857
3858         loader_load_sysclass(&class_java_lang_ClassCastException,
3859                                                  utf_new_char("java/lang/ClassCastException"));
3860         loader_load_sysclass(&class_java_lang_NullPointerException,
3861                                                  utf_new_char("java/lang/NullPointerException"));
3862         loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3863                                                  utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
3864         loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3865                                                  utf_new_char("java/lang/NegativeArraySizeException"));
3866         loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3867                                                  utf_new_char("java/lang/OutOfMemoryError"));
3868         loader_load_sysclass(&class_java_lang_ArrayStoreException,
3869                                                  utf_new_char("java/lang/ArrayStoreException"));
3870         loader_load_sysclass(&class_java_lang_ArithmeticException,
3871                                                  utf_new_char("java/lang/ArithmeticException"));
3872         loader_load_sysclass(&class_java_lang_ThreadDeath,
3873                                                  utf_new_char("java/lang/ThreadDeath"));
3874 }
3875
3876
3877 /*************** function: create_system_exception_classes *******************************
3878
3879         create system exception proto classes needed by default 
3880
3881 ********************************************************************************/
3882
3883 static void create_system_exception_proto_classes()
3884 {
3885
3886         if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3887         proto_java_lang_ClassCastException =
3888                 builtin_new(class_java_lang_ClassCastException);
3889
3890         if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3891
3892         proto_java_lang_NullPointerException =
3893                 builtin_new(class_java_lang_NullPointerException);
3894         if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3895
3896         proto_java_lang_ArrayIndexOutOfBoundsException =
3897                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3898
3899         proto_java_lang_NegativeArraySizeException =
3900                 builtin_new(class_java_lang_NegativeArraySizeException);
3901
3902         proto_java_lang_OutOfMemoryError =
3903                 builtin_new(class_java_lang_OutOfMemoryError);
3904
3905         proto_java_lang_ArithmeticException =
3906                 builtin_new(class_java_lang_ArithmeticException);
3907
3908         proto_java_lang_ArrayStoreException =
3909                 builtin_new(class_java_lang_ArrayStoreException);
3910
3911         proto_java_lang_ThreadDeath =
3912                 builtin_new(class_java_lang_ThreadDeath);
3913
3914
3915 }
3916
3917
3918
3919 /*************** function: create_pseudo_classes *******************************
3920
3921         create pseudo classes used by the typechecker
3922
3923 ********************************************************************************/
3924
3925 static void create_pseudo_classes()
3926 {
3927     /* pseudo class for Arraystubs (extends java.lang.Object) */
3928     
3929     pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3930     list_remove(&unloadedclasses, pseudo_class_Arraystub);
3931
3932     pseudo_class_Arraystub->super = class_java_lang_Object;
3933     pseudo_class_Arraystub->interfacescount = 2;
3934     pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3935     pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3936     pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3937
3938     list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3939     class_link(pseudo_class_Arraystub);
3940
3941         pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3942
3943     /* pseudo class representing the null type */
3944     
3945     pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3946     list_remove(&unloadedclasses, pseudo_class_Null);
3947
3948     pseudo_class_Null->super = class_java_lang_Object;
3949
3950     list_addlast(&unlinkedclasses, pseudo_class_Null);
3951     class_link(pseudo_class_Null);      
3952
3953     /* pseudo class representing new uninitialized objects */
3954     
3955     pseudo_class_New = class_new(utf_new_char("$NEW$"));
3956     list_remove(&unloadedclasses, pseudo_class_New);
3957
3958     pseudo_class_New->super = class_java_lang_Object;
3959
3960     list_addlast(&unlinkedclasses, pseudo_class_New);
3961     class_link(pseudo_class_New);       
3962 }
3963
3964
3965 /********************** Function: loader_init **********************************
3966
3967         Initializes all lists and loads all classes required for the system or the
3968         compiler.
3969
3970 *******************************************************************************/
3971  
3972 void loader_init(u1 *stackbottom)
3973 {
3974         interfaceindex = 0;
3975         
3976         list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3977         list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3978         list_init(&linkedclasses, OFFSET(classinfo, listnode));
3979
3980         /* create utf-symbols for pointer comparison of frequently used strings */
3981         utf_innerclasses    = utf_new_char("InnerClasses");
3982         utf_constantvalue   = utf_new_char("ConstantValue");
3983         utf_code                = utf_new_char("Code");
3984         utf_exceptions          = utf_new_char("Exceptions");
3985         utf_linenumbertable     = utf_new_char("LineNumberTable");
3986         utf_sourcefile          = utf_new_char("SourceFile");
3987         utf_finalize        = utf_new_char("finalize");
3988         utf_fidesc              = utf_new_char("()V");
3989         utf_init                = utf_new_char("<init>");
3990         utf_clinit              = utf_new_char("<clinit>");
3991         utf_initsystemclass = utf_new_char("initializeSystemClass");
3992         utf_systemclass     = utf_new_char("java/lang/System");
3993         utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
3994         utf_initialize      = utf_new_char("initialize");
3995         utf_initializedesc  = utf_new_char("(I)V");
3996
3997         utf_vmclass         = utf_new_char("java/lang/VMClass");
3998         utf_java_lang_Object= utf_new_char("java/lang/Object");
3999
4000         array_packagename   = utf_new_char("<the array package>");
4001
4002         /* create some important classes */
4003         /* These classes have to be created now because the classinfo
4004          * pointers are used in the loading code.
4005          */
4006         class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
4007         class_java_lang_String = class_new(utf_new_char("java/lang/String"));
4008         class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
4009         class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
4010
4011         if (verbose) log_text("loader_init: java/lang/Object");
4012         /* load the classes which were created above */
4013         loader_load_sysclass(NULL, class_java_lang_Object->name);
4014
4015         loader_inited = 1; /*JOWENN*/
4016
4017         loader_load_sysclass(&class_java_lang_Throwable,
4018                                                  utf_new_char("java/lang/Throwable"));
4019
4020         create_system_exception_classes();
4021
4022         /* create classes representing primitive types */
4023         create_primitive_classes();
4024
4025         /* create classes used by the typechecker */
4026         create_pseudo_classes();
4027
4028         /* correct vftbl-entries (retarded loading of class java/lang/String) */
4029         stringtable_update();
4030
4031 #if defined(USE_THREADS)
4032         if (stackbottom!=0)
4033                 initLocks();
4034 #endif
4035         create_system_exception_proto_classes();
4036
4037         loader_inited = 1;
4038 }
4039
4040
4041 /********************* Function: loader_initclasses ****************************
4042
4043         Initializes all loaded but uninitialized classes
4044
4045 *******************************************************************************/
4046
4047 #if 0
4048 /* XXX TWISTI: i think we do not need this */
4049 void loader_initclasses ()
4050 {
4051         classinfo *c;
4052         
4053 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4054         pthread_mutex_lock(&compiler_mutex);
4055 #endif
4056
4057         intsDisable();                     /* schani */
4058
4059         if (makeinitializations) {
4060                 c = list_first(&linkedclasses);
4061                 while (c) {
4062                         class_init(c);
4063                         c = list_next(&linkedclasses, c);
4064                 }
4065         }
4066
4067         intsRestore();                      /* schani */
4068         
4069 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4070         pthread_mutex_unlock(&compiler_mutex);
4071 #endif
4072 }
4073 #endif
4074
4075
4076 static void loader_compute_class_values(classinfo *c)
4077 {
4078         classinfo *subs;
4079
4080         c->vftbl->baseval = ++classvalue;
4081
4082         subs = c->sub;
4083         while (subs != NULL) {
4084                 loader_compute_class_values(subs);
4085                 subs = subs->nextsub;
4086         }
4087         c->vftbl->diffval = classvalue - c->vftbl->baseval;
4088         
4089 /*      
4090         {
4091         int i;
4092         for (i = 0; i < c->index; i++)
4093                 printf(" ");
4094         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
4095         utf_display(c->name);
4096         printf("\n");
4097         }
4098 */      
4099 }
4100
4101
4102 void loader_compute_subclasses()
4103 {
4104         classinfo *c;
4105         
4106 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4107         intsDisable();                     /* schani */
4108 #endif
4109
4110         c = list_first(&linkedclasses);
4111         while (c) {
4112                 if (!(c->flags & ACC_INTERFACE)) {
4113                         c->nextsub = 0;
4114                         c->sub = 0;
4115                 }
4116                 c = list_next(&linkedclasses, c);
4117         }
4118
4119         c = list_first(&linkedclasses);
4120         while (c) {
4121                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4122                         c->nextsub = c->super->sub;
4123                         c->super->sub = c;
4124                 }
4125                 c = list_next(&linkedclasses, c);
4126         }
4127
4128         classvalue = 0;
4129 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4130         cast_lock();
4131 #endif
4132         loader_compute_class_values(class_java_lang_Object);
4133 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4134         cast_unlock();
4135 #endif
4136
4137 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4138         intsRestore();                      /* schani */
4139 #endif
4140 }
4141
4142
4143 /******************** function classloader_buffer ******************************
4144  
4145     sets buffer for reading classdata
4146
4147 *******************************************************************************/
4148
4149 void classload_buffer(u1 *buf, int len)
4150 {
4151         classbuffer      = buf;
4152         classbuffer_size = len;
4153         classbuf_pos     = buf - 1;
4154 }
4155
4156
4157 /******************** Function: loader_close ***********************************
4158
4159         Frees all resources
4160         
4161 *******************************************************************************/
4162
4163 void loader_close()
4164 {
4165         classinfo *c;
4166
4167         while ((c = list_first(&unloadedclasses))) {
4168                 list_remove(&unloadedclasses, c);
4169 /*              class_free(c); */
4170         }
4171         while ((c = list_first(&unlinkedclasses))) {
4172                 list_remove(&unlinkedclasses, c);
4173 /*              class_free(c); */
4174         }
4175         while ((c = list_first(&linkedclasses))) {
4176                 list_remove(&linkedclasses, c);
4177 /*              class_free(c); */
4178         }
4179 }
4180
4181
4182 /*
4183  * These are local overrides for various environment variables in Emacs.
4184  * Please do not remove this and leave it at the end of the file, where
4185  * Emacs will automagically detect them.
4186  * ---------------------------------------------------------------------
4187  * Local variables:
4188  * mode: c
4189  * indent-tabs-mode: t
4190  * c-basic-offset: 4
4191  * tab-width: 4
4192  * End:
4193  */