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