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