- removed unused exception class_ declarations
[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 999 2004-03-30 22:34:40Z twisti $
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(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 (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(utf_new(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(utf_new(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(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(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     If the field cannot be resolved this function panics.
2627
2628 *******************************************************************************/
2629
2630 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2631                                                           classinfo *referer)
2632 {
2633         fieldinfo *fi;
2634
2635         /* XXX resolve class c */
2636         /* XXX check access from REFERER to C */
2637         
2638         fi = class_resolvefield_int(c,name,desc);
2639
2640         if (!fi) {
2641                 log_utf(c->name);
2642                 log_utf(name);
2643                 log_utf(desc);
2644                 panic("Cannot find field given in CONSTANT_Fieldref");
2645                 /* XXX should throw NoSuchFieldError */
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 *******************************************************************************/
2970
2971 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2972                                                                                  classinfo *referer)
2973 {
2974         methodinfo *mi;
2975
2976         /* XXX resolve class c */
2977         /* XXX check access from REFERER to C */
2978         
2979         if ((c->flags & ACC_INTERFACE) == 0)
2980                 return NULL; /* should throw IncompatibleClassChangeError */
2981
2982         mi = class_resolveinterfacemethod_int(c,name,desc);
2983         if (mi)
2984                 goto found;
2985
2986         /* try class java.lang.Object */
2987         mi = class_findmethod(class_java_lang_Object,name,desc);
2988         if (mi)
2989                 goto found;
2990
2991         return NULL; /* should throw NoSuchMethodError */
2992
2993  found:
2994         return mi;
2995 }
2996
2997 /********************* Function: class_resolveclassmethod *********************
2998         
2999     Resolves a reference from REFERER to a method with NAME and DESC in
3000     class C.
3001
3002 *******************************************************************************/
3003
3004 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3005                                                                          classinfo *referer)
3006 {
3007         methodinfo *mi;
3008         int i;
3009         classinfo *cls;
3010         
3011         /* XXX resolve class c */
3012         /* XXX check access from REFERER to C */
3013         
3014         if ((c->flags & ACC_INTERFACE) != 0)
3015                 return NULL; /* should throw IncompatibleClassChangeError */
3016
3017         /* try class c and its superclasses */
3018         cls = c;
3019         do {
3020                 mi = class_findmethod(cls,name,desc);
3021                 if (mi)
3022                         goto found;
3023         } while ((cls = cls->super) != NULL); /* try the superclass */
3024
3025         /* try the superinterfaces */
3026         for (i=0; i<c->interfacescount; ++i) {
3027                 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3028                 if (mi)
3029                         goto found;
3030         }
3031         
3032         return NULL; /* should throw NoSuchMethodError */
3033
3034  found:
3035         if ((mi->flags & ACC_ABSTRACT) != 0 &&
3036                 (c->flags & ACC_ABSTRACT) == 0)
3037                 return NULL; /* should throw AbstractMethodError */
3038
3039         /* XXX check access rights */
3040
3041         return mi;
3042 }
3043
3044
3045 /************************* Function: class_issubclass **************************
3046
3047         Checks if sub is a descendant of super.
3048         
3049 *******************************************************************************/
3050
3051 bool class_issubclass(classinfo *sub, classinfo *super)
3052 {
3053         for (;;) {
3054                 if (!sub) return false;
3055                 if (sub == super) return true;
3056                 sub = sub->super;
3057         }
3058 }
3059
3060
3061 /****************** Initialization function for classes ******************
3062
3063         In Java, every class can have a static initialization function. This
3064         function has to be called BEFORE calling other methods or accessing static
3065         variables.
3066
3067 *******************************************************************************/
3068
3069 void class_init(classinfo *c)
3070 {
3071         methodinfo *m;
3072         s4 i;
3073 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3074         int b;
3075 #endif
3076
3077         if (!makeinitializations)
3078                 return;
3079         if (c->initialized)
3080                 return;
3081
3082         c->initialized = true;
3083
3084 #ifdef STATISTICS
3085         count_class_inits++;
3086 #endif
3087
3088         /* initialize super class */
3089         if (c->super) {
3090                 if (initverbose) {
3091                         char logtext[MAXLOGTEXT];
3092                         sprintf(logtext, "Initialize super class ");
3093                         utf_sprint(logtext + strlen(logtext), c->super->name);
3094                         sprintf(logtext + strlen(logtext), " from ");
3095                         utf_sprint(logtext + strlen(logtext), c->name);
3096                         log_text(logtext);
3097                 }
3098                 class_init(c->super);
3099         }
3100
3101         /* initialize interface classes */
3102         for (i = 0; i < c->interfacescount; i++) {
3103                 if (initverbose) {
3104                         char logtext[MAXLOGTEXT];
3105                         sprintf(logtext, "Initialize interface class ");
3106                         utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
3107                         sprintf(logtext + strlen(logtext), " from ");
3108                         utf_sprint(logtext + strlen(logtext), c->name);
3109                         log_text(logtext);
3110                 }
3111                 class_init(c->interfaces[i]);  /* real */
3112         }
3113
3114         m = class_findmethod(c, utf_clinit, utf_fidesc);
3115         if (!m) {
3116                 if (initverbose) {
3117                         char logtext[MAXLOGTEXT];
3118                         sprintf(logtext, "Class ");
3119                         utf_sprint(logtext + strlen(logtext), c->name);
3120                         sprintf(logtext + strlen(logtext), " has no initializer");
3121                         log_text(logtext);
3122                 }
3123                 /*              goto callinitialize;*/
3124                 return;
3125         }
3126
3127         if (!(m->flags & ACC_STATIC))
3128                 panic("Class initializer is not static!");
3129
3130         if (initverbose) {
3131                 char logtext[MAXLOGTEXT];
3132                 sprintf(logtext, "Starting initializer for class: ");
3133                 utf_sprint(logtext + strlen(logtext), c->name);
3134                 log_text(logtext);
3135         }
3136
3137 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3138         b = blockInts;
3139         blockInts = 0;
3140 #endif
3141
3142         /* now call the initializer */
3143         asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3144
3145 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3146         assert(blockInts == 0);
3147         blockInts = b;
3148 #endif
3149
3150         /* we have to throw an exception */
3151         if (*exceptionptr) {
3152                 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
3153                 printf("Caused by: ");
3154                 utf_display((*exceptionptr)->vftbl->class->name);
3155
3156                 /* do we have a detail message? */
3157                 if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
3158                         printf(": ");
3159                         utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
3160                 }
3161
3162                 printf("\n");
3163                 fflush(stdout);
3164                 exit(1);
3165         }
3166
3167         if (initverbose) {
3168                 char logtext[MAXLOGTEXT];
3169                 sprintf(logtext, "Finished initializer for class: ");
3170                 utf_sprint(logtext + strlen(logtext), c->name);
3171                 log_text(logtext);
3172         }
3173
3174         if (c->name == utf_systemclass) {
3175                 /* class java.lang.System requires explicit initialization */
3176
3177                 if (initverbose)
3178                         printf("#### Initializing class System");
3179
3180                 /* find initializing method */
3181                 m = class_findmethod(c,
3182                                                          utf_initsystemclass,
3183                                                          utf_fidesc);
3184
3185                 if (!m) {
3186                         /* no method found */
3187                         /* printf("initializeSystemClass failed"); */
3188                         return;
3189                 }
3190
3191 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3192                 b = blockInts;
3193                 blockInts = 0;
3194 #endif
3195
3196                 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3197
3198 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3199                 assert(blockInts == 0);
3200                 blockInts = b;
3201 #endif
3202
3203                 if (*exceptionptr) {
3204                         printf("#### initializeSystemClass has thrown: ");
3205                         utf_display((*exceptionptr)->vftbl->class->name);
3206                         printf("\n");
3207                         fflush(stdout);
3208                 }
3209         }
3210 }
3211
3212
3213 /********* Function: find_class_method_constant *********/
3214
3215 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)  
3216 {
3217         u4 i;
3218         voidptr e;
3219
3220         for (i=0; i<c->cpcount; i++) {
3221                 
3222                 e = c -> cpinfos [i];
3223                 if (e) {
3224                         
3225                         switch (c -> cptags [i]) {
3226                         case CONSTANT_Methodref:
3227                                 {
3228                                         constant_FMIref *fmi = e;
3229                                         if (       (fmi->class->name == c1)  
3230                                                            && (fmi->name == m1)
3231                                                            && (fmi->descriptor == d1)) {
3232                                         
3233                                                 return i;
3234                                         }
3235                                 }
3236                                 break;
3237
3238                         case CONSTANT_InterfaceMethodref:
3239                                 {
3240                                         constant_FMIref *fmi = e;
3241                                         if (       (fmi->class->name == c1)  
3242                                                            && (fmi->name == m1)
3243                                                            && (fmi->descriptor == d1)) {
3244
3245                                                 return i;
3246                                         }
3247                                 }
3248                                 break;
3249                         }
3250                 }
3251         }
3252
3253         return -1;
3254 }
3255
3256
3257 void class_showconstanti(classinfo *c, int ii) 
3258 {
3259         u4 i = ii;
3260         voidptr e;
3261                 
3262         e = c->cpinfos [i];
3263         printf ("#%d:  ", (int) i);
3264         if (e) {
3265                 switch (c->cptags [i]) {
3266                 case CONSTANT_Class:
3267                         printf("Classreference -> ");
3268                         utf_display(((classinfo*)e)->name);
3269                         break;
3270                                 
3271                 case CONSTANT_Fieldref:
3272                         printf("Fieldref -> "); goto displayFMIi;
3273                 case CONSTANT_Methodref:
3274                         printf("Methodref -> "); goto displayFMIi;
3275                 case CONSTANT_InterfaceMethodref:
3276                         printf("InterfaceMethod -> "); goto displayFMIi;
3277                 displayFMIi:
3278                         {
3279                                 constant_FMIref *fmi = e;
3280                                 utf_display(fmi->class->name);
3281                                 printf(".");
3282                                 utf_display(fmi->name);
3283                                 printf(" ");
3284                                 utf_display(fmi->descriptor);
3285                         }
3286                         break;
3287
3288                 case CONSTANT_String:
3289                         printf("String -> ");
3290                         utf_display(e);
3291                         break;
3292                 case CONSTANT_Integer:
3293                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3294                         break;
3295                 case CONSTANT_Float:
3296                         printf("Float -> %f", ((constant_float*)e)->value);
3297                         break;
3298                 case CONSTANT_Double:
3299                         printf("Double -> %f", ((constant_double*)e)->value);
3300                         break;
3301                 case CONSTANT_Long:
3302                         {
3303                                 u8 v = ((constant_long*)e)->value;
3304 #if U8_AVAILABLE
3305                                 printf("Long -> %ld", (long int) v);
3306 #else
3307                                 printf("Long -> HI: %ld, LO: %ld\n", 
3308                                             (long int) v.high, (long int) v.low);
3309 #endif 
3310                         }
3311                         break;
3312                 case CONSTANT_NameAndType:
3313                         { 
3314                                 constant_nameandtype *cnt = e;
3315                                 printf("NameAndType: ");
3316                                 utf_display(cnt->name);
3317                                 printf(" ");
3318                                 utf_display(cnt->descriptor);
3319                         }
3320                         break;
3321                 case CONSTANT_Utf8:
3322                         printf("Utf8 -> ");
3323                         utf_display(e);
3324                         break;
3325                 default: 
3326                         panic("Invalid type of ConstantPool-Entry");
3327                 }
3328         }
3329         printf("\n");
3330 }
3331
3332
3333 void class_showconstantpool (classinfo *c) 
3334 {
3335         u4 i;
3336         voidptr e;
3337
3338         printf ("---- dump of constant pool ----\n");
3339
3340         for (i=0; i<c->cpcount; i++) {
3341                 printf ("#%d:  ", (int) i);
3342                 
3343                 e = c -> cpinfos [i];
3344                 if (e) {
3345                         
3346                         switch (c -> cptags [i]) {
3347                         case CONSTANT_Class:
3348                                 printf ("Classreference -> ");
3349                                 utf_display ( ((classinfo*)e) -> name );
3350                                 break;
3351                                 
3352                         case CONSTANT_Fieldref:
3353                                 printf ("Fieldref -> "); goto displayFMI;
3354                         case CONSTANT_Methodref:
3355                                 printf ("Methodref -> "); goto displayFMI;
3356                         case CONSTANT_InterfaceMethodref:
3357                                 printf ("InterfaceMethod -> "); goto displayFMI;
3358                         displayFMI:
3359                                 {
3360                                         constant_FMIref *fmi = e;
3361                                         utf_display ( fmi->class->name );
3362                                         printf (".");
3363                                         utf_display ( fmi->name);
3364                                         printf (" ");
3365                                         utf_display ( fmi->descriptor );
3366                                 }
3367                                 break;
3368
3369                         case CONSTANT_String:
3370                                 printf ("String -> ");
3371                                 utf_display (e);
3372                                 break;
3373                         case CONSTANT_Integer:
3374                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3375                                 break;
3376                         case CONSTANT_Float:
3377                                 printf ("Float -> %f", ((constant_float*)e) -> value);
3378                                 break;
3379                         case CONSTANT_Double:
3380                                 printf ("Double -> %f", ((constant_double*)e) -> value);
3381                                 break;
3382                         case CONSTANT_Long:
3383                                 {
3384                                         u8 v = ((constant_long*)e) -> value;
3385 #if U8_AVAILABLE
3386                                         printf ("Long -> %ld", (long int) v);
3387 #else
3388                                         printf ("Long -> HI: %ld, LO: %ld\n", 
3389                                                         (long int) v.high, (long int) v.low);
3390 #endif 
3391                                 }
3392                                 break;
3393                         case CONSTANT_NameAndType:
3394                                 {
3395                                         constant_nameandtype *cnt = e;
3396                                         printf ("NameAndType: ");
3397                                         utf_display (cnt->name);
3398                                         printf (" ");
3399                                         utf_display (cnt->descriptor);
3400                                 }
3401                                 break;
3402                         case CONSTANT_Utf8:
3403                                 printf ("Utf8 -> ");
3404                                 utf_display (e);
3405                                 break;
3406                         default: 
3407                                 panic ("Invalid type of ConstantPool-Entry");
3408                         }
3409                 }
3410
3411                 printf ("\n");
3412         }
3413 }
3414
3415
3416
3417 /********** Function: class_showmethods   (debugging only) *************/
3418
3419 void class_showmethods (classinfo *c)
3420 {
3421         s4 i;
3422         
3423         printf ("--------- Fields and Methods ----------------\n");
3424         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
3425
3426         printf ("This: "); utf_display (c->name); printf ("\n");
3427         if (c->super) {
3428                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3429                 }
3430         printf ("Index: %d\n", c->index);
3431         
3432         printf ("interfaces:\n");       
3433         for (i=0; i < c-> interfacescount; i++) {
3434                 printf ("   ");
3435                 utf_display (c -> interfaces[i] -> name);
3436                 printf (" (%d)\n", c->interfaces[i] -> index);
3437                 }
3438
3439         printf ("fields:\n");           
3440         for (i=0; i < c -> fieldscount; i++) {
3441                 field_display (&(c -> fields[i]));
3442                 }
3443
3444         printf ("methods:\n");
3445         for (i=0; i < c -> methodscount; i++) {
3446                 methodinfo *m = &(c->methods[i]);
3447                 if ( !(m->flags & ACC_STATIC)) 
3448                         printf ("vftblindex: %d   ", m->vftblindex);
3449
3450                 method_display ( m );
3451
3452                 }
3453
3454         printf ("Virtual function table:\n");
3455         for (i=0; i<c->vftbl->vftbllength; i++) {
3456                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
3457                 }
3458
3459 }
3460
3461
3462
3463 /******************************************************************************/
3464 /******************* General functions for the class loader *******************/
3465 /******************************************************************************/
3466
3467 /********************* Function: loader_load ***********************************
3468
3469         Loads and links the class desired class and each class and interface
3470         referenced by it.
3471         Returns: a pointer to this class
3472
3473 *******************************************************************************/
3474
3475 static int loader_load_running = 0;
3476
3477 classinfo *loader_load(utf *topname)
3478 {
3479         classinfo *top;
3480         classinfo *c;
3481         s8 starttime = 0;
3482         s8 stoptime = 0;
3483         classinfo *notlinkable;
3484
3485         /* avoid recursive calls */
3486         if (loader_load_running)
3487                 return class_new(topname);
3488
3489 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3490         compiler_lock();
3491 #endif
3492
3493         loader_load_running++;
3494         
3495 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3496         intsDisable();
3497 #endif
3498
3499         if (getloadingtime)
3500                 starttime = getcputime();
3501
3502         top = class_new(topname);
3503
3504         /* load classes */
3505         while ((c = list_first(&unloadedclasses))) {
3506                 if (!class_load(c)) {
3507                         if (linkverbose)
3508                                 dolog("Failed to load class");
3509                         list_remove(&unloadedclasses, c);
3510                         top = NULL;
3511                 }
3512         }
3513
3514         /* link classes */
3515         if (linkverbose)
3516                 dolog("Linking...");
3517
3518         /* Added a hack to break infinite linking loops. A better
3519          * linking algorithm would be nice. -Edwin */
3520         notlinkable = NULL;
3521         while ((c = list_first(&unlinkedclasses))) {
3522                 class_link(c);
3523                 if (!c->linked) {
3524                         if (!notlinkable)
3525                                 notlinkable = c;
3526                         else if (notlinkable == c) {
3527                                 /* We tried to link this class for the second time and
3528                                  * no other classes were linked in between, so we are
3529                                  * caught in a loop.
3530                                  */
3531                                 if (linkverbose)
3532                                         dolog("Cannot resolve linking dependencies");
3533                                 top = NULL;
3534
3535                                 if (!*exceptionptr)
3536                                         *exceptionptr = new_exception_utfmessage(string_java_lang_LinkageError,
3537                                                                                                                          c->name);
3538                                 break;
3539                         }
3540
3541                 } else
3542                         notlinkable = NULL;
3543         }
3544         if (linkverbose)
3545                 dolog("Linking done.");
3546
3547         if (loader_inited)
3548                 loader_compute_subclasses();
3549
3550         /* measure time */
3551         if (getloadingtime) {
3552                 stoptime = getcputime();
3553                 loadingtime += (stoptime - starttime);
3554         }
3555
3556
3557         loader_load_running--;
3558         
3559         /* check if a former loader_load call tried to load/link the class and 
3560            failed. This is needed because the class didn't appear in the 
3561            undloadclasses or unlinkedclasses list during this class. */
3562         if (top) {
3563                 if (!top->loaded) {
3564                         if (linkverbose)
3565                                 dolog("Failed to load class (former call)");
3566                         
3567                         new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
3568                                                                          top->name);
3569                         top = NULL;
3570                         
3571                 } else if (!top->linked) {
3572                         if (linkverbose)
3573                                 dolog("Failed to link class (former call)");
3574
3575                         new_exception_utfmessage(string_java_lang_LinkageError,
3576                                                                          top->name);
3577                         top = NULL;
3578                 }
3579         }
3580
3581 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3582         intsRestore();
3583 #endif
3584         
3585 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3586         compiler_unlock();
3587 #endif
3588
3589         /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3590         
3591         return top; 
3592 }
3593
3594
3595 /****************** Function: loader_load_sysclass ****************************
3596
3597         Loads and links the class desired class and each class and interface
3598         referenced by it.
3599
3600     The pointer to the classinfo is stored in *top if top != NULL.
3601     The pointer is also returned.
3602
3603     If the class could not be loaded the function aborts with an error.
3604
3605 *******************************************************************************/
3606
3607 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3608 {
3609         classinfo *cls;
3610
3611         if ((cls = loader_load(topname)) == NULL) {
3612                 log_plain("Could not load important system class: ");
3613                 log_plain_utf(topname);
3614                 log_nl();
3615                 panic("Could not load important system class");
3616         }
3617
3618         if (top) *top = cls;
3619
3620         return cls;
3621 }
3622
3623
3624 /**************** function: create_primitive_classes ***************************
3625
3626         create classes representing primitive types 
3627
3628 ********************************************************************************/
3629
3630 void create_primitive_classes()
3631 {  
3632         int i;
3633
3634         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3635                 /* create primitive class */
3636                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3637                 c -> classUsed = NOTUSED; /* not used initially CO-RT */                
3638                 c -> impldBy = NULL;
3639                 
3640                 /* prevent loader from loading primitive class */
3641                 list_remove (&unloadedclasses, c);
3642                 c->loaded=true;
3643                 /* add to unlinked classes */
3644                 list_addlast (&unlinkedclasses, c);             
3645 /*JOWENN primitive types don't have objects as super class              c -> super = class_java_lang_Object; */
3646                 class_link (c);
3647
3648                 primitivetype_table[i].class_primitive = c;
3649
3650                 /* create class for wrapping the primitive type */
3651                 primitivetype_table[i].class_wrap =
3652                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
3653                 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3654                 primitivetype_table[i].class_wrap  -> impldBy = NULL;
3655
3656                 /* create the primitive array class */
3657                 if (primitivetype_table[i].arrayname) {
3658                         c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3659                         primitivetype_table[i].arrayclass = c;
3660                         c->loaded=true;
3661                         if (!c->linked) class_link(c);
3662                         primitivetype_table[i].arrayvftbl = c->vftbl;
3663                 }
3664         }
3665 }
3666
3667 /**************** function: class_primitive_from_sig ***************************
3668
3669         return the primitive class indicated by the given signature character
3670
3671     If the descriptor does not indicate a valid primitive type the
3672     return value is NULL.
3673
3674 ********************************************************************************/
3675
3676 classinfo *class_primitive_from_sig(char sig)
3677 {
3678         switch (sig) {
3679           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3680           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3681           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3682           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3683           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3684           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3685           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3686           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3687           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3688         }
3689         return NULL;
3690 }
3691
3692 /****************** function: class_from_descriptor ****************************
3693
3694     return the class indicated by the given descriptor
3695
3696     utf_ptr....first character of descriptor
3697     end_ptr....first character after the end of the string
3698     next.......if non-NULL, *next is set to the first character after
3699                the descriptor. (Undefined if an error occurs.)
3700
3701     mode.......a combination (binary or) of the following flags:
3702
3703                (Flags marked with * are the default settings.)
3704
3705                What to do if a reference type descriptor is parsed successfully:
3706
3707                    CLASSLOAD_SKIP...skip it and return something != NULL
3708                                  * CLASSLOAD_NEW....get classinfo * via class_new
3709                    CLASSLOAD_LOAD...get classinfo * via loader_load
3710
3711                How to handle primitive types:
3712
3713                              * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3714                    CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3715
3716                How to handle "V" descriptors:
3717
3718                              * CLASSLOAD_VOID.....handle it like other primitive types
3719                    CLASSLOAD_NOVOID...treat it as an error
3720
3721                How to deal with extra characters after the end of the
3722                descriptor:
3723
3724                              * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3725                    CLASSLOAD_CHECKEND.....treat them as an error
3726
3727                How to deal with errors:
3728
3729                              * CLASSLOAD_PANIC....abort execution with an error message
3730                    CLASSLOAD_NOPANIC..return NULL on error
3731
3732 ********************************************************************************/
3733
3734 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3735                                                                  char **next, int mode)
3736 {
3737         char *start = utf_ptr;
3738         bool error = false;
3739         utf *name;
3740
3741         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3742
3743         if (mode & CLASSLOAD_CHECKEND)
3744                 error |= (utf_ptr != end_ptr);
3745         
3746         if (!error) {
3747                 if (next) *next = utf_ptr;
3748                 
3749                 switch (*start) {
3750                   case 'V':
3751                           if (mode & CLASSLOAD_NOVOID)
3752                                   break;
3753                           /* FALLTHROUGH! */
3754                   case 'I':
3755                   case 'J':
3756                   case 'F':
3757                   case 'D':
3758                   case 'B':
3759                   case 'C':
3760                   case 'S':
3761                   case 'Z':
3762                           return (mode & CLASSLOAD_NULLPRIMITIVE)
3763                                   ? NULL
3764                                   : class_primitive_from_sig(*start);
3765                           
3766                   case 'L':
3767                           start++;
3768                           utf_ptr--;
3769                           /* FALLTHROUGH! */
3770                   case '[':
3771                           if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3772                           name = utf_new(start, utf_ptr - start);
3773                           return (mode & CLASSLOAD_LOAD)
3774                                   ? loader_load(name) : class_new(name); /* XXX handle errors */
3775                 }
3776         }
3777
3778         /* An error occurred */
3779         if (mode & CLASSLOAD_NOPANIC)
3780                 return NULL;
3781
3782         log_plain("Invalid descriptor at beginning of '");
3783         log_plain_utf(utf_new(start, end_ptr - start));
3784         log_plain("'");
3785         log_nl();
3786                                                   
3787         panic("Invalid descriptor");
3788
3789         /* keep compiler happy */
3790         return NULL;
3791 }
3792
3793
3794 /******************* function: type_from_descriptor ****************************
3795
3796     return the basic type indicated by the given descriptor
3797
3798     This function parses a descriptor and returns its basic type as
3799     TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3800
3801     cls...if non-NULL the referenced variable is set to the classinfo *
3802           returned by class_from_descriptor.
3803
3804     For documentation of the arguments utf_ptr, end_ptr, next and mode
3805     see class_from_descriptor. The only difference is that
3806     type_from_descriptor always uses CLASSLOAD_PANIC.
3807
3808 ********************************************************************************/
3809
3810 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3811                                                  char **next, int mode)
3812 {
3813         classinfo *mycls;
3814         if (!cls) cls = &mycls;
3815         *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3816         switch (*utf_ptr) {
3817           case 'B': 
3818           case 'C':
3819           case 'I':
3820           case 'S':  
3821           case 'Z':
3822                   return TYPE_INT;
3823           case 'D':
3824                   return TYPE_DOUBLE;
3825           case 'F':
3826                   return TYPE_FLOAT;
3827           case 'J':
3828                   return TYPE_LONG;
3829           case 'V':
3830                   return TYPE_VOID;
3831         }
3832         return TYPE_ADDRESS;
3833 }
3834
3835
3836 /*************** function: create_pseudo_classes *******************************
3837
3838         create pseudo classes used by the typechecker
3839
3840 ********************************************************************************/
3841
3842 static void create_pseudo_classes()
3843 {
3844     /* pseudo class for Arraystubs (extends java.lang.Object) */
3845     
3846     pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3847     list_remove(&unloadedclasses, pseudo_class_Arraystub);
3848
3849     pseudo_class_Arraystub->super = class_java_lang_Object;
3850     pseudo_class_Arraystub->interfacescount = 2;
3851     pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3852     pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3853     pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3854
3855     list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3856     class_link(pseudo_class_Arraystub);
3857
3858         pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3859
3860     /* pseudo class representing the null type */
3861     
3862     pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3863     list_remove(&unloadedclasses, pseudo_class_Null);
3864
3865     pseudo_class_Null->super = class_java_lang_Object;
3866
3867     list_addlast(&unlinkedclasses, pseudo_class_Null);
3868     class_link(pseudo_class_Null);      
3869
3870     /* pseudo class representing new uninitialized objects */
3871     
3872     pseudo_class_New = class_new(utf_new_char("$NEW$"));
3873     list_remove(&unloadedclasses, pseudo_class_New);
3874
3875     pseudo_class_New->super = class_java_lang_Object;
3876
3877     list_addlast(&unlinkedclasses, pseudo_class_New);
3878     class_link(pseudo_class_New);       
3879 }
3880
3881
3882 /********************** Function: loader_init **********************************
3883
3884         Initializes all lists and loads all classes required for the system or the
3885         compiler.
3886
3887 *******************************************************************************/
3888  
3889 void loader_init(u1 *stackbottom)
3890 {
3891         interfaceindex = 0;
3892         
3893         list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3894         list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3895         list_init(&linkedclasses, OFFSET(classinfo, listnode));
3896
3897         /* create utf-symbols for pointer comparison of frequently used strings */
3898         utf_innerclasses    = utf_new_char("InnerClasses");
3899         utf_constantvalue   = utf_new_char("ConstantValue");
3900         utf_code             = utf_new_char("Code");
3901         utf_exceptions      = utf_new_char("Exceptions");
3902         utf_linenumbertable     = utf_new_char("LineNumberTable");
3903         utf_sourcefile          = utf_new_char("SourceFile");
3904         utf_finalize        = utf_new_char("finalize");
3905         utf_fidesc              = utf_new_char("()V");
3906         utf_init                = utf_new_char("<init>");
3907         utf_clinit              = utf_new_char("<clinit>");
3908         utf_initsystemclass = utf_new_char("initializeSystemClass");
3909         utf_systemclass     = utf_new_char("java/lang/System");
3910         utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
3911         utf_initialize      = utf_new_char("initialize");
3912         utf_initializedesc  = utf_new_char("(I)V");
3913
3914         utf_vmclass         = utf_new_char("java/lang/VMClass");
3915         utf_java_lang_Object= utf_new_char("java/lang/Object");
3916
3917         array_packagename   = utf_new_char("<the array package>");
3918
3919         /* create some important classes */
3920         /* These classes have to be created now because the classinfo
3921          * pointers are used in the loading code.
3922          */
3923         class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3924         class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3925         class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3926         class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3927
3928         if (verbose) log_text("loader_init: java/lang/Object");
3929         /* load the classes which were created above */
3930         loader_load_sysclass(NULL, class_java_lang_Object->name);
3931
3932         loader_inited = 1; /*JOWENN*/
3933
3934         loader_load_sysclass(&class_java_lang_Throwable,
3935                                                  utf_new_char("java/lang/Throwable"));
3936
3937         /* create classes representing primitive types */
3938         create_primitive_classes();
3939
3940         /* create classes used by the typechecker */
3941         create_pseudo_classes();
3942
3943         /* correct vftbl-entries (retarded loading of class java/lang/String) */
3944         stringtable_update();
3945
3946 #if defined(USE_THREADS)
3947         if (stackbottom!=0)
3948                 initLocks();
3949 #endif
3950
3951         loader_inited = 1;
3952 }
3953
3954
3955 /********************* Function: loader_initclasses ****************************
3956
3957         Initializes all loaded but uninitialized classes
3958
3959 *******************************************************************************/
3960
3961 #if 0
3962 /* XXX TWISTI: i think we do not need this */
3963 void loader_initclasses ()
3964 {
3965         classinfo *c;
3966         
3967 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3968         pthread_mutex_lock(&compiler_mutex);
3969 #endif
3970
3971         intsDisable();                     /* schani */
3972
3973         if (makeinitializations) {
3974                 c = list_first(&linkedclasses);
3975                 while (c) {
3976                         class_init(c);
3977                         c = list_next(&linkedclasses, c);
3978                 }
3979         }
3980
3981         intsRestore();                      /* schani */
3982         
3983 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3984         pthread_mutex_unlock(&compiler_mutex);
3985 #endif
3986 }
3987 #endif
3988
3989
3990 static void loader_compute_class_values(classinfo *c)
3991 {
3992         classinfo *subs;
3993
3994         c->vftbl->baseval = ++classvalue;
3995
3996         subs = c->sub;
3997         while (subs != NULL) {
3998                 loader_compute_class_values(subs);
3999                 subs = subs->nextsub;
4000         }
4001         c->vftbl->diffval = classvalue - c->vftbl->baseval;
4002         
4003 /*      
4004         {
4005         int i;
4006         for (i = 0; i < c->index; i++)
4007                 printf(" ");
4008         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
4009         utf_display(c->name);
4010         printf("\n");
4011         }
4012 */      
4013 }
4014
4015
4016 void loader_compute_subclasses()
4017 {
4018         classinfo *c;
4019         
4020 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4021         intsDisable();                     /* schani */
4022 #endif
4023
4024         c = list_first(&linkedclasses);
4025         while (c) {
4026                 if (!(c->flags & ACC_INTERFACE)) {
4027                         c->nextsub = 0;
4028                         c->sub = 0;
4029                 }
4030                 c = list_next(&linkedclasses, c);
4031         }
4032
4033         c = list_first(&linkedclasses);
4034         while (c) {
4035                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4036                         c->nextsub = c->super->sub;
4037                         c->super->sub = c;
4038                 }
4039                 c = list_next(&linkedclasses, c);
4040         }
4041
4042         classvalue = 0;
4043 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4044         cast_lock();
4045 #endif
4046         loader_compute_class_values(class_java_lang_Object);
4047 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4048         cast_unlock();
4049 #endif
4050
4051 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4052         intsRestore();                      /* schani */
4053 #endif
4054 }
4055
4056
4057 /******************** function classloader_buffer ******************************
4058  
4059     sets buffer for reading classdata
4060
4061 *******************************************************************************/
4062
4063 void classload_buffer(u1 *buf, int len)
4064 {
4065         classbuffer      = buf;
4066         classbuffer_size = len;
4067         classbuf_pos     = buf - 1;
4068 }
4069
4070
4071 /******************** Function: loader_close ***********************************
4072
4073         Frees all resources
4074         
4075 *******************************************************************************/
4076
4077 void loader_close()
4078 {
4079         classinfo *c;
4080
4081         while ((c = list_first(&unloadedclasses))) {
4082                 list_remove(&unloadedclasses, c);
4083 /*              class_free(c); */
4084         }
4085         while ((c = list_first(&unlinkedclasses))) {
4086                 list_remove(&unlinkedclasses, c);
4087 /*              class_free(c); */
4088         }
4089         while ((c = list_first(&linkedclasses))) {
4090                 list_remove(&linkedclasses, c);
4091 /*              class_free(c); */
4092         }
4093 }
4094
4095
4096 /*
4097  * These are local overrides for various environment variables in Emacs.
4098  * Please do not remove this and leave it at the end of the file, where
4099  * Emacs will automagically detect them.
4100  * ---------------------------------------------------------------------
4101  * Local variables:
4102  * mode: c
4103  * indent-tabs-mode: t
4104  * c-basic-offset: 4
4105  * tab-width: 4
4106  * End:
4107  */