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