15957bd0587e68aadb616cf7c5c6c636933d5e2c
[cacao.git] / src / vm / loader.c
1 /* loader.c - class loader functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28    Changes: Andreas Krall
29             Roman Obermaiser
30             Mark Probst
31                         Edwin Steiner
32
33    $Id: loader.c 726 2003-12-10 15:41:07Z 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                         u4 codelen;
968                         if (m -> jcode) panic ("Two code-attributes for one method!");
969                         
970                         suck_u4();
971                         m -> maxstack = suck_u2();
972                         m -> maxlocals = suck_u2();
973                         codelen = suck_u4();
974                         if (codelen == 0)
975                                 panic("bytecode has zero length");
976                         if (codelen > 65536)
977                                 panic("bytecode too long");
978                         m -> jcodelength = codelen;
979                         m -> jcode = MNEW (u1, m->jcodelength);
980                         suck_nbytes (m->jcode, m->jcodelength);
981                         m -> exceptiontablelength = suck_u2 ();
982                         m -> exceptiontable = 
983                            MNEW (exceptiontable, m->exceptiontablelength);
984
985 #ifdef STATISTICS
986         count_vmcode_len += m->jcodelength + 18;
987         count_extable_len += 8 * m->exceptiontablelength;
988 #endif
989
990                         for (e=0; e < m->exceptiontablelength; e++) {
991                                 u4 idx;
992                                 m -> exceptiontable[e].startpc = suck_u2();
993                                 m -> exceptiontable[e].endpc = suck_u2();
994                                 m -> exceptiontable[e].handlerpc = suck_u2();
995
996                                 idx = suck_u2();
997                                 if (!idx) m -> exceptiontable[e].catchtype = NULL;
998                                 else {
999                                         m -> exceptiontable[e].catchtype = 
1000                                       class_getconstant (c, idx, CONSTANT_Class);
1001                                         }
1002                                 }                       
1003
1004                         skipattributes ( suck_u2() );
1005                         }
1006                         
1007                 }
1008
1009 }
1010
1011 /********************* Function: method_free ***********************************
1012
1013         frees all memory that was allocated for this method
1014
1015 *******************************************************************************/
1016
1017 static void method_free (methodinfo *m)
1018 {
1019         if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1020         if (m->exceptiontable) 
1021                 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1022         if (m->mcode) CFREE (m->mcode, m->mcodelength);
1023         if (m->stubroutine) {
1024                 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1025                 else                       removecompilerstub (m->stubroutine);
1026                 }
1027 }
1028
1029
1030 /************** Function: method_display  (debugging only) **************/
1031
1032 void method_display (methodinfo *m)
1033 {
1034         printf ("   ");
1035         printflags (m -> flags);
1036         printf (" ");
1037         utf_display (m -> name);
1038         printf (" "); 
1039         utf_display (m -> descriptor);
1040         printf ("\n");
1041 }
1042
1043
1044 /******************** Function: method_canoverwrite ****************************
1045
1046         Check if m and old are identical with respect to type and name. This means
1047         that old can be overwritten with m.
1048         
1049 *******************************************************************************/  
1050
1051 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1052 {
1053         if (m->name != old->name) return false;
1054         if (m->descriptor != old->descriptor) return false;
1055         if (m->flags & ACC_STATIC) return false;
1056         return true;
1057 }
1058
1059
1060
1061
1062 /******************************************************************************/
1063 /************************ Functions for class *********************************/
1064 /******************************************************************************/
1065
1066
1067 /******************** function:: class_getconstant ******************************
1068
1069         retrieves the value at position 'pos' of the constantpool of a class
1070         if the type of the value is other than 'ctype' the system is stopped
1071
1072 *******************************************************************************/
1073
1074 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
1075 {
1076         /* invalid position in constantpool */  
1077         if (pos >= c->cpcount) 
1078                 panic ("Attempt to access constant outside range");
1079
1080         /* check type of constantpool entry */
1081
1082         if (c->cptags[pos] != ctype) {
1083                 class_showconstantpool(c);
1084                 error ("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1085                  (int) ctype, (int) c->cptags[pos] );
1086                 }
1087                 
1088         return c->cpinfos[pos];
1089 }
1090
1091
1092 /********************* Function: class_constanttype ****************************
1093
1094         Determines the type of a class entry in the ConstantPool
1095         
1096 *******************************************************************************/
1097
1098 u4 class_constanttype (classinfo *c, u4 pos)
1099 {
1100         if (pos >= c->cpcount) 
1101                 panic ("Attempt to access constant outside range");
1102         return c->cptags[pos];
1103 }
1104
1105
1106 /******************** function: class_loadcpool ********************************
1107
1108         loads the constantpool of a class, 
1109         the entries are transformed into a simpler format 
1110         by resolving references
1111         (a detailed overview of the compact structures can be found in global.h)        
1112
1113 *******************************************************************************/
1114
1115 static void class_loadcpool (classinfo *c)
1116 {
1117
1118         /* The following structures are used to save information which cannot be 
1119            processed during the first pass. After the complete constantpool has 
1120            been traversed the references can be resolved. 
1121            (only in specific order)                                                */
1122         
1123         /* CONSTANT_Class_info entries */
1124         typedef struct forward_class {      
1125                 struct forward_class *next; 
1126                 u2 thisindex;               
1127                 u2 name_index;              
1128         } forward_class;                    
1129                                         
1130         /* CONSTANT_String */                                      
1131         typedef struct forward_string { 
1132                 struct forward_string *next; 
1133                 u2 thisindex;                
1134                 u2 string_index;
1135         } forward_string;
1136
1137         /* CONSTANT_NameAndType */
1138         typedef struct forward_nameandtype {
1139                 struct forward_nameandtype *next;
1140                 u2 thisindex;
1141                 u2 name_index;
1142                 u2 sig_index;
1143         } forward_nameandtype;
1144
1145         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1146         typedef struct forward_fieldmethint {   
1147                 struct forward_fieldmethint *next;
1148                 u2 thisindex;
1149                 u1 tag;
1150                 u2 class_index;
1151                 u2 nameandtype_index;
1152         } forward_fieldmethint;
1153
1154
1155         u4 idx;
1156         long int dumpsize = dump_size ();
1157
1158         forward_class *forward_classes = NULL;
1159         forward_string *forward_strings = NULL;
1160         forward_nameandtype *forward_nameandtypes = NULL;
1161         forward_fieldmethint *forward_fieldmethints = NULL;
1162
1163         /* number of entries in the constant_pool table  */
1164         u4 cpcount       = c -> cpcount = suck_u2();
1165         /* allocate memory */
1166         u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
1167         voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1168
1169 #ifdef STATISTICS
1170         count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1171 #endif
1172         
1173         /* initialize constantpool */
1174         for (idx=0; idx<cpcount; idx++) {
1175                 cptags[idx] = CONSTANT_UNUSED;
1176                 cpinfos[idx] = NULL;
1177                 }
1178
1179                         
1180                 /******* first pass *******/
1181                 /* entries which cannot be resolved now are written into 
1182                    temporary structures and traversed again later        */
1183                    
1184         idx = 1;
1185         while (idx < cpcount) {
1186                 /* get constant type */
1187                 u4 t = suck_u1 (); 
1188                 switch ( t ) {
1189
1190                         case CONSTANT_Class: { 
1191                                 forward_class *nfc = DNEW(forward_class);
1192
1193                                 nfc -> next = forward_classes;                                                                                  
1194                                 forward_classes = nfc;
1195
1196                                 nfc -> thisindex = idx;
1197                                 /* reference to CONSTANT_NameAndType */
1198                                 nfc -> name_index = suck_u2 (); 
1199
1200                                 idx++;
1201                                 break;
1202                                 }
1203                         
1204                         case CONSTANT_Fieldref:
1205                         case CONSTANT_Methodref:
1206                         case CONSTANT_InterfaceMethodref: { 
1207                                 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1208                                 
1209                                 nff -> next = forward_fieldmethints;
1210                                 forward_fieldmethints = nff;
1211
1212                                 nff -> thisindex = idx;
1213                                 /* constant type */
1214                                 nff -> tag = t;
1215                                 /* class or interface type that contains the declaration of the field or method */
1216                                 nff -> class_index = suck_u2 (); 
1217                                 /* name and descriptor of the field or method */
1218                                 nff -> nameandtype_index = suck_u2 ();
1219
1220                                 idx ++;
1221                                 break;
1222                                 }
1223                                 
1224                         case CONSTANT_String: {
1225                                 forward_string *nfs = DNEW (forward_string);
1226                                 
1227                                 nfs -> next = forward_strings;
1228                                 forward_strings = nfs;
1229                                 
1230                                 nfs -> thisindex = idx;
1231                                 /* reference to CONSTANT_Utf8_info with string characters */
1232                                 nfs -> string_index = suck_u2 ();
1233                                 
1234                                 idx ++;
1235                                 break;
1236                                 }
1237
1238                         case CONSTANT_NameAndType: {
1239                                 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1240                                 
1241                                 nfn -> next = forward_nameandtypes;
1242                                 forward_nameandtypes = nfn;
1243                                 
1244                                 nfn -> thisindex = idx;
1245                                 /* reference to CONSTANT_Utf8_info containing simple name */
1246                                 nfn -> name_index = suck_u2 ();
1247                                 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1248                                 nfn -> sig_index = suck_u2 ();
1249                                 
1250                                 idx ++;
1251                                 break;
1252                                 }
1253
1254                         case CONSTANT_Integer: {
1255                                 constant_integer *ci = NEW (constant_integer);
1256
1257 #ifdef STATISTICS
1258         count_const_pool_len += sizeof(constant_integer);
1259 #endif
1260
1261                                 ci -> value = suck_s4 ();
1262                                 cptags [idx] = CONSTANT_Integer;
1263                                 cpinfos [idx] = ci;
1264                                 idx ++;
1265                                 
1266                                 break;
1267                                 }
1268                                 
1269                         case CONSTANT_Float: {
1270                                 constant_float *cf = NEW (constant_float);
1271
1272 #ifdef STATISTICS
1273         count_const_pool_len += sizeof(constant_float);
1274 #endif
1275
1276                                 cf -> value = suck_float ();
1277                                 cptags [idx] = CONSTANT_Float;
1278                                 cpinfos[idx] = cf;
1279                                 idx ++;
1280                                 break;
1281                                 }
1282                                 
1283                         case CONSTANT_Long: {
1284                                 constant_long *cl = NEW(constant_long);
1285                                         
1286 #ifdef STATISTICS
1287         count_const_pool_len += sizeof(constant_long);
1288 #endif
1289
1290                                 cl -> value = suck_s8 ();
1291                                 cptags [idx] = CONSTANT_Long;
1292                                 cpinfos [idx] = cl;
1293                                 idx += 2;
1294                                 break;
1295                                 }
1296                         
1297                         case CONSTANT_Double: {
1298                                 constant_double *cd = NEW(constant_double);
1299                                 
1300 #ifdef STATISTICS
1301         count_const_pool_len += sizeof(constant_double);
1302 #endif
1303
1304                                 cd -> value = suck_double ();
1305                                 cptags [idx] = CONSTANT_Double;
1306                                 cpinfos [idx] = cd;
1307                                 idx += 2;
1308                                 break;
1309                                 }
1310                                 
1311                         case CONSTANT_Utf8: { 
1312
1313                                 /* number of bytes in the bytes array (not string-length) */
1314                                 u4 length = suck_u2();
1315                                 cptags [idx]  = CONSTANT_Utf8;
1316                                 /* validate the string */
1317                                 ASSERT_LEFT(length);
1318                                 if (!is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1319                                         panic("Invalid UTF-8 string"); 
1320                                 /* insert utf-string into the utf-symboltable */
1321                                 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1322                                 /* skip bytes of the string */
1323                                 skip_nbytes(length);
1324                                 idx++;
1325                                 break;
1326                                 }
1327                                                                                 
1328                         default:
1329                                 error ("Unkown constant type: %d",(int) t);
1330                 
1331                         }  /* end switch */
1332                         
1333                 } /* end while */
1334                 
1335
1336
1337            /* resolve entries in temporary structures */
1338
1339         while (forward_classes) {
1340                 utf *name =
1341                   class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1342
1343                 cptags  [forward_classes -> thisindex] = CONSTANT_Class;
1344                 /* retrieve class from class-table */
1345                 cpinfos [forward_classes -> thisindex] = class_new (name);
1346
1347                 forward_classes = forward_classes -> next;
1348                 
1349                 }
1350
1351         while (forward_strings) {
1352                 utf *text = 
1353                   class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1354 /*
1355                 log_text("forward_string:");
1356                 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1357                 utf_display(text);
1358                 log_text("\n------------------"); */
1359                 /* resolve utf-string */                
1360                 cptags   [forward_strings -> thisindex] = CONSTANT_String;
1361                 cpinfos  [forward_strings -> thisindex] = text;
1362                 
1363                 forward_strings = forward_strings -> next;
1364                 }       
1365
1366         while (forward_nameandtypes) {
1367                 constant_nameandtype *cn = NEW (constant_nameandtype);  
1368
1369 #ifdef STATISTICS
1370                 count_const_pool_len += sizeof(constant_nameandtype);
1371 #endif
1372
1373                 /* resolve simple name and descriptor */
1374                 cn -> name = class_getconstant 
1375                    (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1376                 cn -> descriptor = class_getconstant
1377                    (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1378                  
1379                 cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1380                 cpinfos  [forward_nameandtypes -> thisindex] = cn;
1381                 
1382                 forward_nameandtypes = forward_nameandtypes -> next;
1383                 }
1384
1385
1386         while (forward_fieldmethints)  {
1387                 constant_nameandtype *nat;
1388                 constant_FMIref *fmi = NEW (constant_FMIref);
1389
1390 #ifdef STATISTICS
1391                 count_const_pool_len += sizeof(constant_FMIref);
1392 #endif
1393                 /* resolve simple name and descriptor */
1394                 nat = class_getconstant
1395                         (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1396
1397 #ifdef JOWENN_DEBUG
1398                 log_text("trying to resolve:");
1399                 log_text(nat->name->text);
1400                 switch(forward_fieldmethints ->tag) {
1401                 case CONSTANT_Fieldref: 
1402                                 log_text("CONSTANT_Fieldref");
1403                                 break;
1404                 case CONSTANT_InterfaceMethodref: 
1405                                 log_text("CONSTANT_InterfaceMethodref");
1406                                 break;
1407                 case CONSTANT_Methodref: 
1408                                 log_text("CONSTANT_Methodref");
1409                                 break;
1410                 }
1411 #endif
1412                 fmi -> class = class_getconstant 
1413                         (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1414                 fmi -> name = nat -> name;
1415                 fmi -> descriptor = nat -> descriptor;
1416
1417                 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1418                 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1419         
1420                 switch (forward_fieldmethints -> tag) {
1421                 case CONSTANT_Fieldref:  /* check validity of descriptor */
1422                                          checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1423                                          break;
1424                 case CONSTANT_InterfaceMethodref: 
1425                 case CONSTANT_Methodref: /* check validity of descriptor */
1426                         /* XXX check special names (<init>) */
1427                                          checkmethoddescriptor (fmi->descriptor);
1428                                          break;
1429                 }               
1430         
1431                 forward_fieldmethints = forward_fieldmethints -> next;
1432
1433                 }
1434
1435 /*      class_showconstantpool(c); */
1436
1437         dump_release (dumpsize);
1438 }
1439
1440
1441 /********************** Function: class_load ***********************************
1442         
1443         Loads everything interesting about a class from the class file. The
1444         'classinfo' structure must have been allocated previously.
1445
1446         The super class and the interfaces implemented by this class need not be
1447         loaded. The link is set later by the function 'class_link'.
1448
1449         The loaded class is removed from the list 'unloadedclasses' and added to
1450         the list 'unlinkedclasses'.
1451         
1452 *******************************************************************************/
1453
1454 static int class_load(classinfo *c)
1455 {
1456         u4 i;
1457         u4 mi,ma;
1458
1459 #ifdef STATISTICS
1460         count_class_loads++;
1461 #endif
1462
1463         /* output for debugging purposes */
1464         if (loadverbose) {              
1465                 char logtext[MAXLOGTEXT];
1466                 sprintf(logtext, "Loading class: ");
1467                 utf_sprint(logtext+strlen(logtext), c->name);
1468                 dolog(logtext);
1469         }
1470         
1471         /* load classdata, throw exception on error */
1472
1473         if (!suck_start(c->name)) {
1474                 throw_classnotfoundexception2(c->name);
1475                 return false;
1476         }
1477         
1478         /* check signature */           
1479         if (suck_u4() != MAGIC) panic("Can not find class-file signature");     
1480         /* check version */
1481         mi = suck_u2(); 
1482         ma = suck_u2();
1483         if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1484                 error ("File version %d.%d is not supported",
1485                                  (int) ma, (int) mi);
1486                 }
1487
1488         class_loadcpool (c);
1489         /*JOWENN*/
1490         c->erroneous_state=0;
1491         c->initializing_thread=0;       
1492         /*JOWENN*/
1493         c -> classUsed = NOTUSED; /* not used initially CO-RT */
1494         c -> impldBy = NULL;
1495
1496         /* ACC flags */
1497         c -> flags = suck_u2 (); 
1498         /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1499
1500         /* this class */
1501         suck_u2 ();       
1502         
1503         /* retrieve superclass */
1504         if ( (i = suck_u2 () ) ) {
1505                 c -> super = class_getconstant (c, i, CONSTANT_Class);
1506                 }
1507         else {
1508                 c -> super = NULL;
1509                 }
1510                          
1511         /* retrieve interfaces */
1512         c -> interfacescount = suck_u2 ();
1513         c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1514         for (i=0; i < c -> interfacescount; i++) {
1515                 c -> interfaces [i] = 
1516                       class_getconstant (c, suck_u2(), CONSTANT_Class);
1517                 }
1518
1519         /* load fields */
1520         c -> fieldscount = suck_u2 ();
1521 /*      utf_display(c->name);
1522         printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1523
1524         c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1525         for (i=0; i < c -> fieldscount; i++) {
1526                 field_load (&(c->fields[i]), c);
1527                 }
1528
1529         /* load methods */
1530         c -> methodscount = suck_u2 ();
1531         c -> methods = MNEW (methodinfo, c -> methodscount);
1532         for (i=0; i < c -> methodscount; i++) {
1533                 method_load (&(c -> methods [i]), c);
1534                 }
1535
1536 #ifdef STATISTICS
1537         count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1538         count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1539         count_class_infos += sizeof(methodinfo) * c -> methodscount;
1540 #endif
1541
1542         /* load variable-length attribute structures */ 
1543         attribute_load (suck_u2(), c);
1544
1545         /* free memory */
1546         suck_stop ();
1547
1548         /* remove class from list of unloaded classes and 
1549            add to list of unlinked classes                */
1550         list_remove (&unloadedclasses, c);
1551         list_addlast (&unlinkedclasses, c);
1552         c->loaded=true;
1553         return true;
1554 }
1555
1556
1557
1558 /************** internal Function: class_highestinterface ***********************
1559
1560         Used by the function class_link to determine the amount of memory needed
1561         for the interface table.
1562
1563 *******************************************************************************/
1564
1565 static s4 class_highestinterface (classinfo *c) 
1566 {
1567         s4 h;
1568         s4 i;
1569         
1570         if ( ! (c->flags & ACC_INTERFACE) ) {
1571                 char logtext[MAXLOGTEXT];
1572                 sprintf (logtext, "Interface-methods count requested for non-interface:  ");
1573         utf_sprint (logtext+strlen(logtext), c->name);
1574         error(logtext);
1575         }
1576     
1577     h = c->index;
1578         for (i=0; i<c->interfacescount; i++) {
1579                 s4 h2 = class_highestinterface (c->interfaces[i]);
1580                 if (h2>h) h=h2;
1581                 }
1582         return h;
1583 }
1584
1585
1586 /* class_addinterface **********************************************************
1587
1588         Is needed by class_link for adding a VTBL to a class. All interfaces
1589         implemented by ic are added as well.
1590
1591 *******************************************************************************/        
1592
1593 static void class_addinterface (classinfo *c, classinfo *ic)
1594 {
1595         s4     j, m;
1596         s4     i     = ic->index;
1597         vftbl *vftbl = c->vftbl;
1598         
1599         if (i >= vftbl->interfacetablelength)
1600                 panic ("Inernal error: interfacetable overflow");
1601         if (vftbl->interfacetable[-i])
1602                 return;
1603
1604         if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
1605                 vftbl->interfacevftbllength[i] = 1;
1606                 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1607                 vftbl->interfacetable[-i][0] = NULL;
1608                 }
1609         else {
1610                 vftbl->interfacevftbllength[i] = ic->methodscount;
1611                 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
1612
1613 #ifdef STATISTICS
1614         count_vftbl_len += sizeof(methodptr) *
1615                                  (ic->methodscount + (ic->methodscount == 0));
1616 #endif
1617
1618                 for (j=0; j<ic->methodscount; j++) {
1619                         classinfo *sc = c;
1620                         while (sc) {
1621                                 for (m = 0; m < sc->methodscount; m++) {
1622                                         methodinfo *mi = &(sc->methods[m]);
1623                                         if (method_canoverwrite(mi, &(ic->methods[j]))) {
1624                                                 vftbl->interfacetable[-i][j] = 
1625                                                                           vftbl->table[mi->vftblindex];
1626                                                 goto foundmethod;
1627                                                 }
1628                                         }
1629                                 sc = sc->super;
1630                                 }
1631                          foundmethod: ;
1632                         }
1633                 }
1634
1635         for (j = 0; j < ic->interfacescount; j++) 
1636                 class_addinterface(c, ic->interfaces[j]);
1637 }
1638
1639
1640 /******************* Function: class_new_array *********************************
1641
1642     This function is called by class_new to setup an array class.
1643
1644 *******************************************************************************/
1645
1646 void
1647 class_new_array(classinfo *c)
1648 {
1649         classinfo *comp = NULL;
1650         methodinfo *clone;
1651         int namelen;
1652
1653         /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1654
1655         /* Array classes are not loaded from classfiles. */
1656         list_remove (&unloadedclasses, c);
1657
1658         /* Check array class name */
1659         namelen = c->name->blength;
1660         if (namelen < 2 || c->name->text[0] != '[')
1661                 panic("Invalid array class name");
1662
1663         /* Check the component type */
1664         switch (c->name->text[1]) {
1665           case '[':
1666                   /* c is an array of arrays. We have to create the component class. */
1667                   comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1668                   break;
1669
1670           case 'L':
1671                   /* c is an array of objects. */
1672                   if (namelen < 4 || c->name->text[namelen-1] != ';')
1673                           panic("Invalid array class name");
1674                   comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1675                   break;
1676         }
1677
1678         /* Setup the array class */
1679         c->super = class_java_lang_Object;
1680         c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1681
1682     c->interfacescount = 2;
1683     c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1684     c->interfaces[0] = class_java_lang_Cloneable;
1685     c->interfaces[1] = class_java_io_Serializable;
1686
1687         c->methodscount = 1;
1688         c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1689
1690         clone = c->methods;
1691         memset(clone,0,sizeof(methodinfo));
1692         clone->flags = ACC_PUBLIC; /* XXX protected? */
1693         clone->name = utf_new_char("clone");
1694         clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1695         clone->class = c;
1696         clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1697         clone->monoPoly = MONO; /* XXX should be poly? */
1698
1699         /* XXX: field: length? */
1700
1701         /* The array class has to be linked */
1702         list_addlast(&unlinkedclasses,c);
1703         
1704         /*
1705      * Array classes which are created after the other classes have been
1706      * loaded and linked are linked explicitely.
1707      */
1708         c->loaded=true;
1709      
1710         if (loader_inited)
1711                 loader_load(c->name); /* XXX handle errors */
1712 }
1713
1714 /****************** Function: class_link_array *********************************
1715
1716     This function is called by class_link to create the
1717     arraydescriptor for an array class.
1718
1719     This function returns NULL if the array cannot be linked because
1720     the component type has not been linked yet.
1721
1722 *******************************************************************************/
1723
1724 static
1725 arraydescriptor *
1726 class_link_array(classinfo *c)
1727 {
1728         classinfo *comp = NULL;
1729         int namelen = c->name->blength;
1730         arraydescriptor *desc;
1731         vftbl *compvftbl;
1732
1733         /* Check the component type */
1734         switch (c->name->text[1]) {
1735           case '[':
1736                   /* c is an array of arrays. */
1737                   comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1738                   if (!comp) panic("Could not find component array class.");
1739                   break;
1740
1741           case 'L':
1742                   /* c is an array of objects. */
1743                   comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1744                   if (!comp) panic("Could not find component class.");
1745                   break;
1746         }
1747
1748         /* If the component type has not been linked return NULL */
1749         if (comp && !comp->linked)
1750                 return NULL;
1751
1752         /* Allocate the arraydescriptor */
1753         desc = NEW(arraydescriptor);
1754
1755         if (comp) {
1756                 /* c is an array of references */
1757                 desc->arraytype = ARRAYTYPE_OBJECT;
1758                 desc->componentsize = sizeof(void*);
1759                 desc->dataoffset = OFFSET(java_objectarray,data);
1760                 
1761                 compvftbl = comp->vftbl;
1762                 if (!compvftbl)
1763                         panic("Component class has no vftbl.");
1764                 desc->componentvftbl = compvftbl;
1765                 
1766                 if (compvftbl->arraydesc) {
1767                         desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1768                         desc->dimension = compvftbl->arraydesc->dimension + 1;
1769                         desc->elementtype = compvftbl->arraydesc->elementtype;
1770                 }
1771                 else {
1772                         desc->elementvftbl = compvftbl;
1773                         desc->dimension = 1;
1774                         desc->elementtype = ARRAYTYPE_OBJECT;
1775                 }
1776         }
1777         else {
1778                 /* c is an array of a primitive type */
1779                 switch (c->name->text[1]) {
1780                   case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1781                             desc->dataoffset = OFFSET(java_booleanarray,data);
1782                                 desc->componentsize = sizeof(u1); break;
1783                   case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1784                             desc->dataoffset = OFFSET(java_bytearray,data);
1785                                 desc->componentsize = sizeof(u1); break;
1786                   case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1787                             desc->dataoffset = OFFSET(java_chararray,data);
1788                                 desc->componentsize = sizeof(u2); break;
1789                   case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1790                             desc->dataoffset = OFFSET(java_doublearray,data);
1791                                 desc->componentsize = sizeof(double); break;
1792                   case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1793                             desc->dataoffset = OFFSET(java_floatarray,data);
1794                                 desc->componentsize = sizeof(float); break;
1795                   case 'I': desc->arraytype = ARRAYTYPE_INT;
1796                             desc->dataoffset = OFFSET(java_intarray,data);
1797                                 desc->componentsize = sizeof(s4); break;
1798                   case 'J': desc->arraytype = ARRAYTYPE_LONG;
1799                             desc->dataoffset = OFFSET(java_longarray,data);
1800                                 desc->componentsize = sizeof(s8); break;
1801                   case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1802                             desc->dataoffset = OFFSET(java_shortarray,data);
1803                                 desc->componentsize = sizeof(s2); break;
1804                   default:
1805                           panic("Invalid array class name");
1806                 }
1807                 
1808                 desc->componentvftbl = NULL;
1809                 desc->elementvftbl = NULL;
1810                 desc->dimension = 1;
1811                 desc->elementtype = desc->arraytype;
1812         }
1813
1814         return desc;
1815 }
1816
1817 /********************** Function: class_link ***********************************
1818
1819         Tries to link a class. The super class and every implemented interface must
1820         already have been linked. The function calculates the length in bytes that
1821         an instance of this class requires as well as the VTBL for methods and
1822         interface methods.
1823         
1824         If the class can be linked, it is removed from the list 'unlinkedclasses'
1825         and added to 'linkedclasses'. Otherwise, it is moved to the end of
1826         'unlinkedclasses'.
1827
1828         Attention: If cyclical class definitions are encountered, the program gets
1829         into an infinite loop (we'll have to work that out)
1830
1831 *******************************************************************************/
1832
1833 void class_link(classinfo *c)
1834 {
1835         s4 supervftbllength;          /* vftbllegnth of super class               */
1836         s4 vftbllength;               /* vftbllength of current class             */
1837         s4 interfacetablelength;      /* interface table length                   */
1838         classinfo *super = c->super;  /* super class                              */
1839         classinfo *ic, *c2;           /* intermediate class variables             */
1840         vftbl *v;                     /* vftbl of current class                   */
1841         s4 i;                         /* interface/method/field counter           */
1842         arraydescriptor *arraydesc = NULL;  /* descriptor for array classes       */
1843
1844
1845         /*  check if all superclasses are already linked, if not put c at end of
1846             unlinked list and return. Additionally initialize class fields.       */
1847
1848         /*  check interfaces */
1849
1850         for (i = 0; i < c->interfacescount; i++) {
1851                 ic = c->interfaces[i];
1852                 if (!ic->linked) {
1853                         list_remove(&unlinkedclasses, c);
1854                         list_addlast(&unlinkedclasses, c);
1855                         return; 
1856                 }
1857         }
1858         
1859         /*  check super class */
1860
1861         if (super == NULL) {          /* class java.long.Object */
1862                 c->index = 0;
1863         c->classUsed = USED;     /* Object class is always used CO-RT*/
1864                 c -> impldBy = NULL;
1865                 c->instancesize = sizeof(java_objectheader);
1866                 
1867                 vftbllength = supervftbllength = 0;
1868
1869                 c->finalizer = NULL;
1870         }
1871         else {
1872                 if (!super->linked) {
1873                         list_remove(&unlinkedclasses, c);
1874                         list_addlast(&unlinkedclasses, c);
1875                         return; 
1876                 }
1877
1878                 /* handle array classes */
1879                 if (c->name->text[0] == '[')
1880                         if ((arraydesc = class_link_array(c)) == NULL) {
1881                                 list_remove(&unlinkedclasses, c);
1882                                 list_addlast(&unlinkedclasses, c);
1883                                 return; 
1884                         }
1885                 
1886                 if (c->flags & ACC_INTERFACE)
1887                         c->index = interfaceindex++;
1888                 else
1889                         c->index = super->index + 1;
1890                 
1891                 c->instancesize = super->instancesize;
1892                 
1893                 vftbllength = supervftbllength = super->vftbl->vftbllength;
1894                 
1895                 c->finalizer = super->finalizer;
1896         }
1897
1898
1899         if (linkverbose) {
1900                 char logtext[MAXLOGTEXT];
1901                 sprintf (logtext, "Linking Class: ");
1902                 utf_sprint (logtext+strlen(logtext), c->name );
1903                 dolog (logtext);
1904         }
1905
1906         /* compute vftbl length */
1907
1908         for (i = 0; i < c->methodscount; i++) {
1909                 methodinfo *m = &(c->methods[i]);
1910                         
1911                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1912                         classinfo *sc = super;
1913                         while (sc) {
1914                                 int j;
1915                                 for (j = 0; j < sc->methodscount; j++) {
1916                                         if (method_canoverwrite(m, &(sc->methods[j]))) {
1917                                                 m->vftblindex = sc->methods[j].vftblindex;
1918                                                 goto foundvftblindex;
1919                                         }
1920                                 }
1921                                 sc = sc->super;
1922                         }
1923                         m->vftblindex = (vftbllength++);
1924                 foundvftblindex: ;
1925                 }
1926         }       
1927         
1928 #ifdef STATISTICS
1929         count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1930 #endif
1931
1932         /* compute interfacetable length */
1933
1934         interfacetablelength = 0;
1935         c2 = c;
1936         while (c2) {
1937                 for (i = 0; i < c2->interfacescount; i++) {
1938                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1939                         if (h > interfacetablelength)
1940                                 interfacetablelength = h;
1941                 }
1942                 c2 = c2->super;
1943         }
1944
1945         /* allocate virtual function table */
1946
1947         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1948                                                    (vftbllength - 1) + sizeof(methodptr*) *
1949                                                    (interfacetablelength - (interfacetablelength > 0)));
1950         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1951                                   (interfacetablelength > 1));
1952         c->header.vftbl = c->vftbl = v;
1953         v->class = c;
1954         v->vftbllength = vftbllength;
1955         v->interfacetablelength = interfacetablelength;
1956         v->arraydesc = arraydesc;
1957
1958         /* store interface index in vftbl */
1959         if (c->flags & ACC_INTERFACE)
1960                 v->baseval = -(c->index);
1961
1962         /* copy virtual function table of super class */
1963
1964         for (i = 0; i < supervftbllength; i++) 
1965                 v->table[i] = super->vftbl->table[i];
1966         
1967         /* add method stubs into virtual function table */
1968
1969         for (i = 0; i < c->methodscount; i++) {
1970                 methodinfo *m = &(c->methods[i]);
1971                 if (!(m->flags & ACC_STATIC)) {
1972                         v->table[m->vftblindex] = m->stubroutine;
1973                 }
1974         }
1975
1976         /* compute instance size and offset of each field */
1977         
1978         for (i = 0; i < c->fieldscount; i++) {
1979                 s4 dsize;
1980                 fieldinfo *f = &(c->fields[i]);
1981                 
1982                 if (!(f->flags & ACC_STATIC) ) {
1983                         dsize = desc_typesize (f->descriptor);
1984                         c->instancesize = ALIGN (c->instancesize, dsize);
1985                         f->offset = c->instancesize;
1986                         c->instancesize += dsize;
1987                 }
1988         }
1989
1990         /* initialize interfacetable and interfacevftbllength */
1991         
1992         v->interfacevftbllength = MNEW (s4, interfacetablelength);
1993
1994 #ifdef STATISTICS
1995         count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1996 #endif
1997
1998         for (i = 0; i < interfacetablelength; i++) {
1999                 v->interfacevftbllength[i] = 0;
2000                 v->interfacetable[-i] = NULL;
2001         }
2002         
2003         /* add interfaces */
2004         
2005         for (c2 = c; c2 != NULL; c2 = c2->super)
2006                 for (i = 0; i < c2->interfacescount; i++) {
2007                         class_addinterface (c, c2->interfaces[i]);
2008                 }
2009
2010         /* add finalizer method (not for java.lang.Object) */
2011
2012         if (super != NULL) {
2013                 methodinfo *fi;
2014                 static utf *finame = NULL;
2015                 static utf *fidesc = NULL;
2016
2017                 if (finame == NULL)
2018                         finame = utf_finalize;
2019                 if (fidesc == NULL)
2020                         fidesc = utf_fidesc;
2021
2022                 fi = class_findmethod (c, finame, fidesc);
2023                 if (fi != NULL) {
2024                         if (!(fi->flags & ACC_STATIC)) {
2025                                 c->finalizer = fi;
2026                         }
2027                 }
2028         }
2029
2030         /* final tasks */
2031
2032         c->linked = true;       
2033
2034         list_remove (&unlinkedclasses, c);
2035         list_addlast (&linkedclasses, c);
2036
2037 }
2038
2039
2040 /******************* Function: class_freepool **********************************
2041
2042         Frees all resources used by this classes Constant Pool.
2043
2044 *******************************************************************************/
2045
2046 static void class_freecpool (classinfo *c)
2047 {
2048         u4 idx;
2049         u4 tag;
2050         voidptr info;
2051         
2052         for (idx=0; idx < c->cpcount; idx++) {
2053                 tag = c->cptags[idx];
2054                 info = c->cpinfos[idx];
2055                 
2056                 if (info != NULL) {
2057                         switch (tag) {
2058                         case CONSTANT_Fieldref:
2059                         case CONSTANT_Methodref:
2060                         case CONSTANT_InterfaceMethodref:
2061                                 FREE (info, constant_FMIref);
2062                                 break;
2063                         case CONSTANT_Integer:
2064                                 FREE (info, constant_integer);
2065                                 break;
2066                         case CONSTANT_Float:
2067                                 FREE (info, constant_float);
2068                                 break;
2069                         case CONSTANT_Long:
2070                                 FREE (info, constant_long);
2071                                 break;
2072                         case CONSTANT_Double:
2073                                 FREE (info, constant_double);
2074                                 break;
2075                         case CONSTANT_NameAndType:
2076                                 FREE (info, constant_nameandtype);
2077                                 break;
2078                         }
2079                         }
2080                 }
2081
2082         MFREE (c -> cptags,  u1, c -> cpcount);
2083         MFREE (c -> cpinfos, voidptr, c -> cpcount);
2084 }
2085
2086
2087 /*********************** Function: class_free **********************************
2088
2089         Frees all resources used by the class.
2090
2091 *******************************************************************************/
2092
2093 static void class_free (classinfo *c)
2094 {
2095         s4 i;
2096         vftbl *v;
2097                 
2098         class_freecpool (c);
2099
2100         MFREE (c->interfaces, classinfo*, c->interfacescount);
2101
2102         for (i = 0; i < c->fieldscount; i++)
2103                 field_free(&(c->fields[i]));
2104         
2105         for (i = 0; i < c->methodscount; i++)
2106                 method_free(&(c->methods[i]));
2107         MFREE (c->methods, methodinfo, c->methodscount);
2108
2109         if ((v = c->vftbl) != NULL) {
2110                 if (v->arraydesc)
2111                         mem_free(v->arraydesc,sizeof(arraydescriptor));
2112                 
2113                 for (i = 0; i < v->interfacetablelength; i++) {
2114                         MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2115                         }
2116                 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2117
2118                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2119                     sizeof(methodptr*) * (v->interfacetablelength -
2120                                          (v->interfacetablelength > 0));
2121                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2122                                              (v->interfacetablelength > 1));
2123                 mem_free (v, i);
2124                 }
2125
2126         if (c->innerclasscount)
2127                 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2128
2129         /*      if (c->classvftbl)
2130                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2131         
2132         FREE (c, classinfo);
2133 }
2134
2135 /************************* Function: class_findfield ***************************
2136         
2137         Searches a 'classinfo' structure for a field having the given name and
2138         type.
2139
2140 *******************************************************************************/
2141
2142
2143 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2144 {
2145         s4 i;
2146
2147         
2148         for (i = 0; i < c->fieldscount; i++) { 
2149                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
2150                         return &(c->fields[i]);                                                         
2151     }
2152
2153         panic ("Can not find field given in CONSTANT_Fieldref");
2154         return NULL;
2155 }
2156
2157
2158 /************************* Function: class_findmethod **************************
2159         
2160         Searches a 'classinfo' structure for a method having the given name and
2161         type and returns the index in the class info structure.
2162         If type is NULL, it is ignored.
2163
2164 *******************************************************************************/
2165
2166 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2167 {
2168         s4 i;
2169 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2170         char *buffer;                   
2171         int buffer_len, pos;
2172 #endif
2173 #ifdef JOWENN_DEBUG1
2174
2175         buffer_len = 
2176           utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2177         
2178         buffer = MNEW(char, buffer_len);
2179
2180         strcpy(buffer, "class_findmethod: method:");
2181         utf_sprint(buffer+strlen(buffer), name);
2182         strcpy(buffer+strlen(buffer), ", desc: ");
2183         utf_sprint(buffer+strlen(buffer), desc);
2184         strcpy(buffer+strlen(buffer), ", classname: ");
2185         utf_sprint(buffer+strlen(buffer), c->name);
2186         
2187         log_text(buffer);       
2188
2189         MFREE(buffer, char, buffer_len);
2190 #endif  
2191         for (i = 0; i < c->methodscount; i++) {
2192 #ifdef JOWENN_DEBUG2
2193                 buffer_len = 
2194                   utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2195         
2196                 buffer = MNEW(char, buffer_len);
2197
2198                 strcpy(buffer, "class_findmethod: comparing to method:");
2199                 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2200                 strcpy(buffer+strlen(buffer), ", desc: ");
2201                 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2202         
2203                 log_text(buffer);       
2204
2205                 MFREE(buffer, char, buffer_len);
2206 #endif  
2207                 
2208                 
2209                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2210                                                    (c->methods[i].descriptor == desc)))
2211                         return i;
2212                 }
2213 #ifdef JOWENN_DEBUG2    
2214         class_showconstantpool(c);
2215         log_text("class_findmethod: returning NULL");
2216 #endif
2217         return -1;
2218 }
2219
2220
2221
2222 /************************* Function: class_findmethod **************************
2223         
2224         Searches a 'classinfo' structure for a method having the given name and
2225         type.
2226         If type is NULL, it is ignored.
2227
2228 *******************************************************************************/
2229
2230 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2231 {
2232 #if 0
2233         s4 i;
2234 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2235         char *buffer;                   
2236         int buffer_len, pos;
2237 #endif
2238 #ifdef JOWENN_DEBUG1
2239
2240         buffer_len = 
2241           utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2242         
2243         buffer = MNEW(char, buffer_len);
2244
2245         strcpy(buffer, "class_findmethod: method:");
2246         utf_sprint(buffer+strlen(buffer), name);
2247         strcpy(buffer+strlen(buffer), ", desc: ");
2248         utf_sprint(buffer+strlen(buffer), desc);
2249         strcpy(buffer+strlen(buffer), ", classname: ");
2250         utf_sprint(buffer+strlen(buffer), c->name);
2251         
2252         log_text(buffer);       
2253
2254         MFREE(buffer, char, buffer_len);
2255 #endif  
2256         for (i = 0; i < c->methodscount; i++) {
2257 #ifdef JOWENN_DEBUG2
2258                 buffer_len = 
2259                   utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2260         
2261                 buffer = MNEW(char, buffer_len);
2262
2263                 strcpy(buffer, "class_findmethod: comparing to method:");
2264                 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2265                 strcpy(buffer+strlen(buffer), ", desc: ");
2266                 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2267         
2268                 log_text(buffer);       
2269
2270                 MFREE(buffer, char, buffer_len);
2271 #endif  
2272                 
2273                 
2274                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2275                                                    (c->methods[i].descriptor == desc)))
2276                         return &(c->methods[i]);
2277                 }
2278 #ifdef JOWENN_DEBUG2    
2279         class_showconstantpool(c);
2280         log_text("class_findmethod: returning NULL");
2281 #endif
2282         return NULL;
2283 #endif
2284         s4 idx=class_findmethodIndex(c,name,desc);
2285 /*      if (idx==-1) log_text("class_findmethod: method not found");*/
2286         if (idx==-1) return NULL;
2287         return &(c->methods[idx]);
2288 }
2289
2290
2291 /*********************** Function: class_fetchmethod **************************
2292         
2293     like class_findmethod, but aborts with an error if the method is not found
2294
2295 *******************************************************************************/
2296
2297 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2298 {
2299         methodinfo *mi;
2300         mi = class_findmethod(c,name,desc);
2301         if (!mi) {
2302                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2303                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2304                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2305                 panic("Method not found");
2306         }
2307         return mi;
2308 }
2309
2310 /************************* Function: class_findmethod_approx ******************
2311         
2312         like class_findmethod but ignores the return value when comparing the
2313         descriptor.
2314
2315 *******************************************************************************/
2316
2317 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2318 {
2319         s4 i;
2320
2321         for (i = 0; i < c->methodscount; i++) 
2322                 if (c->methods[i].name == name) {
2323                         utf *meth_descr = c->methods[i].descriptor;
2324                         
2325                         if (desc == NULL) 
2326                                 /* ignore type */
2327                                 return &(c->methods[i]);
2328
2329                         if (desc->blength <= meth_descr->blength) {
2330                                            /* current position in utf text   */
2331                                            char *desc_utf_ptr = desc->text;      
2332                                            char *meth_utf_ptr = meth_descr->text;                                         
2333                                            /* points behind utf strings */
2334                                            char *desc_end = utf_end(desc);         
2335                                            char *meth_end = utf_end(meth_descr);   
2336                                            char ch;
2337
2338                                            /* compare argument types */
2339                                            while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2340
2341                                                    if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2342                                                            break; /* no match */
2343
2344                                                    if (ch==')')
2345                                                            return &(c->methods[i]);   /* all parameter types equal */
2346                                            }
2347                         }
2348                 }
2349
2350         return NULL;
2351 }
2352
2353 /***************** Function: class_resolvemethod_approx ***********************
2354         
2355         Searches a class and every super class for a method (without paying
2356         attention to the return value)
2357
2358 *******************************************************************************/
2359
2360 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2361 {
2362         while (c) {
2363                 /* search for method (ignore returntype) */
2364                 methodinfo *m = class_findmethod_approx (c, name, desc);
2365                 /* method found */
2366                 if (m) return m;
2367                 /* search superclass */
2368                 c = c->super;
2369                 }
2370         return NULL;
2371 }
2372
2373
2374 /************************* Function: class_resolvemethod ***********************
2375         
2376         Searches a class and every super class for a method.
2377
2378 *******************************************************************************/
2379
2380 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2381 {
2382         while (c) {
2383                 methodinfo *m = class_findmethod(c, name, desc);
2384                 if (m) return m;
2385                 /* search superclass */
2386                 c = c->super;
2387         }
2388         return NULL;
2389 }
2390
2391
2392
2393 /************************* Function: class_issubclass **************************
2394
2395         Checks if sub is a descendant of super.
2396         
2397 *******************************************************************************/
2398
2399 bool class_issubclass(classinfo *sub, classinfo *super)
2400 {
2401         for (;;) {
2402                 if (!sub) return false;
2403                 if (sub==super) return true;
2404                 sub = sub -> super;
2405         }
2406 }
2407
2408
2409
2410 /****************** Initialization function for classes ******************
2411
2412         In Java, every class can have a static initialization function. This
2413         function has to be called BEFORE calling other methods or accessing static
2414         variables.
2415
2416 *******************************************************************************/
2417
2418 #ifdef USE_THREADS
2419 extern int blockInts;
2420 #endif
2421
2422 void class_init(classinfo *c)
2423 {
2424         methodinfo *m;
2425         java_objectheader *exceptionptr;
2426         s4 i;
2427         int b;
2428
2429
2430         if (!makeinitializations)
2431                 return;
2432         if (c->initialized)
2433                 return;
2434         c -> initialized = true;
2435
2436
2437
2438 #ifdef STATISTICS
2439         count_class_inits++;
2440 #endif
2441
2442         if (c->super)
2443                 class_init (c->super);
2444         for (i=0; i < c->interfacescount; i++)
2445                 class_init(c->interfaces[i]);  /* real */
2446
2447         m = class_findmethod (c, utf_clinit, utf_fidesc);
2448         if (!m) {
2449                 if (initverbose) {
2450                                                 char logtext[MAXLOGTEXT];
2451                         sprintf (logtext, "Class ");
2452                         utf_sprint (logtext+strlen(logtext), c->name);
2453                         sprintf (logtext+strlen(logtext), " has no initializer");
2454                         dolog (logtext);
2455                         }
2456 /*              goto callinitialize;*/
2457                 return;
2458                 }
2459
2460         if (! (m->flags & ACC_STATIC))
2461                 panic ("Class initializer is not static!");
2462
2463         if (initverbose) {
2464                                 char logtext[MAXLOGTEXT];
2465                 sprintf (logtext, "Starting initializer for class: ");
2466                 utf_sprint (logtext+strlen(logtext), c->name);
2467                 dolog (logtext);
2468         }
2469
2470 #ifdef USE_THREADS
2471         b = blockInts;
2472         blockInts = 0;
2473 #endif
2474
2475         exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2476
2477 #ifdef USE_THREADS
2478         assert(blockInts == 0);
2479         blockInts = b;
2480 #endif
2481
2482         if (exceptionptr) {
2483                 printf ("#### Initializer of ");
2484                 utf_display (c->name);
2485                 printf (" has thrown: ");
2486                 utf_display (exceptionptr->vftbl->class->name);
2487                 printf ("\n");
2488                 fflush (stdout);
2489                 }
2490
2491         if (initverbose) {
2492                                 char logtext[MAXLOGTEXT];
2493                 sprintf (logtext, "Finished initializer for class: ");
2494                 utf_sprint (logtext+strlen(logtext), c->name);
2495                 dolog (logtext);
2496         }
2497         if (c->name == utf_systemclass) {
2498                 /* class java.lang.System requires explicit initialization */
2499
2500                 if (initverbose)
2501                         printf ("#### Initializing class System");
2502
2503                 /* find initializing method */
2504                 m = class_findmethod (c,
2505                                         utf_initsystemclass,
2506                                         utf_fidesc);
2507
2508                 if (!m) {
2509                         /* no method found */
2510                         /* printf("initializeSystemClass failed"); */
2511                         return;
2512                 }
2513                 #ifdef USE_THREADS
2514                         b = blockInts;
2515                         blockInts = 0;
2516                 #endif
2517
2518                 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2519
2520                 #ifdef USE_THREADS
2521                         assert(blockInts == 0);
2522                         blockInts = b;
2523                 #endif
2524
2525                 if (exceptionptr) {
2526                         printf ("#### initializeSystemClass has thrown: ");
2527                         utf_display (exceptionptr->vftbl->class->name);
2528                         printf ("\n");
2529                         fflush (stdout);
2530                 }
2531         }
2532
2533 }
2534
2535
2536
2537
2538 /********* Function: find_class_method_constant *********/
2539 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)  
2540 {
2541         u4 i;
2542         voidptr e;
2543
2544         for (i=0; i<c->cpcount; i++) {
2545                 
2546                 e = c -> cpinfos [i];
2547                 if (e) {
2548                         
2549                         switch (c -> cptags [i]) {
2550                         case CONSTANT_Methodref:
2551                                 {
2552                                         constant_FMIref *fmi = e;
2553                                         if (       (fmi->class->name == c1)  
2554                                                            && (fmi->name == m1)
2555                                                            && (fmi->descriptor == d1)) {
2556                                         
2557                                                 return i;
2558                                         }
2559                                 }
2560                                 break;
2561
2562                         case CONSTANT_InterfaceMethodref:
2563                                 {
2564                                         constant_FMIref *fmi = e;
2565                                         if (       (fmi->class->name == c1)  
2566                                                            && (fmi->name == m1)
2567                                                            && (fmi->descriptor == d1)) {
2568
2569                                                 return i;
2570                                         }
2571                                 }
2572                                 break;
2573                         }
2574                 }
2575         }
2576
2577         return -1;
2578 }
2579
2580
2581 void class_showconstanti(classinfo *c, int ii) 
2582 {
2583         u4 i = ii;
2584         voidptr e;
2585                 
2586         e = c->cpinfos [i];
2587         printf ("#%d:  ", (int) i);
2588         if (e) {
2589                 switch (c->cptags [i]) {
2590                 case CONSTANT_Class:
2591                         printf("Classreference -> ");
2592                         utf_display(((classinfo*)e)->name);
2593                         break;
2594                                 
2595                 case CONSTANT_Fieldref:
2596                         printf("Fieldref -> "); goto displayFMIi;
2597                 case CONSTANT_Methodref:
2598                         printf("Methodref -> "); goto displayFMIi;
2599                 case CONSTANT_InterfaceMethodref:
2600                         printf("InterfaceMethod -> "); goto displayFMIi;
2601                 displayFMIi:
2602                         {
2603                                 constant_FMIref *fmi = e;
2604                                 utf_display(fmi->class->name);
2605                                 printf(".");
2606                                 utf_display(fmi->name);
2607                                 printf(" ");
2608                                 utf_display(fmi->descriptor);
2609                         }
2610                         break;
2611
2612                 case CONSTANT_String:
2613                         printf("String -> ");
2614                         utf_display(e);
2615                         break;
2616                 case CONSTANT_Integer:
2617                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2618                         break;
2619                 case CONSTANT_Float:
2620                         printf("Float -> %f", ((constant_float*)e)->value);
2621                         break;
2622                 case CONSTANT_Double:
2623                         printf("Double -> %f", ((constant_double*)e)->value);
2624                         break;
2625                 case CONSTANT_Long:
2626                         {
2627                                 u8 v = ((constant_long*)e)->value;
2628 #if U8_AVAILABLE
2629                                 printf("Long -> %ld", (long int) v);
2630 #else
2631                                 printf("Long -> HI: %ld, LO: %ld\n", 
2632                                             (long int) v.high, (long int) v.low);
2633 #endif 
2634                         }
2635                         break;
2636                 case CONSTANT_NameAndType:
2637                         { 
2638                                 constant_nameandtype *cnt = e;
2639                                 printf("NameAndType: ");
2640                                 utf_display(cnt->name);
2641                                 printf(" ");
2642                                 utf_display(cnt->descriptor);
2643                         }
2644                         break;
2645                 case CONSTANT_Utf8:
2646                         printf("Utf8 -> ");
2647                         utf_display(e);
2648                         break;
2649                 default: 
2650                         panic("Invalid type of ConstantPool-Entry");
2651                 }
2652         }
2653         printf("\n");
2654 }
2655
2656
2657 void class_showconstantpool (classinfo *c) 
2658 {
2659         u4 i;
2660         voidptr e;
2661
2662         printf ("---- dump of constant pool ----\n");
2663
2664         for (i=0; i<c->cpcount; i++) {
2665                 printf ("#%d:  ", (int) i);
2666                 
2667                 e = c -> cpinfos [i];
2668                 if (e) {
2669                         
2670                         switch (c -> cptags [i]) {
2671                         case CONSTANT_Class:
2672                                 printf ("Classreference -> ");
2673                                 utf_display ( ((classinfo*)e) -> name );
2674                                 break;
2675                                 
2676                         case CONSTANT_Fieldref:
2677                                 printf ("Fieldref -> "); goto displayFMI;
2678                         case CONSTANT_Methodref:
2679                                 printf ("Methodref -> "); goto displayFMI;
2680                         case CONSTANT_InterfaceMethodref:
2681                                 printf ("InterfaceMethod -> "); goto displayFMI;
2682                         displayFMI:
2683                                 {
2684                                         constant_FMIref *fmi = e;
2685                                         utf_display ( fmi->class->name );
2686                                         printf (".");
2687                                         utf_display ( fmi->name);
2688                                         printf (" ");
2689                                         utf_display ( fmi->descriptor );
2690                                 }
2691                                 break;
2692
2693                         case CONSTANT_String:
2694                                 printf ("String -> ");
2695                                 utf_display (e);
2696                                 break;
2697                         case CONSTANT_Integer:
2698                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2699                                 break;
2700                         case CONSTANT_Float:
2701                                 printf ("Float -> %f", ((constant_float*)e) -> value);
2702                                 break;
2703                         case CONSTANT_Double:
2704                                 printf ("Double -> %f", ((constant_double*)e) -> value);
2705                                 break;
2706                         case CONSTANT_Long:
2707                                 {
2708                                         u8 v = ((constant_long*)e) -> value;
2709 #if U8_AVAILABLE
2710                                         printf ("Long -> %ld", (long int) v);
2711 #else
2712                                         printf ("Long -> HI: %ld, LO: %ld\n", 
2713                                                         (long int) v.high, (long int) v.low);
2714 #endif 
2715                                 }
2716                                 break;
2717                         case CONSTANT_NameAndType:
2718                                 {
2719                                         constant_nameandtype *cnt = e;
2720                                         printf ("NameAndType: ");
2721                                         utf_display (cnt->name);
2722                                         printf (" ");
2723                                         utf_display (cnt->descriptor);
2724                                 }
2725                                 break;
2726                         case CONSTANT_Utf8:
2727                                 printf ("Utf8 -> ");
2728                                 utf_display (e);
2729                                 break;
2730                         default: 
2731                                 panic ("Invalid type of ConstantPool-Entry");
2732                         }
2733                 }
2734
2735                 printf ("\n");
2736         }
2737 }
2738
2739
2740
2741 /********** Function: class_showmethods   (debugging only) *************/
2742
2743 void class_showmethods (classinfo *c)
2744 {
2745         s4 i;
2746         
2747         printf ("--------- Fields and Methods ----------------\n");
2748         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
2749
2750         printf ("This: "); utf_display (c->name); printf ("\n");
2751         if (c->super) {
2752                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2753                 }
2754         printf ("Index: %d\n", c->index);
2755         
2756         printf ("interfaces:\n");       
2757         for (i=0; i < c-> interfacescount; i++) {
2758                 printf ("   ");
2759                 utf_display (c -> interfaces[i] -> name);
2760                 printf (" (%d)\n", c->interfaces[i] -> index);
2761                 }
2762
2763         printf ("fields:\n");           
2764         for (i=0; i < c -> fieldscount; i++) {
2765                 field_display (&(c -> fields[i]));
2766                 }
2767
2768         printf ("methods:\n");
2769         for (i=0; i < c -> methodscount; i++) {
2770                 methodinfo *m = &(c->methods[i]);
2771                 if ( !(m->flags & ACC_STATIC)) 
2772                         printf ("vftblindex: %d   ", m->vftblindex);
2773
2774                 method_display ( m );
2775
2776                 }
2777
2778         printf ("Virtual function table:\n");
2779         for (i=0; i<c->vftbl->vftbllength; i++) {
2780                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
2781                 }
2782
2783 }
2784
2785
2786
2787 /******************************************************************************/
2788 /******************* General functions for the class loader *******************/
2789 /******************************************************************************/
2790
2791 /********************* Function: loader_load ***********************************
2792
2793         Loads and links the class desired class and each class and interface
2794         referenced by it.
2795         Returns: a pointer to this class
2796
2797 *******************************************************************************/
2798
2799 static int loader_load_running = 0;
2800
2801 classinfo *loader_load (utf *topname)
2802 {
2803         classinfo *top;
2804         classinfo *c;
2805         long int starttime=0,stoptime=0;
2806         classinfo *notlinkable;
2807         
2808
2809         /* avoid recursive calls */
2810         if (loader_load_running)
2811                 return class_new(topname);
2812         loader_load_running++;
2813         
2814         intsDisable();                           /* schani */
2815
2816         if (getloadingtime)
2817                 starttime = getcputime();
2818
2819         top = class_new (topname);
2820
2821         /* load classes */
2822         while ( (c = list_first(&unloadedclasses)) ) {
2823                 if (!class_load (c)) {
2824                         if (linkverbose) dolog("Failed to load class");
2825                         list_remove (&unloadedclasses, c);
2826                         top=NULL;
2827                     }
2828         }
2829
2830         /* link classes */
2831         if (linkverbose) dolog("Linking...");
2832         /* XXX added a hack to break infinite linking loops. A better
2833          * linking algorithm would be nice. -Edwin */
2834         notlinkable = NULL;
2835         while ( (c = list_first(&unlinkedclasses)) ) {
2836                 class_link (c);
2837                 if (!c->linked) {
2838                         if (!notlinkable)
2839                                 notlinkable = c;
2840                         else if (notlinkable == c) {
2841                                 /* We tried to link this class for the second time and
2842                                  * no other classes were linked in between, so we are
2843                                  * caught in a loop.
2844                                  */
2845                                 if (linkverbose) dolog("Cannot resolve linking dependencies");
2846                                 top=NULL;
2847                                 if (!exceptionptr)
2848                                         throw_linkageerror2(c->name);
2849                                 break;
2850                         }
2851                 }
2852                 else
2853                         notlinkable = NULL;
2854                 }
2855         if (linkverbose) dolog("Linking done.");
2856
2857         if (loader_inited)
2858                 loader_compute_subclasses();
2859
2860         /* measure time */
2861         if (getloadingtime) {
2862                 stoptime = getcputime();
2863                 loadingtime += (stoptime-starttime);
2864                 }
2865
2866
2867         loader_load_running--;
2868         
2869         /* check if a former loader_load call tried to load/link the class and failed.
2870                 This is needed because the class didn't appear in the undloadclasses or unlinkedclasses list during this class; */
2871         if (top) {
2872                 if (!top->loaded) {
2873                         if (linkverbose) dolog("Failed to load class (former call)");
2874                         throw_classnotfoundexception2(top->name);
2875                         top=NULL;
2876                 } else if  (!top->linked) {
2877                         if (linkverbose) dolog("Failed to link class (former call)");
2878                         throw_linkageerror2(top->name);
2879                         top=NULL;
2880                 }
2881         }
2882
2883         intsRestore();                          /* schani */
2884
2885         /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
2886         
2887         return top; 
2888 }
2889
2890 /****************** Function: loader_load_sysclass ****************************
2891
2892         Loads and links the class desired class and each class and interface
2893         referenced by it.
2894
2895     The pointer to the classinfo is stored in *top if top != NULL.
2896     The pointer is also returned.
2897
2898     If the class could not be loaded the function aborts with an error.
2899
2900 *******************************************************************************/
2901
2902 classinfo *loader_load_sysclass(classinfo **top,utf *topname)
2903 {
2904         classinfo *cls;
2905
2906         if ((cls = loader_load(topname)) == NULL) {
2907                 log_plain("Could not important system class: ");
2908                 log_plain_utf(topname);
2909                 log_nl();
2910                 panic("Could not load important system class");
2911         }
2912
2913         if (top) *top = cls;
2914
2915         return cls;
2916 }
2917
2918 /**************** function: create_primitive_classes ***************************
2919
2920         create classes representing primitive types 
2921
2922 ********************************************************************************/
2923
2924
2925 void create_primitive_classes()
2926 {  
2927         int i;
2928
2929         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2930                 /* create primitive class */
2931                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2932                 c -> classUsed = NOTUSED; /* not used initially CO-RT */                
2933                 c -> impldBy = NULL;
2934                 
2935                 /* prevent loader from loading primitive class */
2936                 list_remove (&unloadedclasses, c);
2937                 c->loaded=true;
2938                 /* add to unlinked classes */
2939                 list_addlast (&unlinkedclasses, c);             
2940 /*JOWENN primitive types don't have objects as super class              c -> super = class_java_lang_Object; */
2941                 class_link (c);
2942
2943                 primitivetype_table[i].class_primitive = c;
2944
2945                 /* create class for wrapping the primitive type */
2946                 primitivetype_table[i].class_wrap =
2947                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
2948                 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2949                 primitivetype_table[i].class_wrap  -> impldBy = NULL;
2950
2951                 /* create the primitive array class */
2952                 if (primitivetype_table[i].arrayname) {
2953                         c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2954                         primitivetype_table[i].arrayclass = c;
2955                         c->loaded=true;
2956                         if (!c->linked) class_link(c);
2957                         primitivetype_table[i].arrayvftbl = c->vftbl;
2958                 }
2959         }
2960 }
2961
2962 /**************** function: class_primitive_from_sig ***************************
2963
2964         return the primitive class indicated by the given signature character
2965
2966     If the descriptor does not indicate a valid primitive type the
2967     return value is NULL.
2968
2969 ********************************************************************************/
2970
2971 classinfo *class_primitive_from_sig(char sig)
2972 {
2973         switch (sig) {
2974           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2975           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2976           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2977           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2978           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2979           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2980           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2981           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2982           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2983         }
2984         return NULL;
2985 }
2986
2987 /****************** function: class_from_descriptor ****************************
2988
2989     return the class indicated by the given descriptor
2990
2991     utf_ptr....first character of descriptor
2992     end_ptr....first character after the end of the string
2993     next.......if non-NULL, *next is set to the first character after
2994                the descriptor. (Undefined if an error occurs.)
2995
2996     mode.......a combination (binary or) of the following flags:
2997
2998                (Flags marked with * are the default settings.)
2999
3000                What to do if a reference type descriptor is parsed successfully:
3001
3002                    CLASSLOAD_SKIP...skip it and return something != NULL
3003                                  * CLASSLOAD_NEW....get classinfo * via class_new
3004                    CLASSLOAD_LOAD...get classinfo * via loader_load
3005
3006                How to handle primitive types:
3007
3008                              * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3009                    CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3010
3011                How to handle "V" descriptors:
3012
3013                              * CLASSLOAD_VOID.....handle it like other primitive types
3014                    CLASSLOAD_NOVOID...treat it as an error
3015
3016                How to deal with extra characters after the end of the
3017                descriptor:
3018
3019                              * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3020                    CLASSLOAD_CHECKEND.....treat them as an error
3021
3022                How to deal with errors:
3023
3024                              * CLASSLOAD_PANIC....abort execution with an error message
3025                    CLASSLOAD_NOPANIC..return NULL on error
3026
3027 ********************************************************************************/
3028
3029 classinfo *
3030 class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
3031 {
3032         char *start = utf_ptr;
3033         bool error = false;
3034         utf *name;
3035
3036         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3037
3038         if (mode & CLASSLOAD_CHECKEND)
3039                 error |= (utf_ptr != end_ptr);
3040         
3041         if (!error) {
3042                 if (next) *next = utf_ptr;
3043                 
3044                 switch (*start) {
3045                   case 'V':
3046                           if (mode & CLASSLOAD_NOVOID)
3047                                   break;
3048                           /* FALLTHROUGH! */
3049                   case 'I':
3050                   case 'J':
3051                   case 'F':
3052                   case 'D':
3053                   case 'B':
3054                   case 'C':
3055                   case 'S':
3056                   case 'Z':
3057                           return (mode & CLASSLOAD_NULLPRIMITIVE)
3058                                   ? NULL
3059                                   : class_primitive_from_sig(*start);
3060                           
3061                   case 'L':
3062                           start++;
3063                           utf_ptr--;
3064                           /* FALLTHROUGH! */
3065                   case '[':
3066                           if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3067                           name = utf_new(start,utf_ptr-start);
3068                           return (mode & CLASSLOAD_LOAD)
3069                                   ? loader_load(name) : class_new(name); /* XXX */
3070                 }
3071         }
3072
3073         /* An error occurred */
3074         if (mode & CLASSLOAD_NOPANIC)
3075                 return NULL;
3076
3077         log_plain("Invalid descriptor at beginning of '");
3078         log_plain_utf(utf_new(start,end_ptr-start));
3079         log_plain("'");
3080         log_nl();
3081                                                   
3082         panic("Invalid descriptor");
3083 }
3084
3085 /******************* function: type_from_descriptor ****************************
3086
3087     return the basic type indicated by the given descriptor
3088
3089     This function parses a descriptor and returns its basic type as
3090     TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3091
3092     cls...if non-NULL the referenced variable is set to the classinfo *
3093           returned by class_from_descriptor.
3094
3095     For documentation of the arguments utf_ptr, end_ptr, next and mode
3096     see class_from_descriptor. The only difference is that
3097     type_from_descriptor always uses CLASSLOAD_PANIC.
3098
3099 ********************************************************************************/
3100
3101 int
3102 type_from_descriptor(classinfo **cls,char *utf_ptr,char *end_ptr,char **next,int mode)
3103 {
3104         classinfo *mycls;
3105         if (!cls) cls = &mycls;
3106         *cls = class_from_descriptor(utf_ptr,end_ptr,next,mode & (~CLASSLOAD_NOPANIC));
3107         switch (*utf_ptr) {
3108           case 'B': 
3109           case 'C':
3110           case 'I':
3111           case 'S':  
3112           case 'Z':
3113                   return TYPE_INT;
3114           case 'D':
3115                   return TYPE_DOUBLE;
3116           case 'F':
3117                   return TYPE_FLOAT;
3118           case 'J':
3119                   return TYPE_LONG;
3120           case 'V':
3121                   return TYPE_VOID;
3122         }
3123         return TYPE_ADDRESS;
3124 }
3125
3126 /*************** function: create_pseudo_classes *******************************
3127
3128         create pseudo classes used by the typechecker
3129
3130 ********************************************************************************/
3131
3132 static void
3133 create_pseudo_classes()
3134 {
3135     /* pseudo class for Arraystubs (extends java.lang.Object) */
3136     
3137     pseudo_class_Arraystub = class_new( utf_new_char("$ARRAYSTUB$") );
3138     list_remove(&unloadedclasses,pseudo_class_Arraystub);
3139
3140     pseudo_class_Arraystub->super = class_java_lang_Object;
3141     pseudo_class_Arraystub->interfacescount = 2;
3142     pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
3143     pseudo_class_Arraystub->interfaces[0] =
3144         class_java_lang_Cloneable;
3145     pseudo_class_Arraystub->interfaces[1] =
3146         class_java_io_Serializable;
3147
3148     list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
3149     class_link(pseudo_class_Arraystub);
3150
3151         pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3152
3153     /* pseudo class representing the null type */
3154     
3155     pseudo_class_Null = class_new( utf_new_char("$NULL$") );
3156     list_remove(&unloadedclasses,pseudo_class_Null);
3157
3158     pseudo_class_Null->super = class_java_lang_Object;
3159
3160     list_addlast(&unlinkedclasses,pseudo_class_Null);
3161     class_link(pseudo_class_Null);      
3162
3163     /* pseudo class representing new uninitialized objects */
3164     
3165     pseudo_class_New = class_new( utf_new_char("$NEW$") );
3166     list_remove(&unloadedclasses,pseudo_class_New);
3167
3168     pseudo_class_New->super = class_java_lang_Object;
3169
3170     list_addlast(&unlinkedclasses,pseudo_class_New);
3171     class_link(pseudo_class_New);       
3172 }
3173
3174 /********************** Function: loader_init **********************************
3175
3176         Initializes all lists and loads all classes required for the system or the
3177         compiler.
3178
3179 *******************************************************************************/
3180  
3181 void loader_init (u1 * stackbottom)
3182 {
3183         interfaceindex = 0;
3184         
3185         
3186         log_text("Entering loader_init");
3187                                 
3188         
3189         list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
3190         list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
3191         list_init (&linkedclasses, OFFSET(classinfo, listnode) );
3192
3193         /* create utf-symbols for pointer comparison of frequently used strings */
3194         utf_innerclasses    = utf_new_char("InnerClasses");
3195         utf_constantvalue   = utf_new_char("ConstantValue");
3196         utf_code                = utf_new_char("Code");
3197         utf_finalize        = utf_new_char("finalize");
3198         utf_fidesc              = utf_new_char("()V");
3199         utf_clinit              = utf_new_char("<clinit>");
3200         utf_initsystemclass = utf_new_char("initializeSystemClass");
3201         utf_systemclass     = utf_new_char("java/lang/System");
3202         utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
3203         utf_initialize =utf_new_char("initialize");
3204         utf_initializedesc =utf_new_char("(I)V");
3205
3206         utf_vmclass =utf_new_char("java/lang/VMClass");
3207
3208         /* create some important classes */
3209         /* These classes have to be created now because the classinfo
3210          * pointers are used in the loading code.
3211          */
3212         class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
3213         class_java_lang_String = class_new( utf_new_char("java/lang/String") );
3214         class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
3215         class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
3216
3217         log_text("loader_init: java/lang/Object");
3218         /* load the classes which were created above */
3219         loader_load_sysclass (NULL,class_java_lang_Object->name);
3220
3221         loader_inited=1; /*JOWENN*/
3222
3223                 loader_load_sysclass(&class_java_lang_Throwable,
3224                                                          utf_new_char("java/lang/Throwable") );
3225
3226         log_text("loader_init:  loader_load: java/lang/ClassCastException");
3227                 loader_load_sysclass(&class_java_lang_ClassCastException,
3228                                                          utf_new_char ("java/lang/ClassCastException") );
3229                 loader_load_sysclass(&class_java_lang_NullPointerException,
3230                                                          utf_new_char ("java/lang/NullPointerException") );
3231                 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3232                                                          utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
3233                 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3234                                                          utf_new_char ("java/lang/NegativeArraySizeException") );
3235                 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3236                                                          utf_new_char ("java/lang/OutOfMemoryError") );
3237                 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3238                                                          utf_new_char ("java/lang/ArrayStoreException") );
3239                 loader_load_sysclass(&class_java_lang_ArithmeticException,
3240                                                          utf_new_char ("java/lang/ArithmeticException") );
3241                 loader_load_sysclass(&class_java_lang_ThreadDeath,
3242                                                          utf_new_char ("java/lang/ThreadDeath") );/* schani */
3243                 
3244         /* create classes representing primitive types */
3245         create_primitive_classes();
3246
3247         /* create classes used by the typechecker */
3248         create_pseudo_classes();
3249
3250         /* correct vftbl-entries (retarded loading of class java/lang/String) */
3251         stringtable_update();
3252 #ifdef USE_THREADS
3253         if (stackbottom!=0)
3254                 initLocks();
3255 #endif
3256
3257
3258
3259         log_text("loader_init: creating global proto_java_lang_ClassCastException");
3260         proto_java_lang_ClassCastException =
3261                 builtin_new(class_java_lang_ClassCastException);
3262         heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3263
3264         log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3265
3266         proto_java_lang_NullPointerException =
3267                builtin_new(class_java_lang_NullPointerException);
3268         heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3269         log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3270
3271         proto_java_lang_ArrayIndexOutOfBoundsException =
3272                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3273         heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3274
3275         proto_java_lang_NegativeArraySizeException =
3276                 builtin_new(class_java_lang_NegativeArraySizeException);
3277         heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3278
3279         proto_java_lang_OutOfMemoryError =
3280                 builtin_new(class_java_lang_OutOfMemoryError);
3281         heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3282
3283         proto_java_lang_ArithmeticException =
3284                builtin_new(class_java_lang_ArithmeticException);
3285         heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3286
3287         proto_java_lang_ArrayStoreException =
3288                 builtin_new(class_java_lang_ArrayStoreException);
3289         heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3290
3291         proto_java_lang_ThreadDeath =                             /* schani */
3292                 builtin_new(class_java_lang_ThreadDeath);
3293         heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3294
3295         loader_inited = 1;
3296
3297 }
3298
3299
3300
3301
3302 /********************* Function: loader_initclasses ****************************
3303
3304         Initializes all loaded but uninitialized classes
3305
3306 *******************************************************************************/
3307
3308 void loader_initclasses ()
3309 {
3310         classinfo *c;
3311         
3312         intsDisable();                     /* schani */
3313
3314         if (makeinitializations) {
3315                 c = list_first (&linkedclasses);
3316                 while (c) {
3317                         class_init (c);
3318                         c = list_next (&linkedclasses, c);
3319                         }
3320                 }
3321
3322         intsRestore();                      /* schani */
3323 }
3324
3325 static s4 classvalue;
3326
3327 static void loader_compute_class_values (classinfo *c)
3328 {
3329         classinfo *subs;
3330
3331         c->vftbl->baseval = ++classvalue;
3332
3333         subs = c->sub;
3334         while (subs != NULL) {
3335                 loader_compute_class_values(subs);
3336                 subs = subs->nextsub;
3337                 }
3338         c->vftbl->diffval = classvalue - c->vftbl->baseval;
3339         
3340         /*
3341         {
3342         int i;
3343         for (i = 0; i < c->index; i++)
3344                 printf(" ");
3345         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
3346         utf_display(c->name);
3347         printf("\n");
3348         }
3349         */
3350         
3351 }
3352
3353
3354 void loader_compute_subclasses ()
3355 {
3356         classinfo *c;
3357         
3358         intsDisable();                     /* schani */
3359
3360         c = list_first (&linkedclasses);
3361         while (c) {
3362                 if (!(c->flags & ACC_INTERFACE)) {
3363                         c->nextsub = 0;
3364                         c->sub = 0;
3365                         }
3366                 c = list_next (&linkedclasses, c);
3367                 }
3368
3369         c = list_first (&linkedclasses);
3370         while (c) {
3371                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3372                         c->nextsub = c->super->sub;
3373                         c->super->sub = c;
3374                         }
3375                 c = list_next (&linkedclasses, c);
3376                 }
3377         classvalue = 0;
3378         loader_compute_class_values(class_java_lang_Object);
3379
3380         intsRestore();                      /* schani */
3381 }
3382
3383
3384
3385 /******************** function classloader_buffer ******************************
3386  
3387     sets buffer for reading classdata
3388
3389 *******************************************************************************/
3390
3391 void classload_buffer(u1 *buf, int len)
3392 {
3393         classbuffer        =  buf;
3394         classbuffer_size   =  len;
3395         classbuf_pos       =  buf - 1;
3396 }
3397
3398
3399 /******************** Function: loader_close ***********************************
3400
3401         Frees all resources
3402         
3403 *******************************************************************************/
3404
3405 void loader_close ()
3406 {
3407         classinfo *c;
3408
3409         while ( (c=list_first(&unloadedclasses)) ) {
3410                 list_remove (&unloadedclasses,c);
3411                 class_free (c);
3412                 }
3413         while ( (c=list_first(&unlinkedclasses)) ) {
3414                 list_remove (&unlinkedclasses,c);
3415                 class_free (c);
3416                 }
3417         while ( (c=list_first(&linkedclasses)) ) {
3418                 list_remove (&linkedclasses,c);
3419                 class_free (c);
3420                 }
3421 }
3422
3423
3424 /*
3425  * These are local overrides for various environment variables in Emacs.
3426  * Please do not remove this and leave it at the end of the file, where
3427  * Emacs will automagically detect them.
3428  * ---------------------------------------------------------------------
3429  * Local variables:
3430  * mode: c
3431  * indent-tabs-mode: t
3432  * c-basic-offset: 4
3433  * tab-width: 4
3434  * End:
3435  */