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