Also compile without zlib.
[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 680 2003-11-24 23:12:29Z twisti $
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
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         if (loader_inited)
1657                 loader_load(c->name);
1658 }
1659
1660 /****************** Function: class_link_array *********************************
1661
1662     This function is called by class_link to create the
1663     arraydescriptor for an array class.
1664
1665     This function returns NULL if the array cannot be linked because
1666     the component type has not been linked yet.
1667
1668 *******************************************************************************/
1669
1670 static
1671 arraydescriptor *
1672 class_link_array(classinfo *c)
1673 {
1674         classinfo *comp = NULL;
1675         int namelen = c->name->blength;
1676         arraydescriptor *desc;
1677         vftbl *compvftbl;
1678
1679         /* Check the component type */
1680         switch (c->name->text[1]) {
1681           case '[':
1682                   /* c is an array of arrays. */
1683                   comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1684                   if (!comp) panic("Could not find component array class.");
1685                   break;
1686
1687           case 'L':
1688                   /* c is an array of objects. */
1689                   comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1690                   if (!comp) panic("Could not find component class.");
1691                   break;
1692         }
1693
1694         /* If the component type has not been linked return NULL */
1695         if (comp && !comp->linked)
1696                 return NULL;
1697
1698         /* Allocate the arraydescriptor */
1699         desc = NEW(arraydescriptor);
1700
1701         if (comp) {
1702                 /* c is an array of references */
1703                 desc->arraytype = ARRAYTYPE_OBJECT;
1704                 desc->componentsize = sizeof(void*);
1705                 desc->dataoffset = OFFSET(java_objectarray,data);
1706                 
1707                 compvftbl = comp->vftbl;
1708                 if (!compvftbl)
1709                         panic("Component class has no vftbl.");
1710                 desc->componentvftbl = compvftbl;
1711                 
1712                 if (compvftbl->arraydesc) {
1713                         desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1714                         desc->dimension = compvftbl->arraydesc->dimension + 1;
1715                 }
1716                 else {
1717                         desc->elementvftbl = compvftbl;
1718                         desc->dimension = 1;
1719                 }
1720         }
1721         else {
1722                 /* c is an array of a primitive type */
1723                 switch (c->name->text[1]) {
1724                   case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1725                             desc->dataoffset = OFFSET(java_booleanarray,data);
1726                                 desc->componentsize = sizeof(u1); break;
1727                   case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1728                             desc->dataoffset = OFFSET(java_bytearray,data);
1729                                 desc->componentsize = sizeof(u1); break;
1730                   case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1731                             desc->dataoffset = OFFSET(java_chararray,data);
1732                                 desc->componentsize = sizeof(u2); break;
1733                   case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1734                             desc->dataoffset = OFFSET(java_doublearray,data);
1735                                 desc->componentsize = sizeof(double); break;
1736                   case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1737                             desc->dataoffset = OFFSET(java_floatarray,data);
1738                                 desc->componentsize = sizeof(float); break;
1739                   case 'I': desc->arraytype = ARRAYTYPE_INT;
1740                             desc->dataoffset = OFFSET(java_intarray,data);
1741                                 desc->componentsize = sizeof(s4); break;
1742                   case 'J': desc->arraytype = ARRAYTYPE_LONG;
1743                             desc->dataoffset = OFFSET(java_longarray,data);
1744                                 desc->componentsize = sizeof(s8); break;
1745                   case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1746                             desc->dataoffset = OFFSET(java_shortarray,data);
1747                                 desc->componentsize = sizeof(s2); break;
1748                   default:
1749                           panic("Invalid array class name");
1750                 }
1751                 
1752                 desc->componentvftbl = NULL;
1753                 desc->elementvftbl = NULL;
1754                 desc->dimension = 1;
1755         }
1756
1757         return desc;
1758 }
1759
1760 /********************** Function: class_link ***********************************
1761
1762         Tries to link a class. The super class and every implemented interface must
1763         already have been linked. The function calculates the length in bytes that
1764         an instance of this class requires as well as the VTBL for methods and
1765         interface methods.
1766         
1767         If the class can be linked, it is removed from the list 'unlinkedclasses'
1768         and added to 'linkedclasses'. Otherwise, it is moved to the end of
1769         'unlinkedclasses'.
1770
1771         Attention: If cyclical class definitions are encountered, the program gets
1772         into an infinite loop (we'll have to work that out)
1773
1774 *******************************************************************************/
1775
1776 void class_link(classinfo *c)
1777 {
1778         s4 supervftbllength;          /* vftbllegnth of super class               */
1779         s4 vftbllength;               /* vftbllength of current class             */
1780         s4 interfacetablelength;      /* interface table length                   */
1781         classinfo *super = c->super;  /* super class                              */
1782         classinfo *ic, *c2;           /* intermediate class variables             */
1783         vftbl *v;                     /* vftbl of current class                   */
1784         s4 i;                         /* interface/method/field counter           */
1785         arraydescriptor *arraydesc = NULL;  /* descriptor for array classes       */
1786
1787
1788         /*  check if all superclasses are already linked, if not put c at end of
1789             unlinked list and return. Additionally initialize class fields.       */
1790
1791         /*  check interfaces */
1792
1793         for (i = 0; i < c->interfacescount; i++) {
1794                 ic = c->interfaces[i];
1795                 if (!ic->linked) {
1796                         list_remove(&unlinkedclasses, c);
1797                         list_addlast(&unlinkedclasses, c);
1798                         return; 
1799                 }
1800         }
1801         
1802         /*  check super class */
1803
1804         if (super == NULL) {          /* class java.long.Object */
1805                 c->index = 0;
1806         c->classUsed = USED;     /* Object class is always used CO-RT*/
1807                 c -> impldBy = NULL;
1808                 c->instancesize = sizeof(java_objectheader);
1809                 
1810                 vftbllength = supervftbllength = 0;
1811
1812                 c->finalizer = NULL;
1813         }
1814         else {
1815                 if (!super->linked) {
1816                         list_remove(&unlinkedclasses, c);
1817                         list_addlast(&unlinkedclasses, c);
1818                         return; 
1819                 }
1820
1821                 /* handle array classes */
1822                 if (c->name->text[0] == '[')
1823                         if ((arraydesc = class_link_array(c)) == NULL) {
1824                                 list_remove(&unlinkedclasses, c);
1825                                 list_addlast(&unlinkedclasses, c);
1826                                 return; 
1827                         }
1828                 
1829                 if (c->flags & ACC_INTERFACE)
1830                         c->index = interfaceindex++;
1831                 else
1832                         c->index = super->index + 1;
1833                 
1834                 c->instancesize = super->instancesize;
1835                 
1836                 vftbllength = supervftbllength = super->vftbl->vftbllength;
1837                 
1838                 c->finalizer = super->finalizer;
1839         }
1840
1841
1842         if (linkverbose) {
1843                 sprintf (logtext, "Linking Class: ");
1844                 utf_sprint (logtext+strlen(logtext), c->name );
1845                 dolog ();
1846         }
1847
1848         /* compute vftbl length */
1849
1850         for (i = 0; i < c->methodscount; i++) {
1851                 methodinfo *m = &(c->methods[i]);
1852                         
1853                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1854                         classinfo *sc = super;
1855                         while (sc) {
1856                                 int j;
1857                                 for (j = 0; j < sc->methodscount; j++) {
1858                                         if (method_canoverwrite(m, &(sc->methods[j]))) {
1859                                                 m->vftblindex = sc->methods[j].vftblindex;
1860                                                 goto foundvftblindex;
1861                                         }
1862                                 }
1863                                 sc = sc->super;
1864                         }
1865                         m->vftblindex = (vftbllength++);
1866                 foundvftblindex: ;
1867                 }
1868         }       
1869         
1870 #ifdef STATISTICS
1871         count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1872 #endif
1873
1874         /* compute interfacetable length */
1875
1876         interfacetablelength = 0;
1877         c2 = c;
1878         while (c2) {
1879                 for (i = 0; i < c2->interfacescount; i++) {
1880                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1881                         if (h > interfacetablelength)
1882                                 interfacetablelength = h;
1883                 }
1884                 c2 = c2->super;
1885         }
1886
1887         /* allocate virtual function table */
1888
1889         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1890                                                    (vftbllength - 1) + sizeof(methodptr*) *
1891                                                    (interfacetablelength - (interfacetablelength > 0)));
1892         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1893                                   (interfacetablelength > 1));
1894         c->header.vftbl = c->vftbl = v;
1895         v->class = c;
1896         v->vftbllength = vftbllength;
1897         v->interfacetablelength = interfacetablelength;
1898         v->arraydesc = arraydesc;
1899
1900         /* store interface index in vftbl */
1901         if (c->flags & ACC_INTERFACE)
1902                 v->baseval = -(c->index);
1903
1904         /* copy virtual function table of super class */
1905
1906         for (i = 0; i < supervftbllength; i++) 
1907                 v->table[i] = super->vftbl->table[i];
1908         
1909         /* add method stubs into virtual function table */
1910
1911         for (i = 0; i < c->methodscount; i++) {
1912                 methodinfo *m = &(c->methods[i]);
1913                 if (!(m->flags & ACC_STATIC)) {
1914                         v->table[m->vftblindex] = m->stubroutine;
1915                 }
1916         }
1917
1918         /* compute instance size and offset of each field */
1919         
1920         for (i = 0; i < c->fieldscount; i++) {
1921                 s4 dsize;
1922                 fieldinfo *f = &(c->fields[i]);
1923                 
1924                 if (!(f->flags & ACC_STATIC) ) {
1925                         dsize = desc_typesize (f->descriptor);
1926                         c->instancesize = ALIGN (c->instancesize, dsize);
1927                         f->offset = c->instancesize;
1928                         c->instancesize += dsize;
1929                 }
1930         }
1931
1932         /* initialize interfacetable and interfacevftbllength */
1933         
1934         v->interfacevftbllength = MNEW (s4, interfacetablelength);
1935
1936 #ifdef STATISTICS
1937         count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1938 #endif
1939
1940         for (i = 0; i < interfacetablelength; i++) {
1941                 v->interfacevftbllength[i] = 0;
1942                 v->interfacetable[-i] = NULL;
1943         }
1944         
1945         /* add interfaces */
1946         
1947         for (c2 = c; c2 != NULL; c2 = c2->super)
1948                 for (i = 0; i < c2->interfacescount; i++) {
1949                         class_addinterface (c, c2->interfaces[i]);
1950                 }
1951
1952         /* add finalizer method (not for java.lang.Object) */
1953
1954         if (super != NULL) {
1955                 methodinfo *fi;
1956                 static utf *finame = NULL;
1957                 static utf *fidesc = NULL;
1958
1959                 if (finame == NULL)
1960                         finame = utf_finalize;
1961                 if (fidesc == NULL)
1962                         fidesc = utf_fidesc;
1963
1964                 fi = class_findmethod (c, finame, fidesc);
1965                 if (fi != NULL) {
1966                         if (!(fi->flags & ACC_STATIC)) {
1967                                 c->finalizer = fi;
1968                         }
1969                 }
1970         }
1971
1972         /* final tasks */
1973
1974         c->linked = true;       
1975
1976         list_remove (&unlinkedclasses, c);
1977         list_addlast (&linkedclasses, c);
1978
1979 }
1980
1981
1982 /******************* Function: class_freepool **********************************
1983
1984         Frees all resources used by this classes Constant Pool.
1985
1986 *******************************************************************************/
1987
1988 static void class_freecpool (classinfo *c)
1989 {
1990         u4 idx;
1991         u4 tag;
1992         voidptr info;
1993         
1994         for (idx=0; idx < c->cpcount; idx++) {
1995                 tag = c->cptags[idx];
1996                 info = c->cpinfos[idx];
1997                 
1998                 if (info != NULL) {
1999                         switch (tag) {
2000                         case CONSTANT_Fieldref:
2001                         case CONSTANT_Methodref:
2002                         case CONSTANT_InterfaceMethodref:
2003                                 FREE (info, constant_FMIref);
2004                                 break;
2005                         case CONSTANT_Integer:
2006                                 FREE (info, constant_integer);
2007                                 break;
2008                         case CONSTANT_Float:
2009                                 FREE (info, constant_float);
2010                                 break;
2011                         case CONSTANT_Long:
2012                                 FREE (info, constant_long);
2013                                 break;
2014                         case CONSTANT_Double:
2015                                 FREE (info, constant_double);
2016                                 break;
2017                         case CONSTANT_NameAndType:
2018                                 FREE (info, constant_nameandtype);
2019                                 break;
2020                         }
2021                         }
2022                 }
2023
2024         MFREE (c -> cptags,  u1, c -> cpcount);
2025         MFREE (c -> cpinfos, voidptr, c -> cpcount);
2026 }
2027
2028
2029 /*********************** Function: class_free **********************************
2030
2031         Frees all resources used by the class.
2032
2033 *******************************************************************************/
2034
2035 static void class_free (classinfo *c)
2036 {
2037         s4 i;
2038         vftbl *v;
2039                 
2040         class_freecpool (c);
2041
2042         MFREE (c->interfaces, classinfo*, c->interfacescount);
2043
2044         for (i = 0; i < c->fieldscount; i++)
2045                 field_free(&(c->fields[i]));
2046         
2047         for (i = 0; i < c->methodscount; i++)
2048                 method_free(&(c->methods[i]));
2049         MFREE (c->methods, methodinfo, c->methodscount);
2050
2051         if ((v = c->vftbl) != NULL) {
2052                 if (v->arraydesc)
2053                         mem_free(v->arraydesc,sizeof(arraydescriptor));
2054                 
2055                 for (i = 0; i < v->interfacetablelength; i++) {
2056                         MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2057                         }
2058                 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2059
2060                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2061                     sizeof(methodptr*) * (v->interfacetablelength -
2062                                          (v->interfacetablelength > 0));
2063                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2064                                              (v->interfacetablelength > 1));
2065                 mem_free (v, i);
2066                 }
2067
2068         if (c->innerclasscount)
2069                 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2070
2071         /*      if (c->classvftbl)
2072                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2073         
2074         FREE (c, classinfo);
2075 }
2076
2077 /************************* Function: class_findfield ***************************
2078         
2079         Searches a 'classinfo' structure for a field having the given name and
2080         type.
2081
2082 *******************************************************************************/
2083
2084
2085 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2086 {
2087         s4 i;
2088
2089         
2090         for (i = 0; i < c->fieldscount; i++) { 
2091                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
2092                         return &(c->fields[i]);                                                         
2093     }
2094
2095         panic ("Can not find field given in CONSTANT_Fieldref");
2096         return NULL;
2097 }
2098
2099
2100 /************************* Function: class_findmethod **************************
2101         
2102         Searches a 'classinfo' structure for a method having the given name and
2103         type and returns the index in the class info structure.
2104         If type is NULL, it is ignored.
2105
2106 *******************************************************************************/
2107
2108 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2109 {
2110         s4 i;
2111 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2112         char *buffer;                   
2113         int buffer_len, pos;
2114 #endif
2115 #ifdef JOWENN_DEBUG1
2116
2117         buffer_len = 
2118           utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2119         
2120         buffer = MNEW(char, buffer_len);
2121
2122         strcpy(buffer, "class_findmethod: method:");
2123         utf_sprint(buffer+strlen(buffer), name);
2124         strcpy(buffer+strlen(buffer), ", desc: ");
2125         utf_sprint(buffer+strlen(buffer), desc);
2126         strcpy(buffer+strlen(buffer), ", classname: ");
2127         utf_sprint(buffer+strlen(buffer), c->name);
2128         
2129         log_text(buffer);       
2130
2131         MFREE(buffer, char, buffer_len);
2132 #endif  
2133         for (i = 0; i < c->methodscount; i++) {
2134 #ifdef JOWENN_DEBUG2
2135                 buffer_len = 
2136                   utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2137         
2138                 buffer = MNEW(char, buffer_len);
2139
2140                 strcpy(buffer, "class_findmethod: comparing to method:");
2141                 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2142                 strcpy(buffer+strlen(buffer), ", desc: ");
2143                 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2144         
2145                 log_text(buffer);       
2146
2147                 MFREE(buffer, char, buffer_len);
2148                 #endif  
2149                 
2150                 
2151                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2152                                                    (c->methods[i].descriptor == desc)))
2153                         return i;
2154                 }
2155 #ifdef JOWENN_DEBUG2    
2156         class_showconstantpool(c);
2157         log_text("class_findmethod: returning NULL");
2158 #endif
2159         return -1;
2160 }
2161
2162
2163
2164 /************************* Function: class_findmethod **************************
2165         
2166         Searches a 'classinfo' structure for a method having the given name and
2167         type.
2168         If type is NULL, it is ignored.
2169
2170 *******************************************************************************/
2171
2172 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2173 {
2174 #if 0
2175         s4 i;
2176 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2177         char *buffer;                   
2178         int buffer_len, pos;
2179 #endif
2180 #ifdef JOWENN_DEBUG1
2181
2182         buffer_len = 
2183           utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2184         
2185         buffer = MNEW(char, buffer_len);
2186
2187         strcpy(buffer, "class_findmethod: method:");
2188         utf_sprint(buffer+strlen(buffer), name);
2189         strcpy(buffer+strlen(buffer), ", desc: ");
2190         utf_sprint(buffer+strlen(buffer), desc);
2191         strcpy(buffer+strlen(buffer), ", classname: ");
2192         utf_sprint(buffer+strlen(buffer), c->name);
2193         
2194         log_text(buffer);       
2195
2196         MFREE(buffer, char, buffer_len);
2197 #endif  
2198         for (i = 0; i < c->methodscount; i++) {
2199 #ifdef JOWENN_DEBUG2
2200                 buffer_len = 
2201                   utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2202         
2203                 buffer = MNEW(char, buffer_len);
2204
2205                 strcpy(buffer, "class_findmethod: comparing to method:");
2206                 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2207                 strcpy(buffer+strlen(buffer), ", desc: ");
2208                 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2209         
2210                 log_text(buffer);       
2211
2212                 MFREE(buffer, char, buffer_len);
2213                 #endif  
2214                 
2215                 
2216                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2217                                                    (c->methods[i].descriptor == desc)))
2218                         return &(c->methods[i]);
2219                 }
2220 #ifdef JOWENN_DEBUG2    
2221         class_showconstantpool(c);
2222         log_text("class_findmethod: returning NULL");
2223 #endif
2224         return NULL;
2225 #endif
2226         s4 idx=class_findmethodIndex(c,name,desc);
2227 /*      if (idx==-1) log_text("class_findmethod: method not found");*/
2228         if (idx==-1) return NULL;
2229         return &(c->methods[idx]);
2230 }
2231
2232
2233
2234
2235
2236
2237 /************************* Function: class_findmethod_approx ******************
2238         
2239         like class_findmethod but ignores the return value when comparing the
2240         descriptor.
2241
2242 *******************************************************************************/
2243
2244 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2245 {
2246         s4 i;
2247
2248         for (i = 0; i < c->methodscount; i++) 
2249                 if (c->methods[i].name == name) {
2250                         utf *meth_descr = c->methods[i].descriptor;
2251                         
2252                         if (desc == NULL) 
2253                                 /* ignore type */
2254                                 return &(c->methods[i]);
2255
2256                         if (desc->blength <= meth_descr->blength) {
2257                                            /* current position in utf text   */
2258                                            char *desc_utf_ptr = desc->text;      
2259                                            char *meth_utf_ptr = meth_descr->text;                                         
2260                                            /* points behind utf strings */
2261                                            char *desc_end = utf_end(desc);         
2262                                            char *meth_end = utf_end(meth_descr);   
2263                                            char ch;
2264
2265                                            /* compare argument types */
2266                                            while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2267
2268                                                    if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2269                                                            break; /* no match */
2270
2271                                                    if (ch==')')
2272                                                            return &(c->methods[i]);   /* all parameter types equal */
2273                                            }
2274                         }
2275                 }
2276
2277         return NULL;
2278 }
2279
2280 /***************** Function: class_resolvemethod_approx ***********************
2281         
2282         Searches a class and every super class for a method (without paying
2283         attention to the return value)
2284
2285 *******************************************************************************/
2286
2287 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2288 {
2289         while (c) {
2290                 /* search for method (ignore returntype) */
2291                 methodinfo *m = class_findmethod_approx (c, name, desc);
2292                 /* method found */
2293                 if (m) return m;
2294                 /* search superclass */
2295                 c = c->super;
2296                 }
2297         return NULL;
2298 }
2299
2300
2301 /************************* Function: class_resolvemethod ***********************
2302         
2303         Searches a class and every super class for a method.
2304
2305 *******************************************************************************/
2306
2307 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2308 {
2309         while (c) {
2310                 methodinfo *m = class_findmethod(c, name, desc);
2311                 if (m) return m;
2312                 /* search superclass */
2313                 c = c->super;
2314         }
2315         return NULL;
2316 }
2317
2318
2319
2320 /************************* Function: class_issubclass **************************
2321
2322         Checks if sub is a descendant of super.
2323         
2324 *******************************************************************************/
2325
2326 bool class_issubclass(classinfo *sub, classinfo *super)
2327 {
2328         for (;;) {
2329                 if (!sub) return false;
2330                 if (sub==super) return true;
2331                 sub = sub -> super;
2332         }
2333 }
2334
2335
2336
2337 /****************** Initialization function for classes ******************
2338
2339         In Java, every class can have a static initialization function. This
2340         function has to be called BEFORE calling other methods or accessing static
2341         variables.
2342
2343 *******************************************************************************/
2344
2345 #ifdef USE_THREADS
2346 extern int blockInts;
2347 #endif
2348
2349 void class_init(classinfo *c)
2350 {
2351         methodinfo *m;
2352         java_objectheader *exceptionptr;
2353         s4 i;
2354         int b;
2355
2356
2357         if (!makeinitializations)
2358                 return;
2359         if (c->initialized)
2360                 return;
2361         c -> initialized = true;
2362
2363
2364
2365 #ifdef STATISTICS
2366         count_class_inits++;
2367 #endif
2368
2369         if (c->super)
2370                 class_init (c->super);
2371         for (i=0; i < c->interfacescount; i++)
2372                 class_init(c->interfaces[i]);  /* real */
2373
2374         m = class_findmethod (c, utf_clinit, utf_fidesc);
2375         if (!m) {
2376                 if (initverbose) {
2377                         sprintf (logtext, "Class ");
2378                         utf_sprint (logtext+strlen(logtext), c->name);
2379                         sprintf (logtext+strlen(logtext), " has no initializer");
2380                         dolog ();
2381                         }
2382 /*              goto callinitialize;*/
2383                 return;
2384                 }
2385
2386         if (! (m->flags & ACC_STATIC))
2387                 panic ("Class initializer is not static!");
2388
2389         if (initverbose) {
2390                 sprintf (logtext, "Starting initializer for class: ");
2391                 utf_sprint (logtext+strlen(logtext), c->name);
2392                 dolog ();
2393         }
2394
2395 #ifdef USE_THREADS
2396         b = blockInts;
2397         blockInts = 0;
2398 #endif
2399
2400         exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2401
2402 #ifdef USE_THREADS
2403         assert(blockInts == 0);
2404         blockInts = b;
2405 #endif
2406
2407         if (exceptionptr) {
2408                 printf ("#### Initializer of ");
2409                 utf_display (c->name);
2410                 printf (" has thrown: ");
2411                 utf_display (exceptionptr->vftbl->class->name);
2412                 printf ("\n");
2413                 fflush (stdout);
2414                 }
2415
2416         if (initverbose) {
2417                 sprintf (logtext, "Finished initializer for class: ");
2418                 utf_sprint (logtext+strlen(logtext), c->name);
2419                 dolog ();
2420         }
2421         if (c->name == utf_systemclass) {
2422                 /* class java.lang.System requires explicit initialization */
2423
2424                 if (initverbose)
2425                         printf ("#### Initializing class System");
2426
2427                 /* find initializing method */
2428                 m = class_findmethod (c,
2429                                         utf_initsystemclass,
2430                                         utf_fidesc);
2431
2432                 if (!m) {
2433                         /* no method found */
2434                         /* printf("initializeSystemClass failed"); */
2435                         return;
2436                 }
2437                 #ifdef USE_THREADS
2438                         b = blockInts;
2439                         blockInts = 0;
2440                 #endif
2441
2442                 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2443
2444                 #ifdef USE_THREADS
2445                         assert(blockInts == 0);
2446                         blockInts = b;
2447                 #endif
2448
2449                 if (exceptionptr) {
2450                         printf ("#### initializeSystemClass has thrown: ");
2451                         utf_display (exceptionptr->vftbl->class->name);
2452                         printf ("\n");
2453                         fflush (stdout);
2454                 }
2455         }
2456
2457 }
2458
2459
2460
2461
2462 /********* Function: find_class_method_constant *********/
2463 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)  
2464 {
2465         u4 i;
2466         voidptr e;
2467
2468         for (i=0; i<c->cpcount; i++) {
2469                 
2470                 e = c -> cpinfos [i];
2471                 if (e) {
2472                         
2473                         switch (c -> cptags [i]) {
2474                         case CONSTANT_Methodref:
2475                                 {
2476                                         constant_FMIref *fmi = e;
2477                                         if (       (fmi->class->name == c1)  
2478                                                            && (fmi->name == m1)
2479                                                            && (fmi->descriptor == d1)) {
2480                                         
2481                                                 return i;
2482                                         }
2483                                 }
2484                                 break;
2485
2486                         case CONSTANT_InterfaceMethodref:
2487                                 {
2488                                         constant_FMIref *fmi = e;
2489                                         if (       (fmi->class->name == c1)  
2490                                                            && (fmi->name == m1)
2491                                                            && (fmi->descriptor == d1)) {
2492
2493                                                 return i;
2494                                         }
2495                                 }
2496                                 break;
2497                         }
2498                 }
2499         }
2500
2501         return -1;
2502 }
2503
2504
2505 void class_showconstanti(classinfo *c, int ii) 
2506 {
2507         u4 i = ii;
2508         voidptr e;
2509                 
2510         e = c->cpinfos [i];
2511         printf ("#%d:  ", (int) i);
2512         if (e) {
2513                 switch (c->cptags [i]) {
2514                 case CONSTANT_Class:
2515                         printf("Classreference -> ");
2516                         utf_display(((classinfo*)e)->name);
2517                         break;
2518                                 
2519                 case CONSTANT_Fieldref:
2520                         printf("Fieldref -> "); goto displayFMIi;
2521                 case CONSTANT_Methodref:
2522                         printf("Methodref -> "); goto displayFMIi;
2523                 case CONSTANT_InterfaceMethodref:
2524                         printf("InterfaceMethod -> "); goto displayFMIi;
2525                 displayFMIi:
2526                         {
2527                                 constant_FMIref *fmi = e;
2528                                 utf_display(fmi->class->name);
2529                                 printf(".");
2530                                 utf_display(fmi->name);
2531                                 printf(" ");
2532                                 utf_display(fmi->descriptor);
2533                         }
2534                         break;
2535
2536                 case CONSTANT_String:
2537                         printf("String -> ");
2538                         utf_display(e);
2539                         break;
2540                 case CONSTANT_Integer:
2541                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2542                         break;
2543                 case CONSTANT_Float:
2544                         printf("Float -> %f", ((constant_float*)e)->value);
2545                         break;
2546                 case CONSTANT_Double:
2547                         printf("Double -> %f", ((constant_double*)e)->value);
2548                         break;
2549                 case CONSTANT_Long:
2550                         {
2551                                 u8 v = ((constant_long*)e)->value;
2552 #if U8_AVAILABLE
2553                                 printf("Long -> %ld", (long int) v);
2554 #else
2555                                 printf("Long -> HI: %ld, LO: %ld\n", 
2556                                             (long int) v.high, (long int) v.low);
2557 #endif 
2558                         }
2559                         break;
2560                 case CONSTANT_NameAndType:
2561                         { 
2562                                 constant_nameandtype *cnt = e;
2563                                 printf("NameAndType: ");
2564                                 utf_display(cnt->name);
2565                                 printf(" ");
2566                                 utf_display(cnt->descriptor);
2567                         }
2568                         break;
2569                 case CONSTANT_Utf8:
2570                         printf("Utf8 -> ");
2571                         utf_display(e);
2572                         break;
2573                 default: 
2574                         panic("Invalid type of ConstantPool-Entry");
2575                 }
2576         }
2577         printf("\n");
2578 }
2579
2580
2581 void class_showconstantpool (classinfo *c) 
2582 {
2583         u4 i;
2584         voidptr e;
2585
2586         printf ("---- dump of constant pool ----\n");
2587
2588         for (i=0; i<c->cpcount; i++) {
2589                 printf ("#%d:  ", (int) i);
2590                 
2591                 e = c -> cpinfos [i];
2592                 if (e) {
2593                         
2594                         switch (c -> cptags [i]) {
2595                         case CONSTANT_Class:
2596                                 printf ("Classreference -> ");
2597                                 utf_display ( ((classinfo*)e) -> name );
2598                                 break;
2599                                 
2600                         case CONSTANT_Fieldref:
2601                                 printf ("Fieldref -> "); goto displayFMI;
2602                         case CONSTANT_Methodref:
2603                                 printf ("Methodref -> "); goto displayFMI;
2604                         case CONSTANT_InterfaceMethodref:
2605                                 printf ("InterfaceMethod -> "); goto displayFMI;
2606                         displayFMI:
2607                                 {
2608                                         constant_FMIref *fmi = e;
2609                                         utf_display ( fmi->class->name );
2610                                         printf (".");
2611                                         utf_display ( fmi->name);
2612                                         printf (" ");
2613                                         utf_display ( fmi->descriptor );
2614                                 }
2615                                 break;
2616
2617                         case CONSTANT_String:
2618                                 printf ("String -> ");
2619                                 utf_display (e);
2620                                 break;
2621                         case CONSTANT_Integer:
2622                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2623                                 break;
2624                         case CONSTANT_Float:
2625                                 printf ("Float -> %f", ((constant_float*)e) -> value);
2626                                 break;
2627                         case CONSTANT_Double:
2628                                 printf ("Double -> %f", ((constant_double*)e) -> value);
2629                                 break;
2630                         case CONSTANT_Long:
2631                                 {
2632                                         u8 v = ((constant_long*)e) -> value;
2633 #if U8_AVAILABLE
2634                                         printf ("Long -> %ld", (long int) v);
2635 #else
2636                                         printf ("Long -> HI: %ld, LO: %ld\n", 
2637                                                         (long int) v.high, (long int) v.low);
2638 #endif 
2639                                 }
2640                                 break;
2641                         case CONSTANT_NameAndType:
2642                                 {
2643                                         constant_nameandtype *cnt = e;
2644                                         printf ("NameAndType: ");
2645                                         utf_display (cnt->name);
2646                                         printf (" ");
2647                                         utf_display (cnt->descriptor);
2648                                 }
2649                                 break;
2650                         case CONSTANT_Utf8:
2651                                 printf ("Utf8 -> ");
2652                                 utf_display (e);
2653                                 break;
2654                         default: 
2655                                 panic ("Invalid type of ConstantPool-Entry");
2656                         }
2657                 }
2658
2659                 printf ("\n");
2660         }
2661 }
2662
2663
2664
2665 /********** Function: class_showmethods   (debugging only) *************/
2666
2667 void class_showmethods (classinfo *c)
2668 {
2669         s4 i;
2670         
2671         printf ("--------- Fields and Methods ----------------\n");
2672         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
2673
2674         printf ("This: "); utf_display (c->name); printf ("\n");
2675         if (c->super) {
2676                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2677                 }
2678         printf ("Index: %d\n", c->index);
2679         
2680         printf ("interfaces:\n");       
2681         for (i=0; i < c-> interfacescount; i++) {
2682                 printf ("   ");
2683                 utf_display (c -> interfaces[i] -> name);
2684                 printf (" (%d)\n", c->interfaces[i] -> index);
2685                 }
2686
2687         printf ("fields:\n");           
2688         for (i=0; i < c -> fieldscount; i++) {
2689                 field_display (&(c -> fields[i]));
2690                 }
2691
2692         printf ("methods:\n");
2693         for (i=0; i < c -> methodscount; i++) {
2694                 methodinfo *m = &(c->methods[i]);
2695                 if ( !(m->flags & ACC_STATIC)) 
2696                         printf ("vftblindex: %d   ", m->vftblindex);
2697
2698                 method_display ( m );
2699
2700                 }
2701
2702         printf ("Virtual function table:\n");
2703         for (i=0; i<c->vftbl->vftbllength; i++) {
2704                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
2705                 }
2706
2707 }
2708
2709
2710
2711 /******************************************************************************/
2712 /******************* General functions for the class loader *******************/
2713 /******************************************************************************/
2714
2715 /********************* Function: loader_load ***********************************
2716
2717         Loads and links the class desired class and each class and interface
2718         referenced by it.
2719         Returns: a pointer to this class
2720
2721 *******************************************************************************/
2722
2723 static int loader_load_running = 0;
2724
2725 classinfo *loader_load (utf *topname)
2726 {
2727         classinfo *top;
2728         classinfo *c;
2729         long int starttime=0,stoptime=0;
2730
2731         /* avoid recursive calls */
2732         if (loader_load_running)
2733                 return class_new(topname);
2734         loader_load_running++;
2735         
2736         intsDisable();                           /* schani */
2737
2738         if (getloadingtime)
2739                 starttime = getcputime();
2740
2741         top = class_new (topname);
2742
2743         /* load classes */
2744         while ( (c = list_first(&unloadedclasses)) ) {
2745                 if (!class_load (c)) {
2746                         list_remove (&unloadedclasses, c);
2747                         top=NULL;
2748                     }
2749         }
2750
2751         /* link classes */
2752         while ( (c = list_first(&unlinkedclasses)) ) {
2753                 class_link (c);
2754                 }
2755
2756         if (loader_inited)
2757                 loader_compute_subclasses();
2758
2759         /* measure time */
2760         if (getloadingtime) {
2761                 stoptime = getcputime();
2762                 loadingtime += (stoptime-starttime);
2763                 }
2764
2765         intsRestore();                          /* schani */
2766
2767         loader_load_running--;
2768         
2769         return top; 
2770 }
2771
2772
2773 /**************** function: create_primitive_classes ***************************
2774
2775         create classes representing primitive types 
2776
2777 ********************************************************************************/
2778
2779
2780 void create_primitive_classes()
2781 {  
2782         int i;
2783
2784         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2785                 /* create primitive class */
2786                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2787                 c -> classUsed = NOTUSED; /* not used initially CO-RT */                
2788                 c -> impldBy = NULL;
2789
2790                 /* prevent loader from loading primitive class */
2791                 list_remove (&unloadedclasses, c);
2792                 /* add to unlinked classes */
2793                 list_addlast (&unlinkedclasses, c);             
2794                 c -> super = class_java_lang_Object;
2795                 class_link (c);
2796
2797                 primitivetype_table[i].class_primitive = c;
2798
2799                 /* create class for wrapping the primitive type */
2800                 primitivetype_table[i].class_wrap =
2801                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
2802                 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2803                 primitivetype_table[i].class_wrap  -> impldBy = NULL;
2804
2805                 /* create the primitive array class */
2806                 if (primitivetype_table[i].arrayname) {
2807                         c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2808                         primitivetype_table[i].arrayclass = c;
2809                         if (!c->linked) class_link(c);
2810                         primitivetype_table[i].arrayvftbl = c->vftbl;
2811                 }
2812         }
2813 }
2814
2815 /**************** function: class_primitive_from_sig ***************************
2816
2817         return the primitive class indicated by the given signature character
2818
2819     If the descriptor does not indicate a valid primitive type the
2820     return value is NULL.
2821
2822 ********************************************************************************/
2823
2824 classinfo *class_primitive_from_sig(char sig)
2825 {
2826         switch (sig) {
2827           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2828           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2829           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2830           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2831           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2832           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2833           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2834           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2835           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2836         }
2837         return NULL;
2838 }
2839
2840 /****************** function: class_from_descriptor ****************************
2841
2842     return the class indicated by the given descriptor
2843
2844     utf_ptr....first character of descriptor
2845     end_ptr....first character after the end of the string
2846     next.......if non-NULL, *next is set to the first character after
2847                the descriptor
2848     mode.......what to do if a class descriptor is parsed successfully:
2849                    CLASSLOAD_SKIP...skip it and return something != NULL
2850                    CLASSLOAD_NEW....get classinfo * via class_new
2851                    CLASSLOAD_LOAD...get classinfo * via loader_load
2852
2853     If the descriptor is invalid the return value is NULL
2854
2855 ********************************************************************************/
2856
2857 classinfo *class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
2858 {
2859         char *start = utf_ptr;
2860         bool error = false;
2861         utf *name;
2862         
2863         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
2864         if (error) return NULL;
2865         if (next) *next = utf_ptr;
2866
2867         switch (*start) {
2868           case 'L':
2869                   start++;
2870                   utf_ptr--;
2871                   /* fallthrough */
2872           case '[':
2873                   if (mode == CLASSLOAD_SKIP) return class_java_lang_Object;
2874                   name = utf_new(start,utf_ptr-start);
2875                   return (mode == CLASSLOAD_LOAD) ? loader_load(name) : class_new(name);
2876           default:
2877                   return class_primitive_from_sig(*start);
2878         }
2879 }
2880
2881 /*************** function: create_pseudo_classes *******************************
2882
2883         create pseudo classes used by the typechecker
2884
2885 ********************************************************************************/
2886
2887 static void
2888 create_pseudo_classes()
2889 {
2890     /* pseudo class for Arraystubs (extends java.lang.Object) */
2891     
2892     pseudo_class_Arraystub = class_new( utf_new_char(";Arraystub;") );
2893     list_remove(&unloadedclasses,pseudo_class_Arraystub);
2894
2895     pseudo_class_Arraystub->super = class_java_lang_Object;
2896     pseudo_class_Arraystub->interfacescount = 2;
2897     pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
2898     pseudo_class_Arraystub->interfaces[0] =
2899         class_java_lang_Cloneable;
2900     pseudo_class_Arraystub->interfaces[1] =
2901         class_java_io_Serializable;
2902
2903     list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
2904     class_link(pseudo_class_Arraystub);
2905
2906         pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
2907
2908     /* pseudo class representing the null type */
2909     
2910     pseudo_class_Null = class_new( utf_new_char(";Null;") );
2911     list_remove(&unloadedclasses,pseudo_class_Null);
2912
2913     pseudo_class_Null->super = class_java_lang_Object;
2914
2915     list_addlast(&unlinkedclasses,pseudo_class_Null);
2916     class_link(pseudo_class_Null);      
2917 }
2918
2919 /********************** Function: loader_init **********************************
2920
2921         Initializes all lists and loads all classes required for the system or the
2922         compiler.
2923
2924 *******************************************************************************/
2925  
2926 void loader_init (u1 * stackbottom)
2927 {
2928         interfaceindex = 0;
2929         
2930         
2931         log_text("Entering loader_init");
2932                                 
2933         
2934         list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2935         list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2936         list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2937
2938         /* create utf-symbols for pointer comparison of frequently used strings */
2939         utf_innerclasses    = utf_new_char("InnerClasses");
2940         utf_constantvalue   = utf_new_char("ConstantValue");
2941         utf_code                = utf_new_char("Code");
2942         utf_finalize        = utf_new_char("finalize");
2943         utf_fidesc              = utf_new_char("()V");
2944         utf_clinit              = utf_new_char("<clinit>");
2945         utf_initsystemclass = utf_new_char("initializeSystemClass");
2946         utf_systemclass     = utf_new_char("java/lang/System");
2947         utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
2948         utf_initialize =utf_new_char("initialize");
2949         utf_initializedesc =utf_new_char("(I)V");
2950
2951         utf_vmclass =utf_new_char("java/lang/VMClass");
2952
2953         /* create some important classes */
2954         /* These classes have to be created now because the classinfo
2955          * pointers are used in the loading code.
2956          */
2957         class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
2958         class_java_lang_String = class_new( utf_new_char("java/lang/String") );
2959         class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
2960         class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
2961
2962         log_text("loader_init: java/lang/Object");
2963         /* load the classes which were created above */
2964         loader_load (class_java_lang_Object->name);
2965
2966         loader_inited=1; /*JOWENN*/
2967
2968         class_java_lang_Throwable =
2969                 loader_load( utf_new_char("java/lang/Throwable") );
2970
2971         log_text("loader_init:  loader_load: java/lang/ClassCastException");
2972         class_java_lang_ClassCastException =
2973                 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2974         class_java_lang_NullPointerException =
2975                 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2976         class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2977              utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2978         class_java_lang_NegativeArraySizeException = loader_load (
2979              utf_new_char ("java/lang/NegativeArraySizeException") );
2980         class_java_lang_OutOfMemoryError = loader_load (
2981              utf_new_char ("java/lang/OutOfMemoryError") );
2982         class_java_lang_ArrayStoreException =
2983                 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2984         class_java_lang_ArithmeticException =
2985                 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2986         class_java_lang_ThreadDeath =                             /* schani */
2987                 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2988         /* create classes representing primitive types */
2989         create_primitive_classes();
2990
2991         /* create classes used by the typechecker */
2992         create_pseudo_classes();
2993
2994         /* correct vftbl-entries (retarded loading of class java/lang/String) */
2995         stringtable_update();
2996 #ifdef USE_THREADS
2997         if (stackbottom!=0)
2998                 initLocks();
2999 #endif
3000
3001
3002
3003         log_text("loader_init: creating global proto_java_lang_ClassCastException");
3004         proto_java_lang_ClassCastException =
3005                 builtin_new(class_java_lang_ClassCastException);
3006         heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3007
3008         log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3009
3010         proto_java_lang_NullPointerException =
3011                builtin_new(class_java_lang_NullPointerException);
3012         heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3013         log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3014
3015         proto_java_lang_ArrayIndexOutOfBoundsException =
3016                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3017         heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3018
3019         proto_java_lang_NegativeArraySizeException =
3020                 builtin_new(class_java_lang_NegativeArraySizeException);
3021         heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3022
3023         proto_java_lang_OutOfMemoryError =
3024                 builtin_new(class_java_lang_OutOfMemoryError);
3025         heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3026
3027         proto_java_lang_ArithmeticException =
3028                builtin_new(class_java_lang_ArithmeticException);
3029         heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3030
3031         proto_java_lang_ArrayStoreException =
3032                 builtin_new(class_java_lang_ArrayStoreException);
3033         heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3034
3035         proto_java_lang_ThreadDeath =                             /* schani */
3036                 builtin_new(class_java_lang_ThreadDeath);
3037         heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3038
3039         loader_inited = 1;
3040
3041 }
3042
3043
3044
3045
3046 /********************* Function: loader_initclasses ****************************
3047
3048         Initializes all loaded but uninitialized classes
3049
3050 *******************************************************************************/
3051
3052 void loader_initclasses ()
3053 {
3054         classinfo *c;
3055         
3056         intsDisable();                     /* schani */
3057
3058         if (makeinitializations) {
3059                 c = list_first (&linkedclasses);
3060                 while (c) {
3061                         class_init (c);
3062                         c = list_next (&linkedclasses, c);
3063                         }
3064                 }
3065
3066         intsRestore();                      /* schani */
3067 }
3068
3069 static s4 classvalue;
3070
3071 static void loader_compute_class_values (classinfo *c)
3072 {
3073         classinfo *subs;
3074
3075         c->vftbl->baseval = ++classvalue;
3076
3077         subs = c->sub;
3078         while (subs != NULL) {
3079                 loader_compute_class_values(subs);
3080                 subs = subs->nextsub;
3081                 }
3082         c->vftbl->diffval = classvalue - c->vftbl->baseval;
3083         
3084         /*
3085         {
3086         int i;
3087         for (i = 0; i < c->index; i++)
3088                 printf(" ");
3089         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
3090         utf_display(c->name);
3091         printf("\n");
3092         }
3093         */
3094         
3095 }
3096
3097
3098 void loader_compute_subclasses ()
3099 {
3100         classinfo *c;
3101         
3102         intsDisable();                     /* schani */
3103
3104         c = list_first (&linkedclasses);
3105         while (c) {
3106                 if (!(c->flags & ACC_INTERFACE)) {
3107                         c->nextsub = 0;
3108                         c->sub = 0;
3109                         }
3110                 c = list_next (&linkedclasses, c);
3111                 }
3112
3113         c = list_first (&linkedclasses);
3114         while (c) {
3115                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3116                         c->nextsub = c->super->sub;
3117                         c->super->sub = c;
3118                         }
3119                 c = list_next (&linkedclasses, c);
3120                 }
3121         classvalue = 0;
3122         loader_compute_class_values(class_java_lang_Object);
3123
3124         intsRestore();                      /* schani */
3125 }
3126
3127
3128
3129 /******************** function classloader_buffer ******************************
3130  
3131     sets buffer for reading classdata
3132
3133 *******************************************************************************/
3134
3135 void classload_buffer(u1 *buf, int len)
3136 {
3137         classbuffer        =  buf;
3138         classbuffer_size   =  len;
3139         classbuf_pos       =  buf - 1;
3140 }
3141
3142
3143 /******************** Function: loader_close ***********************************
3144
3145         Frees all resources
3146         
3147 *******************************************************************************/
3148
3149 void loader_close ()
3150 {
3151         classinfo *c;
3152
3153         while ( (c=list_first(&unloadedclasses)) ) {
3154                 list_remove (&unloadedclasses,c);
3155                 class_free (c);
3156                 }
3157         while ( (c=list_first(&unlinkedclasses)) ) {
3158                 list_remove (&unlinkedclasses,c);
3159                 class_free (c);
3160                 }
3161         while ( (c=list_first(&linkedclasses)) ) {
3162                 list_remove (&linkedclasses,c);
3163                 class_free (c);
3164                 }
3165 }
3166
3167
3168 /*
3169  * These are local overrides for various environment variables in Emacs.
3170  * Please do not remove this and leave it at the end of the file, where
3171  * Emacs will automagically detect them.
3172  * ---------------------------------------------------------------------
3173  * Local variables:
3174  * mode: c
3175  * indent-tabs-mode: t
3176  * c-basic-offset: 4
3177  * tab-width: 4
3178  * End:
3179  */