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