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