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