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