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