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