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