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