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