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