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