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