silently remove ACC_SUPER on interfaces
[cacao.git] / src / vm / loader.c
1 /* loader.c - class loader functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28    Changes: Andreas Krall
29             Roman Obermaiser
30             Mark Probst
31                         Edwin Steiner
32
33    $Id: loader.c 915 2004-02-05 23:13:19Z 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_FINAL) != 0) {
2288                                                         log_utf(c->name);
2289                                                         log_utf(sc->name);
2290                                                         log_utf(sc->methods[j].name);
2291                                                         log_utf(sc->methods[j].descriptor);
2292                                                         panic("Trying to overwrite final method");
2293                                                 }
2294                                                 m->vftblindex = sc->methods[j].vftblindex;
2295                                                 goto foundvftblindex;
2296                                         }
2297                                 }
2298                                 sc = sc->super;
2299                         }
2300                         m->vftblindex = (vftbllength++);
2301                 foundvftblindex: ;
2302                 }
2303         }       
2304         
2305 #ifdef STATISTICS
2306         count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2307 #endif
2308
2309         /* compute interfacetable length */
2310
2311         interfacetablelength = 0;
2312         c2 = c;
2313         while (c2) {
2314                 for (i = 0; i < c2->interfacescount; i++) {
2315                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2316                         if (h > interfacetablelength)
2317                                 interfacetablelength = h;
2318                 }
2319                 c2 = c2->super;
2320         }
2321
2322         /* allocate virtual function table */
2323
2324         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2325                                                    (vftbllength - 1) + sizeof(methodptr*) *
2326                                                    (interfacetablelength - (interfacetablelength > 0)));
2327         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2328                                   (interfacetablelength > 1));
2329         c->header.vftbl = c->vftbl = v;
2330         v->class = c;
2331         v->vftbllength = vftbllength;
2332         v->interfacetablelength = interfacetablelength;
2333         v->arraydesc = arraydesc;
2334
2335         /* store interface index in vftbl */
2336         if (c->flags & ACC_INTERFACE)
2337                 v->baseval = -(c->index);
2338
2339         /* copy virtual function table of super class */
2340
2341         for (i = 0; i < supervftbllength; i++) 
2342                 v->table[i] = super->vftbl->table[i];
2343         
2344         /* add method stubs into virtual function table */
2345
2346         for (i = 0; i < c->methodscount; i++) {
2347                 methodinfo *m = &(c->methods[i]);
2348                 if (!(m->flags & ACC_STATIC)) {
2349                         v->table[m->vftblindex] = m->stubroutine;
2350                 }
2351         }
2352
2353         /* compute instance size and offset of each field */
2354         
2355         for (i = 0; i < c->fieldscount; i++) {
2356                 s4 dsize;
2357                 fieldinfo *f = &(c->fields[i]);
2358                 
2359                 if (!(f->flags & ACC_STATIC) ) {
2360                         dsize = desc_typesize(f->descriptor);
2361                         c->instancesize = ALIGN(c->instancesize, dsize);
2362                         f->offset = c->instancesize;
2363                         c->instancesize += dsize;
2364                 }
2365         }
2366
2367         /* initialize interfacetable and interfacevftbllength */
2368         
2369         v->interfacevftbllength = MNEW(s4, interfacetablelength);
2370
2371 #ifdef STATISTICS
2372         count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2373 #endif
2374
2375         for (i = 0; i < interfacetablelength; i++) {
2376                 v->interfacevftbllength[i] = 0;
2377                 v->interfacetable[-i] = NULL;
2378         }
2379         
2380         /* add interfaces */
2381         
2382         for (c2 = c; c2 != NULL; c2 = c2->super)
2383                 for (i = 0; i < c2->interfacescount; i++) {
2384                         class_addinterface(c, c2->interfaces[i]);
2385                 }
2386
2387         /* add finalizer method (not for java.lang.Object) */
2388
2389         if (super != NULL) {
2390                 methodinfo *fi;
2391                 static utf *finame = NULL;
2392                 static utf *fidesc = NULL;
2393
2394                 if (finame == NULL)
2395                         finame = utf_finalize;
2396                 if (fidesc == NULL)
2397                         fidesc = utf_fidesc;
2398
2399                 fi = class_findmethod(c, finame, fidesc);
2400                 if (fi != NULL) {
2401                         if (!(fi->flags & ACC_STATIC)) {
2402                                 c->finalizer = fi;
2403                         }
2404                 }
2405         }
2406
2407         /* final tasks */
2408
2409         c->linked = true;       
2410
2411         list_remove(&unlinkedclasses, c);
2412         list_addlast(&linkedclasses, c);
2413 }
2414
2415
2416 /******************* Function: class_freepool **********************************
2417
2418         Frees all resources used by this classes Constant Pool.
2419
2420 *******************************************************************************/
2421
2422 static void class_freecpool (classinfo *c)
2423 {
2424         u4 idx;
2425         u4 tag;
2426         voidptr info;
2427         
2428         for (idx=0; idx < c->cpcount; idx++) {
2429                 tag = c->cptags[idx];
2430                 info = c->cpinfos[idx];
2431                 
2432                 if (info != NULL) {
2433                         switch (tag) {
2434                         case CONSTANT_Fieldref:
2435                         case CONSTANT_Methodref:
2436                         case CONSTANT_InterfaceMethodref:
2437                                 FREE (info, constant_FMIref);
2438                                 break;
2439                         case CONSTANT_Integer:
2440                                 FREE (info, constant_integer);
2441                                 break;
2442                         case CONSTANT_Float:
2443                                 FREE (info, constant_float);
2444                                 break;
2445                         case CONSTANT_Long:
2446                                 FREE (info, constant_long);
2447                                 break;
2448                         case CONSTANT_Double:
2449                                 FREE (info, constant_double);
2450                                 break;
2451                         case CONSTANT_NameAndType:
2452                                 FREE (info, constant_nameandtype);
2453                                 break;
2454                         }
2455                         }
2456                 }
2457
2458         MFREE (c -> cptags,  u1, c -> cpcount);
2459         MFREE (c -> cpinfos, voidptr, c -> cpcount);
2460 }
2461
2462
2463 /*********************** Function: class_free **********************************
2464
2465         Frees all resources used by the class.
2466
2467 *******************************************************************************/
2468
2469 static void class_free(classinfo *c)
2470 {
2471         s4 i;
2472         vftbl *v;
2473                 
2474         class_freecpool(c);
2475
2476         MFREE(c->interfaces, classinfo*, c->interfacescount);
2477
2478         for (i = 0; i < c->fieldscount; i++)
2479                 field_free(&(c->fields[i]));
2480         
2481         for (i = 0; i < c->methodscount; i++)
2482                 method_free(&(c->methods[i]));
2483         MFREE(c->methods, methodinfo, c->methodscount);
2484
2485         if ((v = c->vftbl) != NULL) {
2486                 if (v->arraydesc)
2487                         mem_free(v->arraydesc,sizeof(arraydescriptor));
2488                 
2489                 for (i = 0; i < v->interfacetablelength; i++) {
2490                         MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2491                 }
2492                 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2493
2494                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2495                     sizeof(methodptr*) * (v->interfacetablelength -
2496                                          (v->interfacetablelength > 0));
2497                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2498                                              (v->interfacetablelength > 1));
2499                 mem_free(v, i);
2500         }
2501
2502         if (c->innerclasscount)
2503                 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2504
2505         /*      if (c->classvftbl)
2506                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2507         
2508         GCFREE(c);
2509 }
2510
2511
2512 /************************* Function: class_findfield ***************************
2513         
2514         Searches a 'classinfo' structure for a field having the given name and
2515         type.
2516
2517 *******************************************************************************/
2518
2519 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2520 {
2521         s4 i;
2522         
2523         for (i = 0; i < c->fieldscount; i++) { 
2524                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
2525                         return &(c->fields[i]);                                                         
2526     }
2527
2528         panic("Can not find field given in CONSTANT_Fieldref");
2529
2530         /* keep compiler happy */
2531         return NULL;
2532 }
2533
2534
2535 /************************* Function: class_findmethod **************************
2536         
2537         Searches a 'classinfo' structure for a method having the given name and
2538         type and returns the index in the class info structure.
2539         If type is NULL, it is ignored.
2540
2541 *******************************************************************************/
2542
2543 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2544 {
2545         s4 i;
2546 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2547         char *buffer;                   
2548         int buffer_len, pos;
2549 #endif
2550 #ifdef JOWENN_DEBUG1
2551
2552         buffer_len = 
2553                 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2554         
2555         buffer = MNEW(char, buffer_len);
2556
2557         strcpy(buffer, "class_findmethod: method:");
2558         utf_sprint(buffer + strlen(buffer), name);
2559         strcpy(buffer + strlen(buffer), ", desc: ");
2560         utf_sprint(buffer + strlen(buffer), desc);
2561         strcpy(buffer + strlen(buffer), ", classname: ");
2562         utf_sprint(buffer + strlen(buffer), c->name);
2563         
2564         log_text(buffer);       
2565
2566         MFREE(buffer, char, buffer_len);
2567 #endif  
2568         for (i = 0; i < c->methodscount; i++) {
2569 #ifdef JOWENN_DEBUG2
2570                 buffer_len = 
2571                         utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2572         
2573                 buffer = MNEW(char, buffer_len);
2574
2575                 strcpy(buffer, "class_findmethod: comparing to method:");
2576                 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2577                 strcpy(buffer + strlen(buffer), ", desc: ");
2578                 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2579         
2580                 log_text(buffer);       
2581
2582                 MFREE(buffer, char, buffer_len);
2583 #endif  
2584                 
2585                 
2586                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2587                                                                                          (c->methods[i].descriptor == desc))) {
2588                         return i;
2589                 }
2590         }
2591
2592 #ifdef JOWENN_DEBUG2    
2593         class_showconstantpool(c);
2594         log_text("class_findmethod: returning NULL");
2595 #endif
2596
2597         return -1;
2598 }
2599
2600
2601 /************************* Function: class_findmethod **************************
2602         
2603         Searches a 'classinfo' structure for a method having the given name and
2604         type.
2605         If type is NULL, it is ignored.
2606
2607 *******************************************************************************/
2608
2609 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2610 {
2611 #if 0
2612         s4 i;
2613 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2614         char *buffer;                   
2615         int buffer_len, pos;
2616 #endif
2617 #ifdef JOWENN_DEBUG1
2618
2619         buffer_len = 
2620                 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2621         
2622         buffer = MNEW(char, buffer_len);
2623
2624         strcpy(buffer, "class_findmethod: method:");
2625         utf_sprint(buffer + strlen(buffer), name);
2626         strcpy(buffer + strlen(buffer), ", desc: ");
2627         utf_sprint(buffer + strlen(buffer), desc);
2628         strcpy(buffer + strlen(buffer), ", classname: ");
2629         utf_sprint(buffer + strlen(buffer), c->name);
2630         
2631         log_text(buffer);       
2632
2633         MFREE(buffer, char, buffer_len);
2634 #endif  
2635         for (i = 0; i < c->methodscount; i++) {
2636 #ifdef JOWENN_DEBUG2
2637                 buffer_len = 
2638                         utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2639         
2640                 buffer = MNEW(char, buffer_len);
2641
2642                 strcpy(buffer, "class_findmethod: comparing to method:");
2643                 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2644                 strcpy(buffer + strlen(buffer), ", desc: ");
2645                 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2646         
2647                 log_text(buffer);       
2648
2649                 MFREE(buffer, char, buffer_len);
2650 #endif  
2651                 
2652                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2653                                                                                          (c->methods[i].descriptor == desc))) {
2654                         return &(c->methods[i]);
2655                 }
2656         }
2657 #ifdef JOWENN_DEBUG2    
2658         class_showconstantpool(c);
2659         log_text("class_findmethod: returning NULL");
2660 #endif
2661         return NULL;
2662 #endif
2663
2664         s4 idx=class_findmethodIndex(c, name, desc);
2665 /*      if (idx==-1) log_text("class_findmethod: method not found");*/
2666         if (idx == -1) return NULL;
2667
2668         return &(c->methods[idx]);
2669 }
2670
2671
2672 /*********************** Function: class_fetchmethod **************************
2673         
2674     like class_findmethod, but aborts with an error if the method is not found
2675
2676 *******************************************************************************/
2677
2678 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2679 {
2680         methodinfo *mi;
2681         mi = class_findmethod(c, name, desc);
2682
2683         if (!mi) {
2684                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2685                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2686                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2687                 panic("Method not found");
2688         }
2689
2690         return mi;
2691 }
2692
2693
2694 /*********************** Function: class_findmethod_w**************************
2695
2696     like class_findmethod, but logs a warning if the method is not found
2697
2698 *******************************************************************************/
2699
2700 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2701 {
2702         methodinfo *mi;
2703         mi = class_findmethod(c, name, desc);
2704
2705         if (!mi) {
2706                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2707                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2708                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2709
2710                 if ( c->flags & ACC_PUBLIC )       log_plain(" PUBLIC ");
2711                 if ( c->flags & ACC_PRIVATE )      log_plain(" PRIVATE ");
2712                 if ( c->flags & ACC_PROTECTED )    log_plain(" PROTECTED ");
2713                 if ( c->flags & ACC_STATIC )       log_plain(" STATIC ");
2714                 if ( c->flags & ACC_FINAL )        log_plain(" FINAL ");
2715                 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2716                 if ( c->flags & ACC_VOLATILE )     log_plain(" VOLATILE ");
2717                 if ( c->flags & ACC_TRANSIENT )    log_plain(" TRANSIENT ");
2718                 if ( c->flags & ACC_NATIVE )       log_plain(" NATIVE ");
2719                 if ( c->flags & ACC_INTERFACE )    log_plain(" INTERFACE ");
2720                 if ( c->flags & ACC_ABSTRACT )     log_plain(" ABSTRACT ");
2721
2722                 log_plain(from); 
2723                 log_plain(" : WARNING: Method not found");log_nl( );
2724         }
2725
2726         return mi;
2727 }
2728
2729
2730 /************************* Function: class_findmethod_approx ******************
2731         
2732         like class_findmethod but ignores the return value when comparing the
2733         descriptor.
2734
2735 *******************************************************************************/
2736
2737 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2738 {
2739         s4 i;
2740
2741         for (i = 0; i < c->methodscount; i++) {
2742                 if (c->methods[i].name == name) {
2743                         utf *meth_descr = c->methods[i].descriptor;
2744                         
2745                         if (desc == NULL) 
2746                                 /* ignore type */
2747                                 return &(c->methods[i]);
2748
2749                         if (desc->blength <= meth_descr->blength) {
2750                                 /* current position in utf text   */
2751                                 char *desc_utf_ptr = desc->text;      
2752                                 char *meth_utf_ptr = meth_descr->text;                                    
2753                                 /* points behind utf strings */
2754                                 char *desc_end = utf_end(desc);         
2755                                 char *meth_end = utf_end(meth_descr);   
2756                                 char ch;
2757
2758                                 /* compare argument types */
2759                                 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2760
2761                                         if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2762                                                 break; /* no match */
2763
2764                                         if (ch == ')')
2765                                                 return &(c->methods[i]);   /* all parameter types equal */
2766                                 }
2767                         }
2768                 }
2769         }
2770
2771         return NULL;
2772 }
2773
2774
2775 /***************** Function: class_resolvemethod_approx ***********************
2776         
2777         Searches a class and every super class for a method (without paying
2778         attention to the return value)
2779
2780 *******************************************************************************/
2781
2782 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2783 {
2784         while (c) {
2785                 /* search for method (ignore returntype) */
2786                 methodinfo *m = class_findmethod_approx(c, name, desc);
2787                 /* method found */
2788                 if (m) return m;
2789                 /* search superclass */
2790                 c = c->super;
2791         }
2792
2793         return NULL;
2794 }
2795
2796
2797 /************************* Function: class_resolvemethod ***********************
2798         
2799         Searches a class and every super class for a method.
2800
2801 *******************************************************************************/
2802
2803 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2804 {
2805         while (c) {
2806                 methodinfo *m = class_findmethod(c, name, desc);
2807                 if (m) return m;
2808                 /* search superclass */
2809                 c = c->super;
2810         }
2811
2812         return NULL;
2813 }
2814
2815
2816 /************************* Function: class_issubclass **************************
2817
2818         Checks if sub is a descendant of super.
2819         
2820 *******************************************************************************/
2821
2822 bool class_issubclass(classinfo *sub, classinfo *super)
2823 {
2824         for (;;) {
2825                 if (!sub) return false;
2826                 if (sub == super) return true;
2827                 sub = sub->super;
2828         }
2829 }
2830
2831
2832 /****************** Initialization function for classes ******************
2833
2834         In Java, every class can have a static initialization function. This
2835         function has to be called BEFORE calling other methods or accessing static
2836         variables.
2837
2838 *******************************************************************************/
2839
2840 void class_init(classinfo *c)
2841 {
2842         methodinfo *m;
2843         s4 i;
2844 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2845         int b;
2846 #endif
2847
2848         if (!makeinitializations)
2849                 return;
2850         if (c->initialized)
2851                 return;
2852
2853         c->initialized = true;
2854
2855 #ifdef STATISTICS
2856         count_class_inits++;
2857 #endif
2858
2859         /* initialize super class */
2860         if (c->super) {
2861                 if (initverbose) {
2862                         char logtext[MAXLOGTEXT];
2863                         sprintf(logtext, "Initialize super class ");
2864                         utf_sprint(logtext + strlen(logtext), c->super->name);
2865                         sprintf(logtext + strlen(logtext), " from ");
2866                         utf_sprint(logtext + strlen(logtext), c->name);
2867                         log_text(logtext);
2868                 }
2869                 class_init(c->super);
2870         }
2871
2872         /* initialize interface classes */
2873         for (i = 0; i < c->interfacescount; i++) {
2874                 if (initverbose) {
2875                         char logtext[MAXLOGTEXT];
2876                         sprintf(logtext, "Initialize interface class ");
2877                         utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2878                         sprintf(logtext + strlen(logtext), " from ");
2879                         utf_sprint(logtext + strlen(logtext), c->name);
2880                         log_text(logtext);
2881                 }
2882                 class_init(c->interfaces[i]);  /* real */
2883         }
2884
2885         m = class_findmethod(c, utf_clinit, utf_fidesc);
2886         if (!m) {
2887                 if (initverbose) {
2888                         char logtext[MAXLOGTEXT];
2889                         sprintf(logtext, "Class ");
2890                         utf_sprint(logtext + strlen(logtext), c->name);
2891                         sprintf(logtext + strlen(logtext), " has no initializer");
2892                         log_text(logtext);
2893                 }
2894                 /*              goto callinitialize;*/
2895                 return;
2896         }
2897
2898         if (!(m->flags & ACC_STATIC))
2899                 panic("Class initializer is not static!");
2900
2901         if (initverbose) {
2902                 char logtext[MAXLOGTEXT];
2903                 sprintf(logtext, "Starting initializer for class: ");
2904                 utf_sprint(logtext + strlen(logtext), c->name);
2905                 log_text(logtext);
2906         }
2907
2908 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2909         b = blockInts;
2910         blockInts = 0;
2911 #endif
2912
2913         /* now call the initializer */
2914         asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2915
2916 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2917         assert(blockInts == 0);
2918         blockInts = b;
2919 #endif
2920
2921         /* we have to throw an exception */
2922         if (*exceptionptr) {
2923                 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2924                 printf("Caused by: ");
2925                 utf_display((*exceptionptr)->vftbl->class->name);
2926                 printf("\n");
2927                 fflush(stdout);
2928                 exit(1);
2929         }
2930
2931         if (initverbose) {
2932                 char logtext[MAXLOGTEXT];
2933                 sprintf(logtext, "Finished initializer for class: ");
2934                 utf_sprint(logtext + strlen(logtext), c->name);
2935                 log_text(logtext);
2936         }
2937
2938         if (c->name == utf_systemclass) {
2939                 /* class java.lang.System requires explicit initialization */
2940
2941                 if (initverbose)
2942                         printf("#### Initializing class System");
2943
2944                 /* find initializing method */
2945                 m = class_findmethod(c,
2946                                                          utf_initsystemclass,
2947                                                          utf_fidesc);
2948
2949                 if (!m) {
2950                         /* no method found */
2951                         /* printf("initializeSystemClass failed"); */
2952                         return;
2953                 }
2954
2955 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2956                 b = blockInts;
2957                 blockInts = 0;
2958 #endif
2959
2960                 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2961
2962 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2963                 assert(blockInts == 0);
2964                 blockInts = b;
2965 #endif
2966
2967                 if (*exceptionptr) {
2968                         printf("#### initializeSystemClass has thrown: ");
2969                         utf_display((*exceptionptr)->vftbl->class->name);
2970                         printf("\n");
2971                         fflush(stdout);
2972                 }
2973         }
2974 }
2975
2976
2977 /********* Function: find_class_method_constant *********/
2978
2979 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)  
2980 {
2981         u4 i;
2982         voidptr e;
2983
2984         for (i=0; i<c->cpcount; i++) {
2985                 
2986                 e = c -> cpinfos [i];
2987                 if (e) {
2988                         
2989                         switch (c -> cptags [i]) {
2990                         case CONSTANT_Methodref:
2991                                 {
2992                                         constant_FMIref *fmi = e;
2993                                         if (       (fmi->class->name == c1)  
2994                                                            && (fmi->name == m1)
2995                                                            && (fmi->descriptor == d1)) {
2996                                         
2997                                                 return i;
2998                                         }
2999                                 }
3000                                 break;
3001
3002                         case CONSTANT_InterfaceMethodref:
3003                                 {
3004                                         constant_FMIref *fmi = e;
3005                                         if (       (fmi->class->name == c1)  
3006                                                            && (fmi->name == m1)
3007                                                            && (fmi->descriptor == d1)) {
3008
3009                                                 return i;
3010                                         }
3011                                 }
3012                                 break;
3013                         }
3014                 }
3015         }
3016
3017         return -1;
3018 }
3019
3020
3021 void class_showconstanti(classinfo *c, int ii) 
3022 {
3023         u4 i = ii;
3024         voidptr e;
3025                 
3026         e = c->cpinfos [i];
3027         printf ("#%d:  ", (int) i);
3028         if (e) {
3029                 switch (c->cptags [i]) {
3030                 case CONSTANT_Class:
3031                         printf("Classreference -> ");
3032                         utf_display(((classinfo*)e)->name);
3033                         break;
3034                                 
3035                 case CONSTANT_Fieldref:
3036                         printf("Fieldref -> "); goto displayFMIi;
3037                 case CONSTANT_Methodref:
3038                         printf("Methodref -> "); goto displayFMIi;
3039                 case CONSTANT_InterfaceMethodref:
3040                         printf("InterfaceMethod -> "); goto displayFMIi;
3041                 displayFMIi:
3042                         {
3043                                 constant_FMIref *fmi = e;
3044                                 utf_display(fmi->class->name);
3045                                 printf(".");
3046                                 utf_display(fmi->name);
3047                                 printf(" ");
3048                                 utf_display(fmi->descriptor);
3049                         }
3050                         break;
3051
3052                 case CONSTANT_String:
3053                         printf("String -> ");
3054                         utf_display(e);
3055                         break;
3056                 case CONSTANT_Integer:
3057                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3058                         break;
3059                 case CONSTANT_Float:
3060                         printf("Float -> %f", ((constant_float*)e)->value);
3061                         break;
3062                 case CONSTANT_Double:
3063                         printf("Double -> %f", ((constant_double*)e)->value);
3064                         break;
3065                 case CONSTANT_Long:
3066                         {
3067                                 u8 v = ((constant_long*)e)->value;
3068 #if U8_AVAILABLE
3069                                 printf("Long -> %ld", (long int) v);
3070 #else
3071                                 printf("Long -> HI: %ld, LO: %ld\n", 
3072                                             (long int) v.high, (long int) v.low);
3073 #endif 
3074                         }
3075                         break;
3076                 case CONSTANT_NameAndType:
3077                         { 
3078                                 constant_nameandtype *cnt = e;
3079                                 printf("NameAndType: ");
3080                                 utf_display(cnt->name);
3081                                 printf(" ");
3082                                 utf_display(cnt->descriptor);
3083                         }
3084                         break;
3085                 case CONSTANT_Utf8:
3086                         printf("Utf8 -> ");
3087                         utf_display(e);
3088                         break;
3089                 default: 
3090                         panic("Invalid type of ConstantPool-Entry");
3091                 }
3092         }
3093         printf("\n");
3094 }
3095
3096
3097 void class_showconstantpool (classinfo *c) 
3098 {
3099         u4 i;
3100         voidptr e;
3101
3102         printf ("---- dump of constant pool ----\n");
3103
3104         for (i=0; i<c->cpcount; i++) {
3105                 printf ("#%d:  ", (int) i);
3106                 
3107                 e = c -> cpinfos [i];
3108                 if (e) {
3109                         
3110                         switch (c -> cptags [i]) {
3111                         case CONSTANT_Class:
3112                                 printf ("Classreference -> ");
3113                                 utf_display ( ((classinfo*)e) -> name );
3114                                 break;
3115                                 
3116                         case CONSTANT_Fieldref:
3117                                 printf ("Fieldref -> "); goto displayFMI;
3118                         case CONSTANT_Methodref:
3119                                 printf ("Methodref -> "); goto displayFMI;
3120                         case CONSTANT_InterfaceMethodref:
3121                                 printf ("InterfaceMethod -> "); goto displayFMI;
3122                         displayFMI:
3123                                 {
3124                                         constant_FMIref *fmi = e;
3125                                         utf_display ( fmi->class->name );
3126                                         printf (".");
3127                                         utf_display ( fmi->name);
3128                                         printf (" ");
3129                                         utf_display ( fmi->descriptor );
3130                                 }
3131                                 break;
3132
3133                         case CONSTANT_String:
3134                                 printf ("String -> ");
3135                                 utf_display (e);
3136                                 break;
3137                         case CONSTANT_Integer:
3138                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3139                                 break;
3140                         case CONSTANT_Float:
3141                                 printf ("Float -> %f", ((constant_float*)e) -> value);
3142                                 break;
3143                         case CONSTANT_Double:
3144                                 printf ("Double -> %f", ((constant_double*)e) -> value);
3145                                 break;
3146                         case CONSTANT_Long:
3147                                 {
3148                                         u8 v = ((constant_long*)e) -> value;
3149 #if U8_AVAILABLE
3150                                         printf ("Long -> %ld", (long int) v);
3151 #else
3152                                         printf ("Long -> HI: %ld, LO: %ld\n", 
3153                                                         (long int) v.high, (long int) v.low);
3154 #endif 
3155                                 }
3156                                 break;
3157                         case CONSTANT_NameAndType:
3158                                 {
3159                                         constant_nameandtype *cnt = e;
3160                                         printf ("NameAndType: ");
3161                                         utf_display (cnt->name);
3162                                         printf (" ");
3163                                         utf_display (cnt->descriptor);
3164                                 }
3165                                 break;
3166                         case CONSTANT_Utf8:
3167                                 printf ("Utf8 -> ");
3168                                 utf_display (e);
3169                                 break;
3170                         default: 
3171                                 panic ("Invalid type of ConstantPool-Entry");
3172                         }
3173                 }
3174
3175                 printf ("\n");
3176         }
3177 }
3178
3179
3180
3181 /********** Function: class_showmethods   (debugging only) *************/
3182
3183 void class_showmethods (classinfo *c)
3184 {
3185         s4 i;
3186         
3187         printf ("--------- Fields and Methods ----------------\n");
3188         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
3189
3190         printf ("This: "); utf_display (c->name); printf ("\n");
3191         if (c->super) {
3192                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3193                 }
3194         printf ("Index: %d\n", c->index);
3195         
3196         printf ("interfaces:\n");       
3197         for (i=0; i < c-> interfacescount; i++) {
3198                 printf ("   ");
3199                 utf_display (c -> interfaces[i] -> name);
3200                 printf (" (%d)\n", c->interfaces[i] -> index);
3201                 }
3202
3203         printf ("fields:\n");           
3204         for (i=0; i < c -> fieldscount; i++) {
3205                 field_display (&(c -> fields[i]));
3206                 }
3207
3208         printf ("methods:\n");
3209         for (i=0; i < c -> methodscount; i++) {
3210                 methodinfo *m = &(c->methods[i]);
3211                 if ( !(m->flags & ACC_STATIC)) 
3212                         printf ("vftblindex: %d   ", m->vftblindex);
3213
3214                 method_display ( m );
3215
3216                 }
3217
3218         printf ("Virtual function table:\n");
3219         for (i=0; i<c->vftbl->vftbllength; i++) {
3220                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
3221                 }
3222
3223 }
3224
3225
3226
3227 /******************************************************************************/
3228 /******************* General functions for the class loader *******************/
3229 /******************************************************************************/
3230
3231 /********************* Function: loader_load ***********************************
3232
3233         Loads and links the class desired class and each class and interface
3234         referenced by it.
3235         Returns: a pointer to this class
3236
3237 *******************************************************************************/
3238
3239 static int loader_load_running = 0;
3240
3241 classinfo *loader_load(utf *topname)
3242 {
3243         classinfo *top;
3244         classinfo *c;
3245         s8 starttime = 0;
3246         s8 stoptime = 0;
3247         classinfo *notlinkable;
3248
3249 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3250         pthread_mutex_lock(&compiler_mutex);
3251 #endif
3252
3253         /* avoid recursive calls */
3254         if (loader_load_running)
3255                 return class_new(topname);
3256
3257         loader_load_running++;
3258         
3259 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3260         intsDisable();
3261 #endif
3262
3263         if (getloadingtime)
3264                 starttime = getcputime();
3265
3266         top = class_new(topname);
3267
3268         /* load classes */
3269         while ((c = list_first(&unloadedclasses))) {
3270                 if (!class_load(c)) {
3271                         if (linkverbose)
3272                                 dolog("Failed to load class");
3273                         list_remove(&unloadedclasses, c);
3274                         top = NULL;
3275                 }
3276         }
3277
3278         /* link classes */
3279         if (linkverbose)
3280                 dolog("Linking...");
3281
3282         /* Added a hack to break infinite linking loops. A better
3283          * linking algorithm would be nice. -Edwin */
3284         notlinkable = NULL;
3285         while ((c = list_first(&unlinkedclasses))) {
3286                 class_link(c);
3287                 if (!c->linked) {
3288                         if (!notlinkable)
3289                                 notlinkable = c;
3290                         else if (notlinkable == c) {
3291                                 /* We tried to link this class for the second time and
3292                                  * no other classes were linked in between, so we are
3293                                  * caught in a loop.
3294                                  */
3295                                 if (linkverbose)
3296                                         dolog("Cannot resolve linking dependencies");
3297                                 top = NULL;
3298                                 if (!*exceptionptr)
3299                                         throw_linkageerror_message(c->name);
3300                                 break;
3301                         }
3302
3303                 } else
3304                         notlinkable = NULL;
3305         }
3306         if (linkverbose)
3307                 dolog("Linking done.");
3308
3309         if (loader_inited)
3310                 loader_compute_subclasses();
3311
3312         /* measure time */
3313         if (getloadingtime) {
3314                 stoptime = getcputime();
3315                 loadingtime += (stoptime - starttime);
3316         }
3317
3318
3319         loader_load_running--;
3320         
3321         /* check if a former loader_load call tried to load/link the class and 
3322            failed. This is needed because the class didn't appear in the 
3323            undloadclasses or unlinkedclasses list during this class. */
3324         if (top) {
3325                 if (!top->loaded) {
3326                         if (linkverbose) dolog("Failed to load class (former call)");
3327                         throw_noclassdeffounderror_message(top->name);
3328                         top = NULL;
3329                         
3330                 } else if (!top->linked) {
3331                         if (linkverbose)
3332                                 dolog("Failed to link class (former call)");
3333                         throw_linkageerror_message(top->name);
3334                         top = NULL;
3335                 }
3336         }
3337
3338 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3339         intsRestore();
3340 #endif
3341         
3342 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3343         pthread_mutex_unlock(&compiler_mutex);
3344 #endif
3345
3346         /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3347         
3348         return top; 
3349 }
3350
3351
3352 /****************** Function: loader_load_sysclass ****************************
3353
3354         Loads and links the class desired class and each class and interface
3355         referenced by it.
3356
3357     The pointer to the classinfo is stored in *top if top != NULL.
3358     The pointer is also returned.
3359
3360     If the class could not be loaded the function aborts with an error.
3361
3362 *******************************************************************************/
3363
3364 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3365 {
3366         classinfo *cls;
3367
3368         if ((cls = loader_load(topname)) == NULL) {
3369                 log_plain("Could not load important system class: ");
3370                 log_plain_utf(topname);
3371                 log_nl();
3372                 panic("Could not load important system class");
3373         }
3374
3375         if (top) *top = cls;
3376
3377         return cls;
3378 }
3379
3380
3381 /**************** function: create_primitive_classes ***************************
3382
3383         create classes representing primitive types 
3384
3385 ********************************************************************************/
3386
3387
3388 void create_primitive_classes()
3389 {  
3390         int i;
3391
3392         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3393                 /* create primitive class */
3394                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3395                 c -> classUsed = NOTUSED; /* not used initially CO-RT */                
3396                 c -> impldBy = NULL;
3397                 
3398                 /* prevent loader from loading primitive class */
3399                 list_remove (&unloadedclasses, c);
3400                 c->loaded=true;
3401                 /* add to unlinked classes */
3402                 list_addlast (&unlinkedclasses, c);             
3403 /*JOWENN primitive types don't have objects as super class              c -> super = class_java_lang_Object; */
3404                 class_link (c);
3405
3406                 primitivetype_table[i].class_primitive = c;
3407
3408                 /* create class for wrapping the primitive type */
3409                 primitivetype_table[i].class_wrap =
3410                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
3411                 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3412                 primitivetype_table[i].class_wrap  -> impldBy = NULL;
3413
3414                 /* create the primitive array class */
3415                 if (primitivetype_table[i].arrayname) {
3416                         c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3417                         primitivetype_table[i].arrayclass = c;
3418                         c->loaded=true;
3419                         if (!c->linked) class_link(c);
3420                         primitivetype_table[i].arrayvftbl = c->vftbl;
3421                 }
3422         }
3423 }
3424
3425 /**************** function: class_primitive_from_sig ***************************
3426
3427         return the primitive class indicated by the given signature character
3428
3429     If the descriptor does not indicate a valid primitive type the
3430     return value is NULL.
3431
3432 ********************************************************************************/
3433
3434 classinfo *class_primitive_from_sig(char sig)
3435 {
3436         switch (sig) {
3437           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3438           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3439           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3440           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3441           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3442           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3443           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3444           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3445           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3446         }
3447         return NULL;
3448 }
3449
3450 /****************** function: class_from_descriptor ****************************
3451
3452     return the class indicated by the given descriptor
3453
3454     utf_ptr....first character of descriptor
3455     end_ptr....first character after the end of the string
3456     next.......if non-NULL, *next is set to the first character after
3457                the descriptor. (Undefined if an error occurs.)
3458
3459     mode.......a combination (binary or) of the following flags:
3460
3461                (Flags marked with * are the default settings.)
3462
3463                What to do if a reference type descriptor is parsed successfully:
3464
3465                    CLASSLOAD_SKIP...skip it and return something != NULL
3466                                  * CLASSLOAD_NEW....get classinfo * via class_new
3467                    CLASSLOAD_LOAD...get classinfo * via loader_load
3468
3469                How to handle primitive types:
3470
3471                              * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3472                    CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3473
3474                How to handle "V" descriptors:
3475
3476                              * CLASSLOAD_VOID.....handle it like other primitive types
3477                    CLASSLOAD_NOVOID...treat it as an error
3478
3479                How to deal with extra characters after the end of the
3480                descriptor:
3481
3482                              * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3483                    CLASSLOAD_CHECKEND.....treat them as an error
3484
3485                How to deal with errors:
3486
3487                              * CLASSLOAD_PANIC....abort execution with an error message
3488                    CLASSLOAD_NOPANIC..return NULL on error
3489
3490 ********************************************************************************/
3491
3492 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3493                                                                  char **next, int mode)
3494 {
3495         char *start = utf_ptr;
3496         bool error = false;
3497         utf *name;
3498
3499         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3500
3501         if (mode & CLASSLOAD_CHECKEND)
3502                 error |= (utf_ptr != end_ptr);
3503         
3504         if (!error) {
3505                 if (next) *next = utf_ptr;
3506                 
3507                 switch (*start) {
3508                   case 'V':
3509                           if (mode & CLASSLOAD_NOVOID)
3510                                   break;
3511                           /* FALLTHROUGH! */
3512                   case 'I':
3513                   case 'J':
3514                   case 'F':
3515                   case 'D':
3516                   case 'B':
3517                   case 'C':
3518                   case 'S':
3519                   case 'Z':
3520                           return (mode & CLASSLOAD_NULLPRIMITIVE)
3521                                   ? NULL
3522                                   : class_primitive_from_sig(*start);
3523                           
3524                   case 'L':
3525                           start++;
3526                           utf_ptr--;
3527                           /* FALLTHROUGH! */
3528                   case '[':
3529                           if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3530                           name = utf_new(start,utf_ptr-start);
3531                           return (mode & CLASSLOAD_LOAD)
3532                                   ? loader_load(name) : class_new(name); /* XXX handle errors */
3533                 }
3534         }
3535
3536         /* An error occurred */
3537         if (mode & CLASSLOAD_NOPANIC)
3538                 return NULL;
3539
3540         log_plain("Invalid descriptor at beginning of '");
3541         log_plain_utf(utf_new(start, end_ptr-start));
3542         log_plain("'");
3543         log_nl();
3544                                                   
3545         panic("Invalid descriptor");
3546
3547         /* keep compiler happy */
3548         return NULL;
3549 }
3550
3551
3552 /******************* function: type_from_descriptor ****************************
3553
3554     return the basic type indicated by the given descriptor
3555
3556     This function parses a descriptor and returns its basic type as
3557     TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3558
3559     cls...if non-NULL the referenced variable is set to the classinfo *
3560           returned by class_from_descriptor.
3561
3562     For documentation of the arguments utf_ptr, end_ptr, next and mode
3563     see class_from_descriptor. The only difference is that
3564     type_from_descriptor always uses CLASSLOAD_PANIC.
3565
3566 ********************************************************************************/
3567
3568 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3569                                                  char **next, int mode)
3570 {
3571         classinfo *mycls;
3572         if (!cls) cls = &mycls;
3573         *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3574         switch (*utf_ptr) {
3575           case 'B': 
3576           case 'C':
3577           case 'I':
3578           case 'S':  
3579           case 'Z':
3580                   return TYPE_INT;
3581           case 'D':
3582                   return TYPE_DOUBLE;
3583           case 'F':
3584                   return TYPE_FLOAT;
3585           case 'J':
3586                   return TYPE_LONG;
3587           case 'V':
3588                   return TYPE_VOID;
3589         }
3590         return TYPE_ADDRESS;
3591 }
3592
3593
3594
3595 /*************** function: create_system_exception_classes *******************************
3596
3597         create system exception classes needed by default 
3598
3599 ********************************************************************************/
3600
3601 static void create_system_exception_classes()
3602 {
3603
3604         if (verbose) log_text("loader_init:  create_system_exception_classs: loader_load: java/lang/ClassCastException");
3605         loader_load_sysclass(&class_java_lang_ClassCastException,
3606                                                  utf_new_char ("java/lang/ClassCastException"));
3607         loader_load_sysclass(&class_java_lang_NullPointerException,
3608                                                  utf_new_char ("java/lang/NullPointerException"));
3609         loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3610                                                  utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3611         loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3612                                                  utf_new_char ("java/lang/NegativeArraySizeException"));
3613         loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3614                                                  utf_new_char ("java/lang/OutOfMemoryError"));
3615         loader_load_sysclass(&class_java_lang_ArrayStoreException,
3616                                                  utf_new_char ("java/lang/ArrayStoreException"));
3617         loader_load_sysclass(&class_java_lang_ArithmeticException,
3618                                                  utf_new_char ("java/lang/ArithmeticException"));
3619         loader_load_sysclass(&class_java_lang_ThreadDeath,
3620                                                  utf_new_char ("java/lang/ThreadDeath"));
3621
3622
3623 }
3624
3625
3626 /*************** function: create_system_exception_classes *******************************
3627
3628         create system exception proto classes needed by default 
3629
3630 ********************************************************************************/
3631
3632 static void create_system_exception_proto_classes()
3633 {
3634
3635         if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3636         proto_java_lang_ClassCastException =
3637                 builtin_new(class_java_lang_ClassCastException);
3638
3639         if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3640
3641         proto_java_lang_NullPointerException =
3642                 builtin_new(class_java_lang_NullPointerException);
3643         if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3644
3645         proto_java_lang_ArrayIndexOutOfBoundsException =
3646                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3647
3648         proto_java_lang_NegativeArraySizeException =
3649                 builtin_new(class_java_lang_NegativeArraySizeException);
3650
3651         proto_java_lang_OutOfMemoryError =
3652                 builtin_new(class_java_lang_OutOfMemoryError);
3653
3654         proto_java_lang_ArithmeticException =
3655                 builtin_new(class_java_lang_ArithmeticException);
3656
3657         proto_java_lang_ArrayStoreException =
3658                 builtin_new(class_java_lang_ArrayStoreException);
3659
3660         proto_java_lang_ThreadDeath =
3661                 builtin_new(class_java_lang_ThreadDeath);
3662
3663
3664 }
3665
3666
3667
3668 /*************** function: create_pseudo_classes *******************************
3669
3670         create pseudo classes used by the typechecker
3671
3672 ********************************************************************************/
3673
3674 static void create_pseudo_classes()
3675 {
3676     /* pseudo class for Arraystubs (extends java.lang.Object) */
3677     
3678     pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3679     list_remove(&unloadedclasses, pseudo_class_Arraystub);
3680
3681     pseudo_class_Arraystub->super = class_java_lang_Object;
3682     pseudo_class_Arraystub->interfacescount = 2;
3683     pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3684     pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3685     pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3686
3687     list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3688     class_link(pseudo_class_Arraystub);
3689
3690         pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3691
3692     /* pseudo class representing the null type */
3693     
3694     pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3695     list_remove(&unloadedclasses, pseudo_class_Null);
3696
3697     pseudo_class_Null->super = class_java_lang_Object;
3698
3699     list_addlast(&unlinkedclasses, pseudo_class_Null);
3700     class_link(pseudo_class_Null);      
3701
3702     /* pseudo class representing new uninitialized objects */
3703     
3704     pseudo_class_New = class_new(utf_new_char("$NEW$"));
3705     list_remove(&unloadedclasses, pseudo_class_New);
3706
3707     pseudo_class_New->super = class_java_lang_Object;
3708
3709     list_addlast(&unlinkedclasses, pseudo_class_New);
3710     class_link(pseudo_class_New);       
3711 }
3712
3713
3714 /********************** Function: loader_init **********************************
3715
3716         Initializes all lists and loads all classes required for the system or the
3717         compiler.
3718
3719 *******************************************************************************/
3720  
3721 void loader_init(u1 *stackbottom)
3722 {
3723         interfaceindex = 0;
3724         
3725         list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3726         list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3727         list_init(&linkedclasses, OFFSET(classinfo, listnode));
3728
3729         /* create utf-symbols for pointer comparison of frequently used strings */
3730         utf_innerclasses    = utf_new_char("InnerClasses");
3731         utf_constantvalue   = utf_new_char("ConstantValue");
3732         utf_code                = utf_new_char("Code");
3733         utf_finalize        = utf_new_char("finalize");
3734         utf_fidesc              = utf_new_char("()V");
3735         utf_init                = utf_new_char("<init>");
3736         utf_clinit              = utf_new_char("<clinit>");
3737         utf_initsystemclass = utf_new_char("initializeSystemClass");
3738         utf_systemclass     = utf_new_char("java/lang/System");
3739         utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
3740         utf_initialize      = utf_new_char("initialize");
3741         utf_initializedesc  = utf_new_char("(I)V");
3742
3743         utf_vmclass         = utf_new_char("java/lang/VMClass");
3744         utf_java_lang_Object= utf_new_char("java/lang/Object");
3745
3746         array_packagename   = utf_new_char("<the array package>");
3747
3748         /* create some important classes */
3749         /* These classes have to be created now because the classinfo
3750          * pointers are used in the loading code.
3751          */
3752         class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3753         class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3754         class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3755         class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3756
3757         if (verbose) log_text("loader_init: java/lang/Object");
3758         /* load the classes which were created above */
3759         loader_load_sysclass(NULL, class_java_lang_Object->name);
3760
3761         loader_inited = 1; /*JOWENN*/
3762
3763         loader_load_sysclass(&class_java_lang_Throwable,
3764                                                  utf_new_char("java/lang/Throwable"));
3765
3766         create_system_exception_classes();
3767
3768         /* create classes representing primitive types */
3769         create_primitive_classes();
3770
3771         /* create classes used by the typechecker */
3772         create_pseudo_classes();
3773
3774         /* correct vftbl-entries (retarded loading of class java/lang/String) */
3775         stringtable_update();
3776
3777 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3778         if (stackbottom!=0)
3779                 initLocks();
3780 #endif
3781         create_system_exception_proto_classes();
3782
3783         loader_inited = 1;
3784 }
3785
3786
3787 /********************* Function: loader_initclasses ****************************
3788
3789         Initializes all loaded but uninitialized classes
3790
3791 *******************************************************************************/
3792
3793 #if 0
3794 /* XXX TWISTI: i think we do not need this */
3795 void loader_initclasses ()
3796 {
3797         classinfo *c;
3798         
3799 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3800         pthread_mutex_lock(&compiler_mutex);
3801 #endif
3802
3803         intsDisable();                     /* schani */
3804
3805         if (makeinitializations) {
3806                 c = list_first(&linkedclasses);
3807                 while (c) {
3808                         class_init(c);
3809                         c = list_next(&linkedclasses, c);
3810                 }
3811         }
3812
3813         intsRestore();                      /* schani */
3814         
3815 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3816         pthread_mutex_unlock(&compiler_mutex);
3817 #endif
3818 }
3819 #endif
3820
3821
3822 static void loader_compute_class_values(classinfo *c)
3823 {
3824         classinfo *subs;
3825
3826         c->vftbl->baseval = ++classvalue;
3827
3828         subs = c->sub;
3829         while (subs != NULL) {
3830                 loader_compute_class_values(subs);
3831                 subs = subs->nextsub;
3832         }
3833         c->vftbl->diffval = classvalue - c->vftbl->baseval;
3834         
3835         /*
3836         {
3837         int i;
3838         for (i = 0; i < c->index; i++)
3839                 printf(" ");
3840         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
3841         utf_display(c->name);
3842         printf("\n");
3843         }
3844         */
3845 }
3846
3847
3848 void loader_compute_subclasses()
3849 {
3850         classinfo *c;
3851         
3852 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3853         intsDisable();                     /* schani */
3854 #endif
3855
3856         c = list_first(&linkedclasses);
3857         while (c) {
3858                 if (!(c->flags & ACC_INTERFACE)) {
3859                         c->nextsub = 0;
3860                         c->sub = 0;
3861                 }
3862                 c = list_next(&linkedclasses, c);
3863         }
3864
3865         c = list_first(&linkedclasses);
3866         while (c) {
3867                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3868                         c->nextsub = c->super->sub;
3869                         c->super->sub = c;
3870                 }
3871                 c = list_next(&linkedclasses, c);
3872         }
3873
3874         classvalue = 0;
3875 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3876         cast_lock();
3877 #endif
3878         loader_compute_class_values(class_java_lang_Object);
3879 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3880         cast_unlock();
3881 #endif
3882
3883 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3884         intsRestore();                      /* schani */
3885 #endif
3886 }
3887
3888
3889 /******************** function classloader_buffer ******************************
3890  
3891     sets buffer for reading classdata
3892
3893 *******************************************************************************/
3894
3895 void classload_buffer(u1 *buf, int len)
3896 {
3897         classbuffer      = buf;
3898         classbuffer_size = len;
3899         classbuf_pos     = buf - 1;
3900 }
3901
3902
3903 /******************** Function: loader_close ***********************************
3904
3905         Frees all resources
3906         
3907 *******************************************************************************/
3908
3909 void loader_close()
3910 {
3911         classinfo *c;
3912
3913         while ((c = list_first(&unloadedclasses))) {
3914                 list_remove(&unloadedclasses, c);
3915                 class_free(c);
3916         }
3917         while ((c = list_first(&unlinkedclasses))) {
3918                 list_remove(&unlinkedclasses, c);
3919                 class_free(c);
3920         }
3921         while ((c = list_first(&linkedclasses))) {
3922                 list_remove(&linkedclasses, c);
3923                 class_free(c);
3924         }
3925 }
3926
3927
3928 /*
3929  * These are local overrides for various environment variables in Emacs.
3930  * Please do not remove this and leave it at the end of the file, where
3931  * Emacs will automagically detect them.
3932  * ---------------------------------------------------------------------
3933  * Local variables:
3934  * mode: c
3935  * indent-tabs-mode: t
3936  * c-basic-offset: 4
3937  * tab-width: 4
3938  * End:
3939  */