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