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