- include options.h/statistics.h instead of main.h
[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
29    Changes: Andreas Krall
30             Roman Obermaiser
31             Mark Probst
32             Edwin Steiner
33             Christian Thalinger
34
35    $Id: loader.c 1237 2004-06-30 19:54:59Z twisti $
36
37 */
38
39
40 #include <stdlib.h>
41 #include <string.h>
42 #include <assert.h>
43 #include <sys/stat.h>
44 #include "global.h"
45 #include "loader.h"
46 #include "options.h"
47 #include "native.h"
48 #include "tables.h"
49 #include "builtin.h"
50 #include "jit/jit.h"
51 #include "asmpart.h"
52 #include "options.h"
53 #include "statistics.h"
54 #include "toolbox/memory.h"
55 #include "toolbox/logging.h"
56 #include "threads/thread.h"
57 #include "threads/locks.h"
58 #include "nat/java_lang_Throwable.h"
59
60 #ifdef USE_ZLIB
61 #include "unzip.h"
62 #endif
63
64 #undef JOWENN_DEBUG
65 #undef JOWENN_DEBUG1
66 #undef JOWENN_DEBUG2
67
68 /* global variables ***********************************************************/
69
70 static s4 interfaceindex;       /* sequential numbering of interfaces         */
71 static s4 classvalue;
72
73
74 /* utf-symbols for pointer comparison of frequently used strings */
75
76 static utf *utf_innerclasses;           /* InnerClasses                           */
77 static utf *utf_constantvalue;          /* ConstantValue                          */
78 static utf *utf_code;                       /* Code                                   */
79 static utf *utf_exceptions;         /* Exceptions                             */
80 static utf *utf_linenumbertable;    /* LineNumberTable                        */
81 static utf *utf_sourcefile;         /* SourceFile                             */
82 static utf *utf_finalize;                   /* finalize                               */
83 static utf *utf_fidesc;                     /* ()V changed                            */
84 static utf *utf_init;                   /* <init>                                 */
85 static utf *utf_clinit;                     /* <clinit>                               */
86 static utf *utf_initsystemclass;        /* initializeSystemClass                  */
87 static utf *utf_systemclass;            /* java/lang/System                       */
88 static utf *utf_vmclassloader;      /* java/lang/VMClassLoader                */
89 static utf *utf_vmclass;            /* java/lang/VMClassLoader                */
90 static utf *utf_initialize;
91 static utf *utf_initializedesc;
92 static utf *utf_java_lang_Object;   /* java/lang/Object                       */
93
94 utf *utf_fillInStackTrace_name;
95 utf *utf_fillInStackTrace_desc;
96
97 utf* clinit_desc(){
98         return utf_fidesc;
99 }
100 utf* clinit_name(){
101         return utf_clinit;
102 }
103
104
105 /* important system classes ***************************************************/
106
107 classinfo *class_java_lang_Object;
108 classinfo *class_java_lang_String;
109 classinfo *class_java_lang_Cloneable;
110 classinfo *class_java_io_Serializable;
111
112 /* Pseudo classes for the typechecker */
113 classinfo *pseudo_class_Arraystub = NULL;
114 classinfo *pseudo_class_Null = NULL;
115 classinfo *pseudo_class_New = NULL;
116 vftbl *pseudo_class_Arraystub_vftbl = NULL;
117
118 utf *array_packagename = NULL;
119
120
121 /********************************************************************
122    list of classpath entries (either filesystem directories or 
123    ZIP/JAR archives
124 ********************************************************************/
125 static classpath_info *classpath_entries=0;
126
127
128 /******************************************************************************
129
130    structure for primitive classes: contains the class for wrapping the 
131    primitive type, the primitive class, the name of the class for wrapping, 
132    the one character type signature and the name of the primitive class
133  
134  ******************************************************************************/
135
136 /* CAUTION: Don't change the order of the types. This table is indexed
137  * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
138  */
139 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { 
140         { NULL, NULL, "java/lang/Integer",   'I', "int"     , "[I", NULL, NULL },
141         { NULL, NULL, "java/lang/Long",      'J', "long"    , "[J", NULL, NULL },
142         { NULL, NULL, "java/lang/Float",     'F', "float"   , "[F", NULL, NULL },
143         { NULL, NULL, "java/lang/Double",    'D', "double"  , "[D", NULL, NULL },
144         { NULL, NULL, "java/lang/Byte",      'B', "byte"    , "[B", NULL, NULL },
145         { NULL, NULL, "java/lang/Character", 'C', "char"    , "[C", NULL, NULL },
146         { NULL, NULL, "java/lang/Short",     'S', "short"   , "[S", NULL, NULL },
147         { NULL, NULL, "java/lang/Boolean",   'Z', "boolean" , "[Z", NULL, NULL },
148         { NULL, NULL, "java/lang/Void",      'V', "void"    , NULL, NULL, NULL }
149 };
150
151
152 /* instances of important system classes **************************************/
153
154 java_objectheader *proto_java_lang_NullPointerException;
155
156
157 /************* functions for reading classdata *********************************
158
159     getting classdata in blocks of variable size
160     (8,16,32,64-bit integer or float)
161
162 *******************************************************************************/
163
164 static char *classpath    = "";     /* searchpath for classfiles              */
165
166
167 static java_objectheader *new_classformaterror(classinfo *c, char *message, ...)
168 {
169         char cfmessage[MAXLOGTEXT];
170         va_list ap;
171
172         utf_sprint_classname(cfmessage, c->name);
173         sprintf(cfmessage + strlen(cfmessage), " (");
174
175         va_start(ap, message);
176         vsprintf(cfmessage + strlen(cfmessage), message, ap);
177         va_end(ap);
178
179         sprintf(cfmessage + strlen(cfmessage), ")");
180
181         return new_exception_message(string_java_lang_ClassFormatError, cfmessage);
182 }
183
184
185 /* check_classbuffer_size ******************************************************
186
187    assert that at least <len> bytes are left to read
188    <len> is limited to the range of non-negative s4 values
189
190 *******************************************************************************/
191
192 static inline bool check_classbuffer_size(classbuffer *cb, s4 len)
193 {
194         if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
195                 *exceptionptr =
196                         new_classformaterror((cb)->class, "Truncated class file");
197
198                 return false;
199         }
200
201         return true;
202 }
203
204
205 /* suck_nbytes *****************************************************************
206
207    transfer block of classfile data into a buffer
208
209 *******************************************************************************/
210
211 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
212 {
213         memcpy(buffer, cb->pos + 1, len);
214         cb->pos += len;
215 }
216
217
218 /* skip_nbytes ****************************************************************
219
220    skip block of classfile data
221
222 *******************************************************************************/
223
224 inline void skip_nbytes(classbuffer *cb, s4 len)
225 {
226         cb->pos += len;
227 }
228
229
230 inline u1 suck_u1(classbuffer *cb)
231 {
232         return *++(cb->pos);
233 }
234
235
236 inline u2 suck_u2(classbuffer *cb)
237 {
238         u1 a = suck_u1(cb);
239         u1 b = suck_u1(cb);
240         return ((u2) a << 8) + (u2) b;
241 }
242
243
244 inline u4 suck_u4(classbuffer *cb)
245 {
246         u1 a = suck_u1(cb);
247         u1 b = suck_u1(cb);
248         u1 c = suck_u1(cb);
249         u1 d = suck_u1(cb);
250         return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
251 }
252
253 #define suck_s8(a) (s8) suck_u8((a))
254 #define suck_s2(a) (s2) suck_u2((a))
255 #define suck_s4(a) (s4) suck_u4((a))
256 #define suck_s1(a) (s1) suck_u1((a))
257
258
259 /* get u8 from classfile data */
260 static u8 suck_u8(classbuffer *cb)
261 {
262 #if U8_AVAILABLE
263         u8 lo, hi;
264         hi = suck_u4(cb);
265         lo = suck_u4(cb);
266         return (hi << 32) + lo;
267 #else
268         u8 v;
269         v.high = suck_u4(cb);
270         v.low = suck_u4(cb);
271         return v;
272 #endif
273 }
274
275
276 /* get float from classfile data */
277 static float suck_float(classbuffer *cb)
278 {
279         float f;
280
281 #if !WORDS_BIGENDIAN 
282         u1 buffer[4];
283         u2 i;
284
285         for (i = 0; i < 4; i++)
286                 buffer[3 - i] = suck_u1(cb);
287
288         memcpy((u1*) (&f), buffer, 4);
289 #else
290         suck_nbytes((u1*) (&f), cb, 4);
291 #endif
292
293         if (sizeof(float) != 4) {
294                 *exceptionptr = new_exception_message(string_java_lang_InternalError,
295                                                                                           "Incompatible float-format");
296
297                 /* XXX should we exit in such a case? */
298                 throw_exception_exit();
299         }
300         
301         return f;
302 }
303
304
305 /* get double from classfile data */
306 static double suck_double(classbuffer *cb)
307 {
308         double d;
309
310 #if !WORDS_BIGENDIAN 
311         u1 buffer[8];
312         u2 i;   
313
314         for (i = 0; i < 8; i++)
315                 buffer[7 - i] = suck_u1(cb);
316
317         memcpy((u1*) (&d), buffer, 8);
318 #else 
319         suck_nbytes((u1*) (&d), cb, 8);
320 #endif
321
322         if (sizeof(double) != 8) {
323                 *exceptionptr = new_exception_message(string_java_lang_InternalError,
324                                                                                           "Incompatible double-format");
325
326                 /* XXX should we exit in such a case? */
327                 throw_exception_exit();
328         }
329         
330         return d;
331 }
332
333
334 /************************** function suck_init *********************************
335
336         called once at startup, sets the searchpath for the classfiles
337
338 *******************************************************************************/
339
340 void suck_init(char *cpath)
341 {
342         char *filename=0;
343         char *start;
344         char *end;
345         int isZip;
346         int filenamelen;
347         union classpath_info *tmp;
348         union classpath_info *insertAfter=0;
349
350         if (!cpath)
351                 return;
352
353         classpath = cpath;
354         
355         if (classpath_entries)
356                 panic("suck_init should be called only once");
357
358         for (start = classpath; (*start) != '\0';) {
359                 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
360
361                 if (start != end) {
362                         isZip = 0;
363                         filenamelen = end - start;
364
365                         if (filenamelen>3) {
366                                 if (strncasecmp(end - 3, "zip", 3) == 0 ||
367                                         strncasecmp(end - 3, "jar", 3) == 0) {
368                                         isZip = 1;
369                                 }
370                         }
371
372                         if (filenamelen >= (CLASSPATH_MAXFILENAME - 1))
373                                 panic("path length >= MAXFILENAME in suck_init");
374
375                         if (!filename)
376                                 filename = MNEW(char, CLASSPATH_MAXFILENAME);
377
378                         strncpy(filename, start, filenamelen);
379                         filename[filenamelen + 1] = '\0';
380                         tmp = 0;
381
382                         if (isZip) {
383 #ifdef USE_ZLIB
384                                 unzFile uf = unzOpen(filename);
385
386                                 if (uf) {
387                                         tmp = (union classpath_info *) NEW(classpath_info);
388                                         tmp->archive.type = CLASSPATH_ARCHIVE;
389                                         tmp->archive.uf = uf;
390                                         tmp->archive.next = 0;
391                                         filename = 0;
392                                 }
393 #else
394                                 panic("Zip/JAR not supported");
395 #endif
396                                 
397                         } else {
398                                 tmp = (union classpath_info *) NEW(classpath_info);
399                                 tmp->filepath.type = CLASSPATH_PATH;
400                                 tmp->filepath.next = 0;
401
402                                 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
403                                         filename[filenamelen] = '/';
404                                         filename[filenamelen + 1] = '\0';
405                                         filenamelen++;
406                                 }
407                         
408                                 tmp->filepath.filename = filename;
409                                 tmp->filepath.pathlen = filenamelen;                            
410                                 filename = 0;
411                         }
412
413                         if (tmp) {
414                                 if (insertAfter) {
415                                         insertAfter->filepath.next = tmp;
416
417                                 } else {
418                                         classpath_entries = tmp;
419                                 }
420                                 insertAfter = tmp;
421                         }
422                 }
423
424                 if ((*end) == ':')
425                         start = end + 1;
426                 else
427                         start = end;
428         
429                 if (filename) {
430                         MFREE(filename, char, CLASSPATH_MAXFILENAME);
431                         filename = NULL;
432                 }
433         }
434 }
435
436
437 void create_all_classes()
438 {
439         classpath_info *cpi;
440
441         for (cpi = classpath_entries; cpi != 0; cpi = cpi->filepath.next) {
442 #if defined(USE_ZLIB)
443                 if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
444                         cacao_entry_s *ce;
445                         unz_s *s;
446
447                         s = (unz_s *) cpi->archive.uf;
448                         ce = s->cacao_dir_list;
449                                 
450                         while (ce) {
451                                 (void) class_new(ce->name);
452                                 ce = ce->next;
453                         }
454
455                 } else {
456 #endif
457 #if defined(USE_ZLIB)
458                 }
459 #endif
460         }
461 }
462
463
464 /************************** function suck_start ********************************
465
466         returns true if classbuffer is already loaded or a file for the
467         specified class has succussfully been read in. All directories of
468         the searchpath are used to find the classfile (<classname>.class).
469         Returns false if no classfile is found and writes an error message. 
470         
471 *******************************************************************************/
472
473 classbuffer *suck_start(classinfo *c)
474 {
475         classpath_info *currPos;
476         char *utf_ptr;
477         char ch;
478         char filename[CLASSPATH_MAXFILENAME+10];  /* room for '.class'            */
479         int  filenamelen=0;
480         FILE *classfile;
481         int  err;
482         struct stat buffer;
483         classbuffer *cb;
484
485         utf_ptr = c->name->text;
486
487         while (utf_ptr < utf_end(c->name)) {
488                 if (filenamelen >= CLASSPATH_MAXFILENAME) {
489                         *exceptionptr =
490                                 new_exception_message(string_java_lang_InternalError,
491                                                                           "Filename too long");
492
493                         /* XXX should we exit in such a case? */
494                         throw_exception_exit();
495                 }
496
497                 ch = *utf_ptr++;
498                 if ((ch <= ' ' || ch > 'z') && (ch != '/'))     /* invalid character */
499                         ch = '?';
500                 filename[filenamelen++] = ch;
501         }
502
503         strcpy(filename + filenamelen, ".class");
504         filenamelen += 6;
505
506         for (currPos = classpath_entries; currPos != 0; currPos = currPos->filepath.next) {
507 #ifdef USE_ZLIB
508                 if (currPos->filepath.type == CLASSPATH_ARCHIVE) {
509                         if (cacao_locate(currPos->archive.uf, c->name) == UNZ_OK) {
510                                 unz_file_info file_info;
511                                 /*log_text("Class found in zip file");*/
512                                 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
513                                                 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
514                                         if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
515                                                 cb = NEW(classbuffer);
516                                                 cb->class = c;
517                                                 cb->size = file_info.uncompressed_size;
518                                                 cb->data = MNEW(u1, cb->size);
519                                                 cb->pos = cb->data - 1;
520                                                 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
521                                                 if (unzReadCurrentFile(currPos->archive.uf, cb->data, cb->size) == cb->size) {
522                                                         unzCloseCurrentFile(currPos->archive.uf);
523                                                         return cb;
524
525                                                 } else {
526                                                         MFREE(cb->data, u1, cb->size);
527                                                         FREE(cb, classbuffer);
528                                                         log_text("Error while unzipping");
529                                                 }
530                                         } else log_text("Error while opening file in archive");
531                                 } else log_text("Error while retrieving fileinfo");
532                         }
533                         unzCloseCurrentFile(currPos->archive.uf);
534
535                 } else {
536 #endif
537                         if ((currPos->filepath.pathlen + filenamelen) >= CLASSPATH_MAXFILENAME) continue;
538                         strcpy(currPos->filepath.filename + currPos->filepath.pathlen, filename);
539                         classfile = fopen(currPos->filepath.filename, "r");
540                         if (classfile) {                                       /* file exists */
541
542                                 /* determine size of classfile */
543
544                                 /* dolog("File: %s",filename); */
545                                 err = stat(currPos->filepath.filename, &buffer);
546
547                                 if (!err) {                            /* read classfile data */
548                                         cb = NEW(classbuffer);
549                                         cb->class = c;
550                                         cb->size = buffer.st_size;
551                                         cb->data = MNEW(u1, cb->size);
552                                         cb->pos = cb->data - 1;
553                                         fread(cb->data, 1, cb->size, classfile);
554                                         fclose(classfile);
555
556                                         return cb;
557                                 }
558                         }
559 #ifdef USE_ZLIB
560                 }
561 #endif
562         }
563
564         if (verbose) {
565                 dolog("Warning: Can not open class file '%s'", filename);
566         }
567
568         return NULL;
569 }
570
571
572 /************************** function suck_stop *********************************
573
574         frees memory for buffer with classfile data.
575         Caution: this function may only be called if buffer has been allocated
576                  by suck_start with reading a file
577         
578 *******************************************************************************/
579
580 void suck_stop(classbuffer *cb)
581 {
582         /* free memory */
583
584         MFREE(cb->data, u1, cb->size);
585         FREE(cb, classbuffer);
586 }
587
588
589 /******************************************************************************/
590 /******************* Some support functions ***********************************/
591 /******************************************************************************/
592
593 void fprintflags (FILE *fp, u2 f)
594 {
595    if ( f & ACC_PUBLIC )       fprintf (fp," PUBLIC");
596    if ( f & ACC_PRIVATE )      fprintf (fp," PRIVATE");
597    if ( f & ACC_PROTECTED )    fprintf (fp," PROTECTED");
598    if ( f & ACC_STATIC )       fprintf (fp," STATIC");
599    if ( f & ACC_FINAL )        fprintf (fp," FINAL");
600    if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
601    if ( f & ACC_VOLATILE )     fprintf (fp," VOLATILE");
602    if ( f & ACC_TRANSIENT )    fprintf (fp," TRANSIENT");
603    if ( f & ACC_NATIVE )       fprintf (fp," NATIVE");
604    if ( f & ACC_INTERFACE )    fprintf (fp," INTERFACE");
605    if ( f & ACC_ABSTRACT )     fprintf (fp," ABSTRACT");
606 }
607
608
609 /********** internal function: printflags  (only for debugging) ***************/
610
611 void printflags(u2 f)
612 {
613    if ( f & ACC_PUBLIC )       printf (" PUBLIC");
614    if ( f & ACC_PRIVATE )      printf (" PRIVATE");
615    if ( f & ACC_PROTECTED )    printf (" PROTECTED");
616    if ( f & ACC_STATIC )       printf (" STATIC");
617    if ( f & ACC_FINAL )        printf (" FINAL");
618    if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
619    if ( f & ACC_VOLATILE )     printf (" VOLATILE");
620    if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
621    if ( f & ACC_NATIVE )       printf (" NATIVE");
622    if ( f & ACC_INTERFACE )    printf (" INTERFACE");
623    if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
624 }
625
626
627 /********************** Function: skipattributebody ****************************
628
629         skips an attribute after the 16 bit reference to attribute_name has already
630         been read
631         
632 *******************************************************************************/
633
634 static bool skipattributebody(classbuffer *cb)
635 {
636         u4 len;
637
638         if (!check_classbuffer_size(cb, 4))
639                 return false;
640
641         len = suck_u4(cb);
642
643         if (!check_classbuffer_size(cb, len))
644                 return false;
645
646         skip_nbytes(cb, len);
647
648         return true;
649 }
650
651
652 /************************* Function: skipattributes ****************************
653
654         skips num attribute structures
655         
656 *******************************************************************************/
657
658 static bool skipattributes(classbuffer *cb, u4 num)
659 {
660         u4 i;
661         u4 len;
662
663         for (i = 0; i < num; i++) {
664                 if (!check_classbuffer_size(cb, 2 + 4))
665                         return false;
666
667                 suck_u2(cb);
668                 len = suck_u4(cb);
669
670                 if (!check_classbuffer_size(cb, len))
671                         return false;
672
673                 skip_nbytes(cb, len);
674         }
675
676         return true;
677 }
678
679
680 /******************** function: innerclass_getconstant ************************
681
682     like class_getconstant, but if cptags is ZERO null is returned
683         
684 *******************************************************************************/
685
686 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype) 
687 {
688         /* invalid position in constantpool */
689         if (pos >= c->cpcount)
690                 panic("Attempt to access constant outside range");
691
692         /* constantpool entry of type 0 */      
693         if (!c->cptags[pos])
694                 return NULL;
695
696         /* check type of constantpool entry */
697         if (c->cptags[pos] != ctype) {
698                 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
699                           (int) ctype, (int) c->cptags[pos] );
700         }
701                 
702         return c->cpinfos[pos];
703 }
704
705
706 /************************ function: attribute_load ****************************
707
708     read attributes from classfile
709         
710 *******************************************************************************/
711
712 static bool attribute_load(classbuffer *cb, classinfo *c, u4 num)
713 {
714         u4 i, j;
715
716         for (i = 0; i < num; i++) {
717                 utf *aname;
718
719                 /* retrieve attribute name */
720                 if (!check_classbuffer_size(cb, 2))
721                         return false;
722
723                 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
724
725                 if (aname == utf_innerclasses) {
726                         /* innerclasses attribute */
727                         if (c->innerclass != NULL)
728                                 panic("Class has more than one InnerClasses attribute");
729                                 
730                         if (!check_classbuffer_size(cb, 4 + 2))
731                                 return false;
732
733                         /* skip attribute length */                                             
734                         suck_u4(cb);
735
736                         /* number of records */
737                         c->innerclasscount = suck_u2(cb);
738
739                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
740                                 return false;
741
742                         /* allocate memory for innerclass structure */
743                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
744
745                         for (j = 0; j < c->innerclasscount; j++) {
746                                 /* The innerclass structure contains a class with an encoded
747                                    name, its defining scope, its simple name  and a bitmask of
748                                    the access flags. If an inner class is not a member, its
749                                    outer_class is NULL, if a class is anonymous, its name is
750                                    NULL. */
751                                                                 
752                                 innerclassinfo *info = c->innerclass + j;
753
754                                 info->inner_class =
755                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
756                                 info->outer_class =
757                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
758                                 info->name =
759                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
760                                 info->flags = suck_u2(cb);
761                         }
762
763                 } else if (aname == utf_sourcefile) {
764                         if (!check_classbuffer_size(cb, 4 + 2))
765                                 return false;
766
767                         suck_u4(cb);
768                         c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
769
770                 } else {
771                         /* unknown attribute */
772                         if (!skipattributebody(cb))
773                                 return false;
774                 }
775         }
776
777         return true;
778 }
779
780
781 /******************* function: checkfielddescriptor ****************************
782
783         checks whether a field-descriptor is valid and aborts otherwise
784         all referenced classes are inserted into the list of unloaded classes
785         
786 *******************************************************************************/
787
788 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
789 {
790         class_from_descriptor(utf_ptr,end_pos,NULL,
791                                                   CLASSLOAD_NEW
792                                                   | CLASSLOAD_NULLPRIMITIVE
793                                                   | CLASSLOAD_NOVOID
794                                                   | CLASSLOAD_CHECKEND);
795         
796         /* XXX use the following if -noverify */
797 #if 0
798         char *tstart;  /* pointer to start of classname */
799         char ch;
800         char *start = utf_ptr;
801
802         switch (*utf_ptr++) {
803           case 'B':
804           case 'C':
805           case 'I':
806           case 'S':
807           case 'Z':  
808           case 'J':  
809           case 'F':  
810           case 'D':
811                   /* primitive type */  
812                   break;
813                   
814           case '[':
815           case 'L':
816                   if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
817                           panic ("Ill formed descriptor");
818                   break;
819                   
820           default:   
821                   panic ("Ill formed descriptor");
822         }                       
823         
824         /* exceeding characters */              
825         if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
826 #endif
827 }
828
829
830 /******************* function checkmethoddescriptor ****************************
831
832     checks whether a method-descriptor is valid and aborts otherwise.
833     All referenced classes are inserted into the list of unloaded classes.
834
835     The number of arguments is returned. A long or double argument is counted
836     as two arguments.
837         
838 *******************************************************************************/
839
840 static int checkmethoddescriptor(classinfo *c, utf *descriptor)
841 {
842         char *utf_ptr;                      /* current position in utf text       */
843         char *end_pos;                      /* points behind utf string           */
844         s4 argcount = 0;                    /* number of arguments                */
845
846         utf_ptr = descriptor->text;
847         end_pos = utf_end(descriptor);
848
849         /* method descriptor must start with parenthesis */
850         if (utf_ptr == end_pos || *utf_ptr++ != '(')
851                 panic ("Missing '(' in method descriptor");
852
853     /* check arguments */
854     while (utf_ptr != end_pos && *utf_ptr != ')') {
855                 /* We cannot count the this argument here because
856                  * we don't know if the method is static. */
857                 if (*utf_ptr == 'J' || *utf_ptr == 'D')
858                         argcount+=2;
859                 else
860                         argcount++;
861                 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
862                                                           CLASSLOAD_NEW
863                                                           | CLASSLOAD_NULLPRIMITIVE
864                                                           | CLASSLOAD_NOVOID);
865         }
866
867         if (utf_ptr == end_pos)
868                 panic("Missing ')' in method descriptor");
869
870     utf_ptr++; /* skip ')' */
871
872         class_from_descriptor(utf_ptr,
873                                                   end_pos,
874                                                   NULL,
875                                                   CLASSLOAD_NEW |
876                                                   CLASSLOAD_NULLPRIMITIVE |
877                                                   CLASSLOAD_CHECKEND);
878
879         if (argcount > 255) {
880                 *exceptionptr =
881                         new_classformaterror(c, "Too many arguments in signature");
882
883                 return 0;
884         }
885
886         return argcount;
887
888         /* XXX use the following if -noverify */
889 #if 0
890         /* check arguments */
891         while ((c = *utf_ptr++) != ')') {
892                 start = utf_ptr-1;
893                 
894                 switch (c) {
895                 case 'B':
896                 case 'C':
897                 case 'I':
898                 case 'S':
899                 case 'Z':  
900                 case 'J':  
901                 case 'F':  
902                 case 'D':
903                         /* primitive type */  
904                         break;
905
906                 case '[':
907                 case 'L':
908                         if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
909                                 panic ("Ill formed method descriptor");
910                         break;
911                         
912                 default:   
913                         panic ("Ill formed methodtype-descriptor");
914                 }
915         }
916
917         /* check returntype */
918         if (*utf_ptr=='V') {
919                 /* returntype void */
920                 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
921         }
922         else
923                 /* treat as field-descriptor */
924                 checkfielddescriptor (utf_ptr,end_pos);
925 #endif
926 }
927
928
929 /***************** Function: print_arraydescriptor ****************************
930
931         Debugging helper for displaying an arraydescriptor
932         
933 *******************************************************************************/
934
935 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
936 {
937         if (!desc) {
938                 fprintf(file, "<NULL>");
939                 return;
940         }
941
942         fprintf(file, "{");
943         if (desc->componentvftbl) {
944                 if (desc->componentvftbl->class)
945                         utf_fprint(file, desc->componentvftbl->class->name);
946                 else
947                         fprintf(file, "<no classinfo>");
948         }
949         else
950                 fprintf(file, "0");
951                 
952         fprintf(file, ",");
953         if (desc->elementvftbl) {
954                 if (desc->elementvftbl->class)
955                         utf_fprint(file, desc->elementvftbl->class->name);
956                 else
957                         fprintf(file, "<no classinfo>");
958         }
959         else
960                 fprintf(file, "0");
961         fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
962                         desc->dataoffset, desc->componentsize);
963 }
964
965
966 /******************************************************************************/
967 /**************************  Functions for fields  ****************************/
968 /******************************************************************************/
969
970
971 /* field_load ******************************************************************
972
973    Load everything about a class field from the class file and fill a
974    'fieldinfo' structure. For static fields, space in the data segment is
975    allocated.
976
977 *******************************************************************************/
978
979 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
980
981 static bool field_load(classbuffer *cb, classinfo *c, fieldinfo *f)
982 {
983         u4 attrnum,i;
984         u4 jtype;
985         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
986
987         if (!check_classbuffer_size(cb, 2 + 2 + 2))
988                 return false;
989
990         f->flags = suck_u2(cb);
991         f->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
992         f->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
993         
994         if (opt_verify) {
995                 /* check name */
996                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
997                         panic("Field with invalid name");
998                 
999                 /* check flag consistency */
1000                 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1001
1002                 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1003                         panic("Field has invalid access flags");
1004
1005                 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
1006                         panic("Field is declared final and volatile");
1007
1008                 if ((c->flags & ACC_INTERFACE) != 0) {
1009                         if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1010                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1011                                 panic("Interface field is not declared static final public");
1012
1013                         if ((f->flags & ACC_TRANSIENT) != 0)
1014                                 panic("Interface field declared transient");
1015                 }
1016
1017                 /* check descriptor */
1018                 checkfielddescriptor(f->descriptor->text, utf_end(f->descriptor));
1019         }
1020                 
1021         f->type = jtype = desc_to_type(f->descriptor);    /* data type            */
1022         f->offset = 0;                             /* offset from start of object */
1023         f->class = c;
1024         f->xta = NULL;
1025         
1026         switch (f->type) {
1027         case TYPE_INT:     f->value.i = 0; break;
1028         case TYPE_FLOAT:   f->value.f = 0.0; break;
1029         case TYPE_DOUBLE:  f->value.d = 0.0; break;
1030         case TYPE_ADDRESS: f->value.a = NULL; break;
1031         case TYPE_LONG:
1032 #if U8_AVAILABLE
1033                 f->value.l = 0; break;
1034 #else
1035                 f->value.l.low = 0; f->value.l.high = 0; break;
1036 #endif
1037         }
1038
1039         /* read attributes */
1040         if (!check_classbuffer_size(cb, 2))
1041                 return false;
1042
1043         attrnum = suck_u2(cb);
1044         for (i = 0; i < attrnum; i++) {
1045                 utf *aname;
1046
1047                 if (!check_classbuffer_size(cb, 2))
1048                         return false;
1049
1050                 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1051                 
1052                 if (aname != utf_constantvalue) {
1053                         /* unknown attribute */
1054                         if (!skipattributebody(cb))
1055                                 return false;
1056
1057                 } else {
1058                         /* constant value attribute */
1059                         if (pindex != field_load_NOVALUE)
1060                                 panic("Field has more than one ConstantValue attribute");
1061                         
1062                         if (!check_classbuffer_size(cb, 4 + 2))
1063                                 return false;
1064
1065                         /* check attribute length */
1066                         if (suck_u4(cb) != 2)
1067                                 panic("ConstantValue attribute has invalid length");
1068                         
1069                         /* index of value in constantpool */            
1070                         pindex = suck_u2(cb);
1071                 
1072                         /* initialize field with value from constantpool */             
1073                         switch (jtype) {
1074                         case TYPE_INT: {
1075                                 constant_integer *ci = 
1076                                         class_getconstant(c, pindex, CONSTANT_Integer);
1077                                 f->value.i = ci->value;
1078                         }
1079                         break;
1080                                         
1081                         case TYPE_LONG: {
1082                                 constant_long *cl = 
1083                                         class_getconstant(c, pindex, CONSTANT_Long);
1084                                 f->value.l = cl->value;
1085                         }
1086                         break;
1087
1088                         case TYPE_FLOAT: {
1089                                 constant_float *cf = 
1090                                         class_getconstant(c, pindex, CONSTANT_Float);
1091                                 f->value.f = cf->value;
1092                         }
1093                         break;
1094                                                                                         
1095                         case TYPE_DOUBLE: {
1096                                 constant_double *cd = 
1097                                         class_getconstant(c, pindex, CONSTANT_Double);
1098                                 f->value.d = cd->value;
1099                         }
1100                         break;
1101                                                 
1102                         case TYPE_ADDRESS: { 
1103                                 utf *u = class_getconstant(c, pindex, CONSTANT_String);
1104                                 /* create javastring from compressed utf8-string */                                     
1105                                 f->value.a = literalstring_new(u);
1106                         }
1107                         break;
1108         
1109                         default: 
1110                                 log_text ("Invalid Constant - Type");
1111                         }
1112                 }
1113         }
1114
1115         /* everything was ok */
1116
1117         return true;
1118 }
1119
1120
1121 /********************** function: field_free **********************************/
1122
1123 static void field_free(fieldinfo *f)
1124 {
1125         /* empty */
1126 }
1127
1128
1129 /**************** Function: field_display (debugging only) ********************/
1130
1131 void field_display(fieldinfo *f)
1132 {
1133         printf("   ");
1134         printflags(f->flags);
1135         printf(" ");
1136         utf_display(f->name);
1137         printf(" ");
1138         utf_display(f->descriptor);     
1139         printf(" offset: %ld\n", (long int) (f->offset));
1140 }
1141
1142
1143 /******************************************************************************/
1144 /************************* Functions for methods ******************************/
1145 /******************************************************************************/
1146
1147
1148 /* method_load *****************************************************************
1149
1150    Loads a method from the class file and fills an existing 'methodinfo'
1151    structure. For native methods, the function pointer field is set to the
1152    real function pointer, for JavaVM methods a pointer to the compiler is used
1153    preliminarily.
1154         
1155 *******************************************************************************/
1156
1157 static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m)
1158 {
1159         s4 argcount;
1160         s4 i, j;
1161         u4 attrnum;
1162         u4 codeattrnum;
1163
1164 #ifdef STATISTICS
1165         if (opt_stat)
1166                 count_all_methods++;
1167 #endif
1168
1169         m->thrownexceptionscount = 0;
1170         m->linenumbercount = 0;
1171         m->linenumbers = 0;
1172         m->class = c;
1173         m->nativelyoverloaded = false;
1174         
1175         if (!check_classbuffer_size(cb, 2 + 2 + 2))
1176                 return false;
1177
1178         m->flags = suck_u2(cb);
1179         m->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1180         m->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1181
1182         if (opt_verify) {
1183                 if (!is_valid_name_utf(m->name))
1184                         panic("Method with invalid name");
1185
1186                 if (m->name->text[0] == '<'
1187                         && m->name != utf_init && m->name != utf_clinit)
1188                         panic("Method with invalid special name");
1189         }
1190         
1191         argcount = checkmethoddescriptor(c, m->descriptor);
1192
1193         if (!(m->flags & ACC_STATIC))
1194                 argcount++; /* count the 'this' argument */
1195
1196         if (opt_verify) {
1197                 if (argcount > 255)
1198                         panic("Too many arguments in signature");
1199
1200                 /* check flag consistency */
1201                 if (m->name != utf_clinit) {
1202                         i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1203
1204                         if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1205                                 panic("Method has invalid access flags");
1206
1207                         if ((m->flags & ACC_ABSTRACT) != 0) {
1208                                 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1209                                                                  ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1210                                         *exceptionptr =
1211                                                 new_classformaterror(c,
1212                                                                                          "Illegal method modifiers: 0x%x",
1213                                                                                          m->flags);
1214
1215                                         return false;
1216                                 }
1217                         }
1218
1219                         if ((c->flags & ACC_INTERFACE) != 0) {
1220                                 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1221                                         != (ACC_ABSTRACT | ACC_PUBLIC))
1222                                         panic("Interface method is not declared abstract and public");
1223                         }
1224
1225                         if (m->name == utf_init) {
1226                                 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1227                                                                  | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1228                                         panic("Instance initialization method has invalid flags set");
1229                         }
1230                 }
1231         }
1232                 
1233         m->jcode = NULL;
1234         m->basicblockcount = 0;
1235         m->basicblocks = NULL;
1236         m->basicblockindex = NULL;
1237         m->instructioncount = 0;
1238         m->instructions = NULL;
1239         m->stackcount = 0;
1240         m->stack = NULL;
1241         m->exceptiontable = NULL;
1242         m->registerdata = NULL;
1243         m->stubroutine = NULL;
1244         m->mcode = NULL;
1245         m->entrypoint = NULL;
1246         m->methodUsed = NOTUSED;    
1247         m->monoPoly = MONO;    
1248         m->subRedefs = 0;
1249         m->subRedefsUsed = 0;
1250
1251         m->xta = NULL;
1252         
1253         if (!(m->flags & ACC_NATIVE)) {
1254                 m->stubroutine = createcompilerstub(m);
1255
1256         } else {
1257                 functionptr f = native_findfunction(c->name, m->name, m->descriptor, 
1258                                                                                         (m->flags & ACC_STATIC) != 0);
1259                 if (f) {
1260                         m->stubroutine = createnativestub(f, m);
1261                 }
1262         }
1263         
1264         if (!check_classbuffer_size(cb, 2))
1265                 return false;
1266         
1267         attrnum = suck_u2(cb);
1268         for (i = 0; i < attrnum; i++) {
1269                 utf *aname;
1270
1271                 if (!check_classbuffer_size(cb, 2))
1272                         return false;
1273
1274                 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1275
1276                 if (aname != utf_code) {
1277                         if (aname == utf_exceptions) {
1278                                 s4 j;
1279                                 
1280                                 if (!check_classbuffer_size(cb, 4 + 2))
1281                                         return false;
1282
1283                                 suck_u4(cb); /*length*/
1284                                 m->thrownexceptionscount = suck_u2(cb);
1285
1286                                 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1287                                         return false;
1288
1289                                 m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
1290
1291                                 for (j = 0; j < m->thrownexceptionscount; j++) {
1292                                         (m->thrownexceptions)[j] =
1293                                                 class_getconstant(c, suck_u2(cb), CONSTANT_Class);
1294                                 }
1295                                 
1296                         } else {
1297                                 if (!skipattributebody(cb))
1298                                         return false;
1299                         }
1300
1301                 } else {
1302                         if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1303                                         *exceptionptr =
1304                                                 new_classformaterror(c,
1305                                                                                          "Code attribute in native or abstract methods");
1306
1307                                         return false;
1308                         }
1309                         
1310                         if (m->jcode) {
1311                                 *exceptionptr =
1312                                         new_classformaterror(c, "Multiple Code attributes");
1313
1314                                 return false;
1315                         }
1316
1317                         if (!check_classbuffer_size(cb, 4 + 2 + 2))
1318                                 return false;
1319
1320                         suck_u4(cb);
1321                         m->maxstack = suck_u2(cb);
1322                         m->maxlocals = suck_u2(cb);
1323
1324                         if (m->maxlocals < argcount) {
1325                                 *exceptionptr =
1326                                         new_classformaterror(c, "Arguments can't fit into locals");
1327
1328                                 return false;
1329                         }
1330                         
1331                         if (!check_classbuffer_size(cb, 4))
1332                                 return false;
1333
1334                         m->jcodelength = suck_u4(cb);
1335
1336                         if (m->jcodelength == 0)
1337                                 panic("bytecode has zero length");
1338
1339                         if (m->jcodelength > 65535) {
1340                                 *exceptionptr =
1341                                         new_classformaterror(c,
1342                                                                                  "Code of a method longer than 65535 bytes");
1343
1344                                 return false;
1345                         }
1346
1347                         if (!check_classbuffer_size(cb, m->jcodelength))
1348                                 return false;
1349
1350                         m->jcode = MNEW(u1, m->jcodelength);
1351                         suck_nbytes(m->jcode, cb, m->jcodelength);
1352
1353                         if (!check_classbuffer_size(cb, 2))
1354                                 return false;
1355
1356                         m->exceptiontablelength = suck_u2(cb);
1357
1358                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1359                                 return false;
1360
1361                         m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1362
1363 #if defined(STATISTICS)
1364                         if (opt_stat) {
1365                                 count_vmcode_len += m->jcodelength + 18;
1366                                 count_extable_len += 8 * m->exceptiontablelength;
1367                         }
1368 #endif
1369
1370                         for (j = 0; j < m->exceptiontablelength; j++) {
1371                                 u4 idx;
1372                                 m->exceptiontable[j].startpc = suck_u2(cb);
1373                                 m->exceptiontable[j].endpc = suck_u2(cb);
1374                                 m->exceptiontable[j].handlerpc = suck_u2(cb);
1375
1376                                 idx = suck_u2(cb);
1377                                 if (!idx) {
1378                                         m->exceptiontable[j].catchtype = NULL;
1379
1380                                 } else {
1381                                         m->exceptiontable[j].catchtype =
1382                                                 class_getconstant(c, idx, CONSTANT_Class);
1383                                 }
1384                         }
1385
1386                         if (!check_classbuffer_size(cb, 2))
1387                                 return false;
1388
1389                         codeattrnum = suck_u2(cb);
1390
1391                         for (; codeattrnum > 0; codeattrnum--) {
1392                                 utf *caname;
1393
1394                                 if (!check_classbuffer_size(cb, 2))
1395                                         return false;
1396
1397                                 caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1398
1399                                 if (caname == utf_linenumbertable) {
1400                                         u2 lncid;
1401
1402                                         if (!check_classbuffer_size(cb, 4 + 2))
1403                                                 return false;
1404
1405                                         suck_u4(cb);
1406                                         m->linenumbercount = suck_u2(cb);
1407
1408                                         if (!check_classbuffer_size(cb,
1409                                                                                                 (2 + 2) * m->linenumbercount))
1410                                                 return false;
1411
1412                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1413                                         
1414                                         for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1415                                                 m->linenumbers[lncid].start_pc = suck_u2(cb);
1416                                                 m->linenumbers[lncid].line_number = suck_u2(cb);
1417                                         }
1418                                         codeattrnum--;
1419
1420                                         if (!skipattributes(cb, codeattrnum))
1421                                                 return false;
1422                                         
1423                                         break;
1424                                 } else {
1425                                         if (!skipattributebody(cb))
1426                                                 return false;
1427                                 }
1428                         }
1429                 }
1430         }
1431
1432         if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1433                 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1434
1435                 return false;
1436         }
1437
1438         /* everything was ok */
1439
1440         return true;
1441 }
1442
1443
1444 /********************* Function: method_free ***********************************
1445
1446         frees all memory that was allocated for this method
1447
1448 *******************************************************************************/
1449
1450 static void method_free(methodinfo *m)
1451 {
1452         if (m->jcode)
1453                 MFREE(m->jcode, u1, m->jcodelength);
1454
1455         if (m->exceptiontable)
1456                 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1457
1458         if (m->mcode)
1459                 CFREE(m->mcode, m->mcodelength);
1460
1461         if (m->stubroutine) {
1462                 if (m->flags & ACC_NATIVE) {
1463                         removenativestub(m->stubroutine);
1464
1465                 } else {
1466                         removecompilerstub(m->stubroutine);
1467                 }
1468         }
1469 }
1470
1471
1472 /************** Function: method_display  (debugging only) **************/
1473
1474 void method_display(methodinfo *m)
1475 {
1476         printf("   ");
1477         printflags(m->flags);
1478         printf(" ");
1479         utf_display(m->name);
1480         printf(" "); 
1481         utf_display(m->descriptor);
1482         printf("\n");
1483 }
1484
1485 /************** Function: method_display_flags_last  (debugging only) **************/
1486
1487 void method_display_flags_last(methodinfo *m)
1488 {
1489         printf(" ");
1490         utf_display(m->name);
1491         printf(" ");
1492         utf_display(m->descriptor);
1493         printf("   ");
1494         printflags(m->flags);
1495         printf("\n");
1496 }
1497
1498
1499 /******************** Function: method_canoverwrite ****************************
1500
1501         Check if m and old are identical with respect to type and name. This means
1502         that old can be overwritten with m.
1503         
1504 *******************************************************************************/
1505
1506 static bool method_canoverwrite(methodinfo *m, methodinfo *old)
1507 {
1508         if (m->name != old->name) return false;
1509         if (m->descriptor != old->descriptor) return false;
1510         if (m->flags & ACC_STATIC) return false;
1511         return true;
1512 }
1513
1514
1515 /******************************************************************************/
1516 /************************ Functions for class *********************************/
1517 /******************************************************************************/
1518
1519
1520 /******************** function:: class_getconstant *****************************
1521
1522         retrieves the value at position 'pos' of the constantpool of a class
1523         if the type of the value is other than 'ctype' the system is stopped
1524
1525 *******************************************************************************/
1526
1527 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1528 {
1529         /* invalid position in constantpool */
1530         /* (pos == 0 is caught by type comparison) */
1531         if (pos >= c->cpcount)
1532                 panic("Attempt to access constant outside range");
1533
1534         /* check type of constantpool entry */
1535
1536         if (c->cptags[pos] != ctype) {
1537                 class_showconstantpool(c);
1538                 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1539                           (int) ctype, (int) c->cptags[pos]);
1540         }
1541                 
1542         return c->cpinfos[pos];
1543 }
1544
1545
1546 /********************* Function: class_constanttype ****************************
1547
1548         Determines the type of a class entry in the ConstantPool
1549         
1550 *******************************************************************************/
1551
1552 u4 class_constanttype(classinfo *c, u4 pos)
1553 {
1554         if (pos >= c->cpcount)
1555                 panic("Attempt to access constant outside range");
1556
1557         return c->cptags[pos];
1558 }
1559
1560
1561 /******************** function: class_loadcpool ********************************
1562
1563         loads the constantpool of a class, 
1564         the entries are transformed into a simpler format 
1565         by resolving references
1566         (a detailed overview of the compact structures can be found in global.h)        
1567
1568 *******************************************************************************/
1569
1570 static bool class_loadcpool(classbuffer *cb, classinfo *c)
1571 {
1572
1573         /* The following structures are used to save information which cannot be 
1574            processed during the first pass. After the complete constantpool has 
1575            been traversed the references can be resolved. 
1576            (only in specific order)                                                */
1577         
1578         /* CONSTANT_Class_info entries */
1579         typedef struct forward_class {      
1580                 struct forward_class *next; 
1581                 u2 thisindex;               
1582                 u2 name_index;              
1583         } forward_class;                    
1584                                         
1585         /* CONSTANT_String */                                      
1586         typedef struct forward_string { 
1587                 struct forward_string *next; 
1588                 u2 thisindex;                
1589                 u2 string_index;
1590         } forward_string;
1591
1592         /* CONSTANT_NameAndType */
1593         typedef struct forward_nameandtype {
1594                 struct forward_nameandtype *next;
1595                 u2 thisindex;
1596                 u2 name_index;
1597                 u2 sig_index;
1598         } forward_nameandtype;
1599
1600         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1601         typedef struct forward_fieldmethint {   
1602                 struct forward_fieldmethint *next;
1603                 u2 thisindex;
1604                 u1 tag;
1605                 u2 class_index;
1606                 u2 nameandtype_index;
1607         } forward_fieldmethint;
1608
1609
1610         u4 idx;
1611         long int dumpsize = dump_size ();
1612
1613         forward_class *forward_classes = NULL;
1614         forward_string *forward_strings = NULL;
1615         forward_nameandtype *forward_nameandtypes = NULL;
1616         forward_fieldmethint *forward_fieldmethints = NULL;
1617
1618         u4 cpcount;
1619         u1 *cptags;
1620         voidptr *cpinfos;
1621
1622         /* number of entries in the constant_pool table plus one */
1623         if (!check_classbuffer_size(cb, 2))
1624                 return false;
1625
1626         cpcount = c->cpcount = suck_u2(cb);
1627
1628         /* allocate memory */
1629         cptags  = c->cptags  = MNEW(u1, cpcount);
1630         cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1631
1632         if (!cpcount)
1633                 panic("Invalid constant_pool_count (0)");
1634         
1635 #if defined(STATISTICS)
1636         if (opt_stat)
1637                 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1638 #endif
1639         
1640         /* initialize constantpool */
1641         for (idx = 0; idx < cpcount; idx++) {
1642                 cptags[idx] = CONSTANT_UNUSED;
1643                 cpinfos[idx] = NULL;
1644         }
1645
1646                         
1647         /******* first pass *******/
1648         /* entries which cannot be resolved now are written into 
1649            temporary structures and traversed again later        */
1650                    
1651         idx = 1;
1652         while (idx < cpcount) {
1653                 u4 t;
1654
1655                 /* get constant type */
1656                 if (!check_classbuffer_size(cb, 1))
1657                         return false;
1658
1659                 t = suck_u1(cb);
1660
1661                 switch (t) {
1662                 case CONSTANT_Class: { 
1663                         forward_class *nfc = DNEW(forward_class);
1664
1665                         nfc->next = forward_classes;
1666                         forward_classes = nfc;
1667
1668                         nfc->thisindex = idx;
1669                         /* reference to CONSTANT_NameAndType */
1670                         if (!check_classbuffer_size(cb, 2))
1671                                 return false;
1672
1673                         nfc->name_index = suck_u2(cb);
1674
1675                         idx++;
1676                         break;
1677                 }
1678                         
1679                 case CONSTANT_Fieldref:
1680                 case CONSTANT_Methodref:
1681                 case CONSTANT_InterfaceMethodref: { 
1682                         forward_fieldmethint *nff = DNEW(forward_fieldmethint);
1683                                 
1684                         nff->next = forward_fieldmethints;
1685                         forward_fieldmethints = nff;
1686
1687                         nff->thisindex = idx;
1688                         /* constant type */
1689                         nff->tag = t;
1690
1691                         if (!check_classbuffer_size(cb, 2 + 2))
1692                                 return false;
1693
1694                         /* class or interface type that contains the declaration of the
1695                            field or method */
1696                         nff->class_index = suck_u2(cb);
1697
1698                         /* name and descriptor of the field or method */
1699                         nff->nameandtype_index = suck_u2(cb);
1700
1701                         idx++;
1702                         break;
1703                 }
1704                                 
1705                 case CONSTANT_String: {
1706                         forward_string *nfs = DNEW(forward_string);
1707                                 
1708                         nfs->next = forward_strings;
1709                         forward_strings = nfs;
1710                                 
1711                         nfs->thisindex = idx;
1712
1713                         /* reference to CONSTANT_Utf8_info with string characters */
1714                         if (!check_classbuffer_size(cb, 2))
1715                                 return false;
1716
1717                         nfs->string_index = suck_u2(cb);
1718                                 
1719                         idx++;
1720                         break;
1721                 }
1722
1723                 case CONSTANT_NameAndType: {
1724                         forward_nameandtype *nfn = DNEW(forward_nameandtype);
1725                                 
1726                         nfn->next = forward_nameandtypes;
1727                         forward_nameandtypes = nfn;
1728                                 
1729                         nfn->thisindex = idx;
1730
1731                         if (!check_classbuffer_size(cb, 2 + 2))
1732                                 return false;
1733
1734                         /* reference to CONSTANT_Utf8_info containing simple name */
1735                         nfn->name_index = suck_u2(cb);
1736
1737                         /* reference to CONSTANT_Utf8_info containing field or method
1738                            descriptor */
1739                         nfn->sig_index = suck_u2(cb);
1740                                 
1741                         idx++;
1742                         break;
1743                 }
1744
1745                 case CONSTANT_Integer: {
1746                         constant_integer *ci = NEW(constant_integer);
1747
1748 #if defined(STATISTICS)
1749                         if (opt_stat)
1750                                 count_const_pool_len += sizeof(constant_integer);
1751 #endif
1752
1753                         if (!check_classbuffer_size(cb, 4))
1754                                 return false;
1755
1756                         ci->value = suck_s4(cb);
1757                         cptags[idx] = CONSTANT_Integer;
1758                         cpinfos[idx] = ci;
1759
1760                         idx++;
1761                         break;
1762                 }
1763                                 
1764                 case CONSTANT_Float: {
1765                         constant_float *cf = NEW(constant_float);
1766
1767 #if defined(STATISTICS)
1768                         if (opt_stat)
1769                                 count_const_pool_len += sizeof(constant_float);
1770 #endif
1771
1772                         if (!check_classbuffer_size(cb, 4))
1773                                 return false;
1774
1775                         cf->value = suck_float(cb);
1776                         cptags[idx] = CONSTANT_Float;
1777                         cpinfos[idx] = cf;
1778
1779                         idx++;
1780                         break;
1781                 }
1782                                 
1783                 case CONSTANT_Long: {
1784                         constant_long *cl = NEW(constant_long);
1785                                         
1786 #if defined(STATISTICS)
1787                         if (opt_stat)
1788                                 count_const_pool_len += sizeof(constant_long);
1789 #endif
1790
1791                         if (!check_classbuffer_size(cb, 8))
1792                                 return false;
1793
1794                         cl->value = suck_s8(cb);
1795                         cptags[idx] = CONSTANT_Long;
1796                         cpinfos[idx] = cl;
1797                         idx += 2;
1798                         if (idx > cpcount)
1799                                 panic("Long constant exceeds constant pool");
1800                         break;
1801                 }
1802                         
1803                 case CONSTANT_Double: {
1804                         constant_double *cd = NEW(constant_double);
1805                                 
1806 #if defined(STATISTICS)
1807                         if (opt_stat)
1808                                 count_const_pool_len += sizeof(constant_double);
1809 #endif
1810
1811                         if (!check_classbuffer_size(cb, 8))
1812                                 return false;
1813
1814                         cd->value = suck_double(cb);
1815                         cptags[idx] = CONSTANT_Double;
1816                         cpinfos[idx] = cd;
1817                         idx += 2;
1818                         if (idx > cpcount)
1819                                 panic("Double constant exceeds constant pool");
1820                         break;
1821                 }
1822                                 
1823                 case CONSTANT_Utf8: { 
1824                         u4 length;
1825
1826                         /* number of bytes in the bytes array (not string-length) */
1827                         if (!check_classbuffer_size(cb, 2))
1828                                 return false;
1829
1830                         length = suck_u2(cb);
1831                         cptags[idx] = CONSTANT_Utf8;
1832
1833                         /* validate the string */
1834                         if (!check_classbuffer_size(cb, length))
1835                                 return false;
1836
1837                         if (opt_verify &&
1838                                 !is_valid_utf(cb->pos + 1, cb->pos + 1 + length)) {
1839                                 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1840                                 panic("Invalid UTF-8 string");
1841                         }
1842                         /* insert utf-string into the utf-symboltable */
1843                         cpinfos[idx] = utf_new_intern(cb->pos + 1, length);
1844
1845                         /* skip bytes of the string (buffer size check above) */
1846                         skip_nbytes(cb, length);
1847                         idx++;
1848                         break;
1849                 }
1850                                                                                 
1851                 default:
1852                         error("Unkown constant type: %d",(int) t);
1853                 }  /* end switch */
1854         } /* end while */
1855
1856
1857         /* resolve entries in temporary structures */
1858
1859         while (forward_classes) {
1860                 utf *name =
1861                         class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1862
1863                 if (opt_verify && !is_valid_name_utf(name))
1864                         panic("Class reference with invalid name");
1865
1866                 cptags[forward_classes->thisindex] = CONSTANT_Class;
1867                 /* retrieve class from class-table */
1868                 if (opt_eager) {
1869                         classinfo *tc;
1870                         tc = class_new_intern(name);
1871
1872                         if (!class_load(tc))
1873                                 return false;
1874
1875                         /* link the class later, so we cannot link the currently loaded
1876                            class */
1877                         list_addfirst(&unlinkedclasses, tc);
1878
1879                         cpinfos[forward_classes->thisindex] = tc;
1880
1881                 } else {
1882                         cpinfos[forward_classes->thisindex] = class_new(name);
1883                 }
1884
1885                 forward_classes = forward_classes->next;
1886         }
1887
1888         while (forward_strings) {
1889                 utf *text =
1890                         class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1891
1892                 /* resolve utf-string */                
1893                 cptags[forward_strings->thisindex] = CONSTANT_String;
1894                 cpinfos[forward_strings->thisindex] = text;
1895                 
1896                 forward_strings = forward_strings->next;
1897         }
1898
1899         while (forward_nameandtypes) {
1900                 constant_nameandtype *cn = NEW(constant_nameandtype);   
1901
1902 #if defined(STATISTICS)
1903                 if (opt_stat)
1904                         count_const_pool_len += sizeof(constant_nameandtype);
1905 #endif
1906
1907                 /* resolve simple name and descriptor */
1908                 cn->name = class_getconstant(c,
1909                                                                          forward_nameandtypes->name_index,
1910                                                                          CONSTANT_Utf8);
1911
1912                 cn->descriptor = class_getconstant(c,
1913                                                                                    forward_nameandtypes->sig_index,
1914                                                                                    CONSTANT_Utf8);
1915
1916                 if (opt_verify) {
1917                         /* check name */
1918                         if (!is_valid_name_utf(cn->name))
1919                                 panic("NameAndType with invalid name");
1920                         /* disallow referencing <clinit> among others */
1921                         if (cn->name->text[0] == '<' && cn->name != utf_init)
1922                                 panic("NameAndType with invalid special name");
1923                 }
1924
1925                 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1926                 cpinfos[forward_nameandtypes->thisindex] = cn;
1927                 
1928                 forward_nameandtypes = forward_nameandtypes->next;
1929         }
1930
1931         while (forward_fieldmethints) {
1932                 constant_nameandtype *nat;
1933                 constant_FMIref *fmi = NEW(constant_FMIref);
1934
1935 #if defined(STATISTICS)
1936                 if (opt_stat)
1937                         count_const_pool_len += sizeof(constant_FMIref);
1938 #endif
1939                 /* resolve simple name and descriptor */
1940                 nat = class_getconstant(c,
1941                                                                 forward_fieldmethints->nameandtype_index,
1942                                                                 CONSTANT_NameAndType);
1943
1944                 fmi->class = class_getconstant(c,
1945                                                                            forward_fieldmethints->class_index,
1946                                                                            CONSTANT_Class);
1947                 fmi->name = nat->name;
1948                 fmi->descriptor = nat->descriptor;
1949
1950                 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1951                 cpinfos[forward_fieldmethints->thisindex] = fmi;
1952         
1953                 switch (forward_fieldmethints->tag) {
1954                 case CONSTANT_Fieldref:  /* check validity of descriptor */
1955                         checkfielddescriptor(fmi->descriptor->text,
1956                                                                  utf_end(fmi->descriptor));
1957                         break;
1958                 case CONSTANT_InterfaceMethodref:
1959                 case CONSTANT_Methodref: /* check validity of descriptor */
1960                         checkmethoddescriptor(c, fmi->descriptor);
1961                         break;
1962                 }
1963         
1964                 forward_fieldmethints = forward_fieldmethints->next;
1965         }
1966
1967         dump_release(dumpsize);
1968
1969         /* everything was ok */
1970
1971         return true;
1972 }
1973
1974
1975 /********************** Function: class_load ***********************************
1976         
1977         Loads everything interesting about a class from the class file. The
1978         'classinfo' structure must have been allocated previously.
1979
1980         The super class and the interfaces implemented by this class need not be
1981         loaded. The link is set later by the function 'class_link'.
1982
1983         The loaded class is removed from the list 'unloadedclasses' and added to
1984         the list 'unlinkedclasses'.
1985         
1986 *******************************************************************************/
1987
1988 classinfo *class_load_intern(classbuffer *cb);
1989
1990 classinfo *class_load(classinfo *c)
1991 {
1992         classbuffer *cb;
1993         classinfo *r;
1994         s8 starttime;
1995         s8 stoptime;
1996
1997 #if defined(USE_THREADS)
1998 #if defined(NATIVE_THREADS)
1999         compiler_lock();
2000         tables_lock();
2001 #else
2002         intsDisable();
2003 #endif
2004 #endif
2005
2006         /* maybe the class is already loaded */
2007         if (c->loaded) {
2008 #if defined(USE_THREADS)
2009 #if defined(NATIVE_THREADS)
2010                 tables_unlock();
2011                 compiler_unlock();
2012 #else
2013                 intsRestore();
2014 #endif
2015 #endif
2016
2017                 return c;
2018         }
2019
2020         /* measure time */
2021         if (getloadingtime)
2022                 starttime = getcputime();
2023
2024         /* load classdata, throw exception on error */
2025
2026         if ((cb = suck_start(c)) == NULL) {
2027                 /* this means, the classpath was not set properly */
2028                 if (c->name == utf_java_lang_Object)
2029                         throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2030                                                                            "java/lang/Object");
2031
2032                 *exceptionptr =
2033                         new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2034                                                                          c->name);
2035
2036 #if defined(USE_THREADS)
2037 #if defined(NATIVE_THREADS)
2038                 tables_unlock();
2039                 compiler_unlock();
2040 #else
2041                 intsRestore();
2042 #endif
2043 #endif
2044
2045                 return NULL;
2046         }
2047         
2048         /* call the internal function */
2049         r = class_load_intern(cb);
2050
2051         /* if return value is NULL, we had a problem and the class is not loaded */
2052         if (!r) {
2053                 c->loaded = false;
2054
2055                 /* now free the allocated memory, otherwise we could ran into a DOS */
2056                 class_remove(c);
2057         }
2058
2059         /* free memory */
2060         suck_stop(cb);
2061
2062         /* measure time */
2063         if (getloadingtime) {
2064                 stoptime = getcputime();
2065                 loadingtime += (stoptime - starttime);
2066         }
2067
2068 #if defined(USE_THREADS)
2069 #if defined(NATIVE_THREADS)
2070         tables_unlock();
2071         compiler_unlock();
2072 #else
2073         intsRestore();
2074 #endif
2075 #endif
2076
2077         return r;
2078 }
2079
2080
2081 classinfo *class_load_intern(classbuffer *cb)
2082 {
2083         classinfo *c;
2084         u4 i;
2085         u4 mi, ma;
2086 /*      s4 classdata_left; */
2087         char msg[MAXLOGTEXT];               /* maybe we get an exception */
2088
2089         /* get the classbuffer's class */
2090         c = cb->class;
2091
2092         /* maybe the class is already loaded */
2093         if (c->loaded)
2094                 return c;
2095
2096 #if defined(STATISTICS)
2097         if (opt_stat)
2098                 count_class_loads++;
2099 #endif
2100
2101         /* output for debugging purposes */
2102         if (loadverbose)
2103                 log_message_class("Loading class: ", c);
2104         
2105         /* class is somewhat loaded */
2106         c->loaded = true;
2107
2108         if (!check_classbuffer_size(cb, 4 + 2 + 2))
2109                 return NULL;
2110
2111         /* check signature */
2112         if (suck_u4(cb) != MAGIC) {
2113                 *exceptionptr = new_classformaterror(c, "Bad magic number");
2114
2115                 return NULL;
2116         }
2117
2118         /* check version */
2119         mi = suck_u2(cb);
2120         ma = suck_u2(cb);
2121
2122         if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2123                 *exceptionptr =
2124                         new_classformaterror(c,
2125                                                                  "Unsupported major.minor version %d.%d",
2126                                                                  ma, mi);
2127
2128                 return NULL;
2129         }
2130
2131         if (!class_loadcpool(cb, c))
2132                 return NULL;
2133
2134         /*JOWENN*/
2135         c->erroneous_state = 0;
2136         c->initializing_thread = 0;     
2137         /*JOWENN*/
2138         c->classUsed = NOTUSED; /* not used initially CO-RT */
2139         c->impldBy = NULL;
2140
2141         /* ACC flags */
2142         if (!check_classbuffer_size(cb, 2))
2143                 return NULL;
2144
2145         c->flags = suck_u2(cb);
2146         /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
2147
2148         /* check ACC flags consistency */
2149         if (c->flags & ACC_INTERFACE) {
2150                 if (!(c->flags & ACC_ABSTRACT)) {
2151                         /* We work around this because interfaces in JDK 1.1 are
2152                          * not declared abstract. */
2153
2154                         c->flags |= ACC_ABSTRACT;
2155                         /* panic("Interface class not declared abstract"); */
2156                 }
2157
2158                 if (c->flags & ACC_FINAL) {
2159                         *exceptionptr =
2160                                 new_classformaterror(c,
2161                                                                          "Illegal class modifiers: 0x%x", c->flags);
2162
2163                         return NULL;
2164                 }
2165
2166                 if (c->flags & ACC_SUPER) {
2167                         c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2168                 }
2169         }
2170
2171         if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2172                 *exceptionptr =
2173                         new_classformaterror(c, "Illegal class modifiers: 0x%x", c->flags);
2174
2175                 return NULL;
2176         }
2177
2178         if (!check_classbuffer_size(cb, 2 + 2))
2179                 return NULL;
2180
2181         /* this class */
2182         i = suck_u2(cb);
2183         if (class_getconstant(c, i, CONSTANT_Class) != c) {
2184                 utf_sprint(msg, c->name);
2185                 sprintf(msg + strlen(msg), " (wrong name: ");
2186                 utf_sprint(msg + strlen(msg),
2187                                    ((classinfo *) class_getconstant(c, i, CONSTANT_Class))->name);
2188                 sprintf(msg + strlen(msg), ")");
2189
2190                 *exceptionptr =
2191                         new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2192
2193                 return NULL;
2194         }
2195         
2196         /* retrieve superclass */
2197         if ((i = suck_u2(cb))) {
2198                 c->super = class_getconstant(c, i, CONSTANT_Class);
2199
2200                 /* java.lang.Object may not have a super class. */
2201                 if (c->name == utf_java_lang_Object) {
2202                         *exceptionptr =
2203                                 new_exception_message(string_java_lang_ClassFormatError,
2204                                                                           "java.lang.Object with superclass");
2205
2206                         return NULL;
2207                 }
2208
2209                 /* Interfaces must have java.lang.Object as super class. */
2210                 if ((c->flags & ACC_INTERFACE) &&
2211                         c->super->name != utf_java_lang_Object) {
2212                         *exceptionptr =
2213                                 new_exception_message(string_java_lang_ClassFormatError,
2214                                                                           "Interfaces must have java.lang.Object as superclass");
2215
2216                         return NULL;
2217                 }
2218
2219         } else {
2220                 c->super = NULL;
2221
2222                 /* This is only allowed for java.lang.Object. */
2223                 if (c->name != utf_java_lang_Object) {
2224                         *exceptionptr = new_classformaterror(c, "Bad superclass index");
2225
2226                         return NULL;
2227                 }
2228                         
2229         }
2230                          
2231         /* retrieve interfaces */
2232         if (!check_classbuffer_size(cb, 2))
2233                 return NULL;
2234
2235         c->interfacescount = suck_u2(cb);
2236
2237         if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2238                 return NULL;
2239
2240         c->interfaces = MNEW(classinfo*, c->interfacescount);
2241         for (i = 0; i < c->interfacescount; i++) {
2242                 c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class);
2243         }
2244
2245         /* load fields */
2246         if (!check_classbuffer_size(cb, 2))
2247                 return NULL;
2248
2249         c->fieldscount = suck_u2(cb);
2250         c->fields = GCNEW(fieldinfo, c->fieldscount);
2251 /*      c->fields = MNEW(fieldinfo, c->fieldscount); */
2252         for (i = 0; i < c->fieldscount; i++) {
2253                 if (!field_load(cb, c, &(c->fields[i])))
2254                         return NULL;
2255         }
2256
2257         /* load methods */
2258         if (!check_classbuffer_size(cb, 2))
2259                 return NULL;
2260
2261         c->methodscount = suck_u2(cb);
2262         c->methods = GCNEW(methodinfo, c->methodscount);
2263 /*      c->methods = MNEW(methodinfo, c->methodscount); */
2264         for (i = 0; i < c->methodscount; i++) {
2265                 if (!method_load(cb, c, &(c->methods[i])))
2266                         return NULL;
2267         }
2268
2269         /* Check if all fields and methods can be uniquely
2270          * identified by (name,descriptor). */
2271         if (opt_verify) {
2272                 /* We use a hash table here to avoid making the
2273                  * average case quadratic in # of methods, fields.
2274                  */
2275                 static int shift = 0;
2276                 u2 *hashtab;
2277                 u2 *next; /* for chaining colliding hash entries */
2278                 size_t len;
2279                 size_t hashlen;
2280                 u2 index;
2281                 u2 old;
2282
2283                 /* Allocate hashtable */
2284                 len = c->methodscount;
2285                 if (len < c->fieldscount) len = c->fieldscount;
2286                 hashlen = 5 * len;
2287                 hashtab = MNEW(u2,(hashlen + len));
2288                 next = hashtab + hashlen;
2289
2290                 /* Determine bitshift (to get good hash values) */
2291                 if (!shift) {
2292                         len = sizeof(utf);
2293                         while (len) {
2294                                 len >>= 1;
2295                                 shift++;
2296                         }
2297                 }
2298
2299                 /* Check fields */
2300                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2301
2302                 for (i = 0; i < c->fieldscount; ++i) {
2303                         fieldinfo *fi = c->fields + i;
2304
2305                         /* It's ok if we lose bits here */
2306                         index = ((((size_t) fi->name) +
2307                                           ((size_t) fi->descriptor)) >> shift) % hashlen;
2308
2309                         if ((old = hashtab[index])) {
2310                                 old--;
2311                                 next[i] = old;
2312                                 do {
2313                                         if (c->fields[old].name == fi->name &&
2314                                                 c->fields[old].descriptor == fi->descriptor) {
2315                                                 *exceptionptr =
2316                                                         new_classformaterror(c,
2317                                                                                                  "Repetitive field name/signature");
2318
2319                                                 return NULL;
2320                                         }
2321                                 } while ((old = next[old]));
2322                         }
2323                         hashtab[index] = i + 1;
2324                 }
2325                 
2326                 /* Check methods */
2327                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2328
2329                 for (i = 0; i < c->methodscount; ++i) {
2330                         methodinfo *mi = c->methods + i;
2331
2332                         /* It's ok if we lose bits here */
2333                         index = ((((size_t) mi->name) +
2334                                           ((size_t) mi->descriptor)) >> shift) % hashlen;
2335
2336                         if ((old = hashtab[index])) {
2337                                 old--;
2338                                 next[i] = old;
2339                                 do {
2340                                         if (c->methods[old].name == mi->name &&
2341                                                 c->methods[old].descriptor == mi->descriptor) {
2342                                                 *exceptionptr =
2343                                                         new_classformaterror(c,
2344                                                                                                  "Repetitive method name/signature");
2345
2346                                                 return NULL;
2347                                         }
2348                                 } while ((old = next[old]));
2349                         }
2350                         hashtab[index] = i + 1;
2351                 }
2352                 
2353                 MFREE(hashtab, u2, (hashlen + len));
2354         }
2355
2356 #if defined(STATISTICS)
2357         if (opt_stat) {
2358                 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2359                 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2360                 count_class_infos += sizeof(methodinfo) * c->methodscount;
2361         }
2362 #endif
2363
2364         /* load variable-length attribute structures */ 
2365         if (!check_classbuffer_size(cb, 2))
2366                 return NULL;
2367
2368         if (!attribute_load(cb, c, suck_u2(cb)))
2369                 return NULL;
2370
2371 #if 0
2372         /* XXX TWISTI is this still in the JVM spec? SUN and IBM don't complain about it */
2373         
2374         /* check if all data has been read */
2375         classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2376
2377         if (classdata_left > 0) {
2378                 /* surplus */           
2379                 dolog("There are %d extra bytes at end of classfile", classdata_left);
2380                 /* The JVM spec disallows extra bytes. */
2381                 panic("Extra bytes at end of classfile");
2382         }
2383 #endif
2384
2385         if (loadverbose)
2386                 log_message_class("Loading done class: ", c);
2387
2388         return c;
2389 }
2390
2391
2392
2393 /************** internal Function: class_highestinterface **********************
2394
2395         Used by the function class_link to determine the amount of memory needed
2396         for the interface table.
2397
2398 *******************************************************************************/
2399
2400 static s4 class_highestinterface(classinfo *c) 
2401 {
2402         s4 h;
2403         s4 i;
2404         
2405         if (!(c->flags & ACC_INTERFACE)) {
2406                 char logtext[MAXLOGTEXT];
2407                 sprintf(logtext, "Interface-methods count requested for non-interface:  ");
2408         utf_sprint(logtext + strlen(logtext), c->name);
2409         error("%s",logtext);
2410         }
2411     
2412     h = c->index;
2413         for (i = 0; i < c->interfacescount; i++) {
2414                 s4 h2 = class_highestinterface(c->interfaces[i]);
2415                 if (h2 > h) h = h2;
2416         }
2417
2418         return h;
2419 }
2420
2421
2422 /* class_addinterface **********************************************************
2423
2424         Is needed by class_link for adding a VTBL to a class. All interfaces
2425         implemented by ic are added as well.
2426
2427 *******************************************************************************/
2428
2429 static void class_addinterface(classinfo *c, classinfo *ic)
2430 {
2431         s4     j, m;
2432         s4     i     = ic->index;
2433         vftbl *vftbl = c->vftbl;
2434
2435         if (i >= vftbl->interfacetablelength)
2436                 panic ("Inernal error: interfacetable overflow");
2437
2438         if (vftbl->interfacetable[-i])
2439                 return;
2440
2441         if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
2442                 vftbl->interfacevftbllength[i] = 1;
2443                 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
2444                 vftbl->interfacetable[-i][0] = NULL;
2445
2446         } else {
2447                 vftbl->interfacevftbllength[i] = ic->methodscount;
2448                 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
2449
2450 #ifdef STATISTICS
2451                 if (opt_stat)
2452                         count_vftbl_len += sizeof(methodptr) *
2453                                 (ic->methodscount + (ic->methodscount == 0));
2454 #endif
2455
2456                 for (j = 0; j < ic->methodscount; j++) {
2457                         classinfo *sc = c;
2458                         while (sc) {
2459                                 for (m = 0; m < sc->methodscount; m++) {
2460                                         methodinfo *mi = &(sc->methods[m]);
2461                                         if (method_canoverwrite(mi, &(ic->methods[j]))) {
2462                                                 vftbl->interfacetable[-i][j] =
2463                                                         vftbl->table[mi->vftblindex];
2464                                                 goto foundmethod;
2465                                         }
2466                                 }
2467                                 sc = sc->super;
2468                         }
2469                 foundmethod:
2470                         ;
2471                 }
2472         }
2473
2474         for (j = 0; j < ic->interfacescount; j++) 
2475                 class_addinterface(c, ic->interfaces[j]);
2476 }
2477
2478
2479 /******************* Function: class_new_array *********************************
2480
2481     This function is called by class_new to setup an array class.
2482
2483 *******************************************************************************/
2484
2485 void class_new_array(classinfo *c)
2486 {
2487         classinfo *comp = NULL;
2488         methodinfo *clone;
2489         int namelen;
2490
2491         /* Check array class name */
2492         namelen = c->name->blength;
2493         if (namelen < 2 || c->name->text[0] != '[')
2494                 panic("Invalid array class name");
2495
2496         /* Check the component type */
2497         switch (c->name->text[1]) {
2498         case '[':
2499                 /* c is an array of arrays. We have to create the component class. */
2500                 if (opt_eager) {
2501                         comp = class_new_intern(utf_new_intern(c->name->text + 1,
2502                                                                                                    namelen - 1));
2503                         class_load(comp);
2504                         list_addfirst(&unlinkedclasses, comp);
2505
2506                 } else {
2507                         comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2508                 }
2509                 break;
2510
2511         case 'L':
2512                 /* c is an array of objects. */
2513                 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2514                         panic("Invalid array class name");
2515
2516                 if (opt_eager) {
2517                         comp = class_new_intern(utf_new_intern(c->name->text + 2,
2518                                                                                                    namelen - 3));
2519                         class_load(comp);
2520                         list_addfirst(&unlinkedclasses, comp);
2521
2522                 } else {
2523                         comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2524                 }
2525                 break;
2526         }
2527
2528         /* Setup the array class */
2529         c->super = class_java_lang_Object;
2530         c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2531
2532     c->interfacescount = 2;
2533     c->interfaces = MNEW(classinfo*, 2);
2534
2535         if (opt_eager) {
2536                 classinfo *tc;
2537
2538                 tc = class_new_intern(utf_new_char("java/lang/Cloneable"));
2539                 class_load(tc);
2540                 list_addfirst(&unlinkedclasses, tc);
2541                 c->interfaces[0] = tc;
2542
2543                 tc = class_new_intern(utf_new_char("java/io/Serializable"));
2544                 class_load(tc);
2545                 list_addfirst(&unlinkedclasses, tc);
2546                 c->interfaces[1] = tc;
2547
2548         } else {
2549                 c->interfaces[0] = class_new(utf_new_char("java/lang/Cloneable"));
2550                 c->interfaces[1] = class_new(utf_new_char("java/io/Serializable"));
2551         }
2552
2553         c->methodscount = 1;
2554         c->methods = MNEW(methodinfo, c->methodscount);
2555
2556         clone = c->methods;
2557         memset(clone, 0, sizeof(methodinfo));
2558         clone->flags = ACC_PUBLIC;
2559         clone->name = utf_new_char("clone");
2560         clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2561         clone->class = c;
2562         clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2563         clone->monoPoly = MONO;
2564
2565         /* XXX: field: length? */
2566
2567         /* array classes are not loaded from class files */
2568         c->loaded = true;
2569 }
2570
2571
2572 /****************** Function: class_link_array *********************************
2573
2574     This function is called by class_link to create the
2575     arraydescriptor for an array class.
2576
2577     This function returns NULL if the array cannot be linked because
2578     the component type has not been linked yet.
2579
2580 *******************************************************************************/
2581
2582 static arraydescriptor *class_link_array(classinfo *c)
2583 {
2584         classinfo *comp = NULL;
2585         s4 namelen = c->name->blength;
2586         arraydescriptor *desc;
2587         vftbl *compvftbl;
2588
2589         /* Check the component type */
2590         switch (c->name->text[1]) {
2591         case '[':
2592                 /* c is an array of arrays. */
2593 /*              comp = class_get(utf_new_intern(c->name->text + 1, namelen - 1)); */
2594                 comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2595                 if (!comp)
2596                         panic("Could not find component array class.");
2597                 break;
2598
2599         case 'L':
2600                 /* c is an array of objects. */
2601 /*              comp = class_get(utf_new_intern(c->name->text + 2, namelen - 3)); */
2602                 comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2603                 if (!comp)
2604                         panic("Could not find component class.");
2605                 break;
2606         }
2607
2608         /* If the component type has not been linked, link it now */
2609         if (comp && !comp->linked) {
2610                 if (!comp->loaded)
2611                         class_load(comp);
2612                 class_link(comp);
2613         }
2614
2615         /* Allocate the arraydescriptor */
2616         desc = NEW(arraydescriptor);
2617
2618         if (comp) {
2619                 /* c is an array of references */
2620                 desc->arraytype = ARRAYTYPE_OBJECT;
2621                 desc->componentsize = sizeof(void*);
2622                 desc->dataoffset = OFFSET(java_objectarray, data);
2623                 
2624                 compvftbl = comp->vftbl;
2625                 if (!compvftbl)
2626                         panic("Component class has no vftbl");
2627                 desc->componentvftbl = compvftbl;
2628                 
2629                 if (compvftbl->arraydesc) {
2630                         desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2631                         if (compvftbl->arraydesc->dimension >= 255)
2632                                 panic("Creating array of dimension >255");
2633                         desc->dimension = compvftbl->arraydesc->dimension + 1;
2634                         desc->elementtype = compvftbl->arraydesc->elementtype;
2635
2636                 } else {
2637                         desc->elementvftbl = compvftbl;
2638                         desc->dimension = 1;
2639                         desc->elementtype = ARRAYTYPE_OBJECT;
2640                 }
2641
2642         } else {
2643                 /* c is an array of a primitive type */
2644                 switch (c->name->text[1]) {
2645                 case 'Z':
2646                         desc->arraytype = ARRAYTYPE_BOOLEAN;
2647                         desc->dataoffset = OFFSET(java_booleanarray,data);
2648                         desc->componentsize = sizeof(u1);
2649                         break;
2650
2651                 case 'B':
2652                         desc->arraytype = ARRAYTYPE_BYTE;
2653                         desc->dataoffset = OFFSET(java_bytearray,data);
2654                         desc->componentsize = sizeof(u1);
2655                         break;
2656
2657                 case 'C':
2658                         desc->arraytype = ARRAYTYPE_CHAR;
2659                         desc->dataoffset = OFFSET(java_chararray,data);
2660                         desc->componentsize = sizeof(u2);
2661                         break;
2662
2663                 case 'D':
2664                         desc->arraytype = ARRAYTYPE_DOUBLE;
2665                         desc->dataoffset = OFFSET(java_doublearray,data);
2666                         desc->componentsize = sizeof(double);
2667                         break;
2668
2669                 case 'F':
2670                         desc->arraytype = ARRAYTYPE_FLOAT;
2671                         desc->dataoffset = OFFSET(java_floatarray,data);
2672                         desc->componentsize = sizeof(float);
2673                         break;
2674
2675                 case 'I':
2676                         desc->arraytype = ARRAYTYPE_INT;
2677                         desc->dataoffset = OFFSET(java_intarray,data);
2678                         desc->componentsize = sizeof(s4);
2679                         break;
2680
2681                 case 'J':
2682                         desc->arraytype = ARRAYTYPE_LONG;
2683                         desc->dataoffset = OFFSET(java_longarray,data);
2684                         desc->componentsize = sizeof(s8);
2685                         break;
2686
2687                 case 'S':
2688                         desc->arraytype = ARRAYTYPE_SHORT;
2689                         desc->dataoffset = OFFSET(java_shortarray,data);
2690                         desc->componentsize = sizeof(s2);
2691                         break;
2692
2693                 default:
2694                         panic("Invalid array class name");
2695                 }
2696                 
2697                 desc->componentvftbl = NULL;
2698                 desc->elementvftbl = NULL;
2699                 desc->dimension = 1;
2700                 desc->elementtype = desc->arraytype;
2701         }
2702
2703         return desc;
2704 }
2705
2706
2707 /********************** Function: class_link ***********************************
2708
2709         Tries to link a class. The function calculates the length in bytes that
2710         an instance of this class requires as well as the VTBL for methods and
2711         interface methods.
2712         
2713 *******************************************************************************/
2714
2715 static classinfo *class_link_intern(classinfo *c);
2716
2717 classinfo *class_link(classinfo *c)
2718 {
2719         classinfo *r;
2720         s8 starttime;
2721         s8 stoptime;
2722
2723 #if defined(USE_THREADS)
2724 #if defined(NATIVE_THREADS)
2725         compiler_lock();
2726         tables_lock();
2727 #else
2728         intsDisable();
2729 #endif
2730 #endif
2731
2732         /* maybe the class is already linked */
2733         if (c->linked) {
2734 #if defined(USE_THREADS)
2735 #if defined(NATIVE_THREADS)
2736                 tables_unlock();
2737                 compiler_unlock();
2738 #else
2739                 intsRestore();
2740 #endif
2741 #endif
2742
2743                 return c;
2744         }
2745
2746         /* measure time */
2747         if (getloadingtime)
2748                 starttime = getcputime();
2749
2750         /* call the internal function */
2751         r = class_link_intern(c);
2752
2753         /* if return value is NULL, we had a problem and the class is not linked */
2754         if (!r)
2755                 c->linked = false;
2756
2757         /* measure time */
2758         if (getloadingtime) {
2759                 stoptime = getcputime();
2760                 loadingtime += (stoptime - starttime);
2761         }
2762
2763 #if defined(USE_THREADS)
2764 #if defined(NATIVE_THREADS)
2765         tables_unlock();
2766         compiler_unlock();
2767 #else
2768         intsRestore();
2769 #endif
2770 #endif
2771
2772         return r;
2773 }
2774
2775
2776 static classinfo *class_link_intern(classinfo *c)
2777 {
2778         s4 supervftbllength;          /* vftbllegnth of super class               */
2779         s4 vftbllength;               /* vftbllength of current class             */
2780         s4 interfacetablelength;      /* interface table length                   */
2781         classinfo *super = c->super;  /* super class                              */
2782         classinfo *ic, *c2;           /* intermediate class variables             */
2783         vftbl *v;                     /* vftbl of current class                   */
2784         s4 i;                         /* interface/method/field counter           */
2785         arraydescriptor *arraydesc = NULL;  /* descriptor for array classes       */
2786
2787         /* maybe the class is already linked */
2788         if (c->linked)
2789                 return c;
2790
2791         if (linkverbose)
2792                 log_message_class("Linking class: ", c);
2793
2794         /* ok, this class is somewhat linked */
2795         c->linked = true;
2796
2797         /* check interfaces */
2798
2799         for (i = 0; i < c->interfacescount; i++) {
2800                 ic = c->interfaces[i];
2801
2802                 /* detect circularity */
2803                 if (ic == c) {
2804                         *exceptionptr =
2805                                 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2806                                                                                  c->name);
2807
2808                         return NULL;
2809                 }
2810
2811                 if (!ic->loaded)
2812                         if (!class_load(ic))
2813                                 return NULL;
2814
2815                 if (!ic->linked)
2816                         if (!class_link(ic))
2817                                 return NULL;
2818
2819                 if (!(ic->flags & ACC_INTERFACE)) {
2820                         dolog("Specified interface is not declared as interface:");
2821                         log_utf(ic->name);
2822                         dolog("in");
2823                         log_utf(c->name);
2824                         panic("Specified interface is not declared as interface");
2825                 }
2826         }
2827         
2828         /*  check super class */
2829
2830         if (super == NULL) {          /* class java.lang.Object */
2831                 c->index = 0;
2832         c->classUsed = USED;     /* Object class is always used CO-RT*/
2833                 c->impldBy = NULL;
2834                 c->instancesize = sizeof(java_objectheader);
2835                 
2836                 vftbllength = supervftbllength = 0;
2837
2838                 c->finalizer = NULL;
2839
2840         } else {
2841                 /* detect circularity */
2842                 if (super == c) {
2843                         *exceptionptr =
2844                                 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2845                                                                                  c->name);
2846
2847                         return NULL;
2848                 }
2849
2850                 if (!super->loaded)
2851                         if (!class_load(super))
2852                                 return NULL;
2853
2854                 if (!super->linked)
2855                         if (!class_link(super))
2856                                 return NULL;
2857
2858                 if (super->flags & ACC_INTERFACE)
2859                         panic("Interface specified as super class");
2860
2861                 /* handle array classes */
2862                 /* The component class must have been linked already. */
2863                 if (c->name->text[0] == '[') {
2864                         if ((arraydesc = class_link_array(c)) == NULL) {
2865                                 panic("class_link: class_link_array");
2866                         }
2867                 }
2868
2869                 /* Don't allow extending final classes */
2870                 if (super->flags & ACC_FINAL)
2871                         panic("Trying to extend final class");
2872                 
2873                 if (c->flags & ACC_INTERFACE)
2874                         c->index = interfaceindex++;
2875                 else
2876                         c->index = super->index + 1;
2877                 
2878                 c->instancesize = super->instancesize;
2879                 
2880                 vftbllength = supervftbllength = super->vftbl->vftbllength;
2881                 
2882                 c->finalizer = super->finalizer;
2883         }
2884
2885         /* compute vftbl length */
2886
2887         for (i = 0; i < c->methodscount; i++) {
2888                 methodinfo *m = &(c->methods[i]);
2889                         
2890                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2891                         classinfo *sc = super;
2892                         while (sc) {
2893                                 s4 j;
2894                                 for (j = 0; j < sc->methodscount; j++) {
2895                                         if (method_canoverwrite(m, &(sc->methods[j]))) {
2896                                                 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2897                                                         goto notfoundvftblindex;
2898
2899                                                 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2900                                                         log_utf(c->name);
2901                                                         log_utf(sc->name);
2902                                                         log_utf(sc->methods[j].name);
2903                                                         log_utf(sc->methods[j].descriptor);
2904                                                         panic("Trying to overwrite final method");
2905                                                 }
2906                                                 m->vftblindex = sc->methods[j].vftblindex;
2907                                                 goto foundvftblindex;
2908                                         }
2909                                 }
2910                                 sc = sc->super;
2911                         }
2912                 notfoundvftblindex:
2913                         m->vftblindex = (vftbllength++);
2914                 foundvftblindex:
2915                         ;
2916                 }
2917         }       
2918         
2919 #ifdef STATISTICS
2920         if (opt_stat)
2921                 count_vftbl_len +=
2922                         sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2923 #endif
2924
2925         /* compute interfacetable length */
2926
2927         interfacetablelength = 0;
2928         c2 = c;
2929         while (c2) {
2930                 for (i = 0; i < c2->interfacescount; i++) {
2931                         s4 h = class_highestinterface(c2->interfaces[i]) + 1;
2932                         if (h > interfacetablelength)
2933                                 interfacetablelength = h;
2934                 }
2935                 c2 = c2->super;
2936         }
2937
2938         /* allocate virtual function table */
2939
2940         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2941                                                    (vftbllength - 1) + sizeof(methodptr*) *
2942                                                    (interfacetablelength - (interfacetablelength > 0)));
2943         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2944                                   (interfacetablelength > 1));
2945         c->header.vftbl = c->vftbl = v;
2946 /*      utf_display_classname(c->name);printf(", c->header.vftbl=%p\n", c->header.vftbl); */
2947         v->class = c;
2948         v->vftbllength = vftbllength;
2949         v->interfacetablelength = interfacetablelength;
2950         v->arraydesc = arraydesc;
2951
2952         /* store interface index in vftbl */
2953         if (c->flags & ACC_INTERFACE)
2954                 v->baseval = -(c->index);
2955
2956         /* copy virtual function table of super class */
2957
2958         for (i = 0; i < supervftbllength; i++) 
2959                 v->table[i] = super->vftbl->table[i];
2960         
2961         /* add method stubs into virtual function table */
2962
2963         for (i = 0; i < c->methodscount; i++) {
2964                 methodinfo *m = &(c->methods[i]);
2965                 if (!(m->flags & ACC_STATIC)) {
2966                         v->table[m->vftblindex] = m->stubroutine;
2967                 }
2968         }
2969
2970         /* compute instance size and offset of each field */
2971         
2972         for (i = 0; i < c->fieldscount; i++) {
2973                 s4 dsize;
2974                 fieldinfo *f = &(c->fields[i]);
2975                 
2976                 if (!(f->flags & ACC_STATIC)) {
2977                         dsize = desc_typesize(f->descriptor);
2978                         c->instancesize = ALIGN(c->instancesize, dsize);
2979                         f->offset = c->instancesize;
2980                         c->instancesize += dsize;
2981                 }
2982         }
2983
2984         /* initialize interfacetable and interfacevftbllength */
2985         
2986         v->interfacevftbllength = MNEW(s4, interfacetablelength);
2987
2988 #ifdef STATISTICS
2989         if (opt_stat)
2990                 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2991 #endif
2992
2993         for (i = 0; i < interfacetablelength; i++) {
2994                 v->interfacevftbllength[i] = 0;
2995                 v->interfacetable[-i] = NULL;
2996         }
2997         
2998         /* add interfaces */
2999         
3000         for (c2 = c; c2 != NULL; c2 = c2->super)
3001                 for (i = 0; i < c2->interfacescount; i++) {
3002                         class_addinterface(c, c2->interfaces[i]);
3003                 }
3004
3005         /* add finalizer method (not for java.lang.Object) */
3006
3007         if (super != NULL) {
3008                 methodinfo *fi;
3009                 static utf *finame = NULL;
3010                 static utf *fidesc = NULL;
3011
3012                 if (finame == NULL)
3013                         finame = utf_finalize;
3014                 if (fidesc == NULL)
3015                         fidesc = utf_fidesc;
3016
3017                 fi = class_findmethod(c, finame, fidesc);
3018                 if (fi != NULL) {
3019                         if (!(fi->flags & ACC_STATIC)) {
3020                                 c->finalizer = fi;
3021                         }
3022                 }
3023         }
3024
3025         /* final tasks */
3026
3027         loader_compute_subclasses(c);
3028
3029         if (linkverbose)
3030                 log_message_class("Linking done class: ", c);
3031
3032         /* just return c to show that we didn't had a problem */
3033
3034         return c;
3035 }
3036
3037
3038 /******************* Function: class_freepool **********************************
3039
3040         Frees all resources used by this classes Constant Pool.
3041
3042 *******************************************************************************/
3043
3044 static void class_freecpool(classinfo *c)
3045 {
3046         u4 idx;
3047         u4 tag;
3048         voidptr info;
3049         
3050         if (c->cptags && c->cpinfos) {
3051                 for (idx = 0; idx < c->cpcount; idx++) {
3052                         tag = c->cptags[idx];
3053                         info = c->cpinfos[idx];
3054                 
3055                         if (info != NULL) {
3056                                 switch (tag) {
3057                                 case CONSTANT_Fieldref:
3058                                 case CONSTANT_Methodref:
3059                                 case CONSTANT_InterfaceMethodref:
3060                                         FREE(info, constant_FMIref);
3061                                         break;
3062                                 case CONSTANT_Integer:
3063                                         FREE(info, constant_integer);
3064                                         break;
3065                                 case CONSTANT_Float:
3066                                         FREE(info, constant_float);
3067                                         break;
3068                                 case CONSTANT_Long:
3069                                         FREE(info, constant_long);
3070                                         break;
3071                                 case CONSTANT_Double:
3072                                         FREE(info, constant_double);
3073                                         break;
3074                                 case CONSTANT_NameAndType:
3075                                         FREE(info, constant_nameandtype);
3076                                         break;
3077                                 }
3078                         }
3079                 }
3080         }
3081
3082         if (c->cptags)
3083                 MFREE(c->cptags, u1, c->cpcount);
3084
3085         if (c->cpinfos)
3086                 MFREE(c->cpinfos, voidptr, c->cpcount);
3087 }
3088
3089
3090 /*********************** Function: class_free **********************************
3091
3092         Frees all resources used by the class.
3093
3094 *******************************************************************************/
3095
3096 void class_free(classinfo *c)
3097 {
3098         s4 i;
3099         vftbl *v;
3100                 
3101         class_freecpool(c);
3102
3103         if (c->interfaces)
3104                 MFREE(c->interfaces, classinfo*, c->interfacescount);
3105
3106         if (c->fields) {
3107                 for (i = 0; i < c->fieldscount; i++)
3108                         field_free(&(c->fields[i]));
3109 /*      MFREE(c->fields, fieldinfo, c->fieldscount); */
3110         }
3111         
3112         if (c->methods) {
3113                 for (i = 0; i < c->methodscount; i++)
3114                         method_free(&(c->methods[i]));
3115 /*      MFREE(c->methods, methodinfo, c->methodscount); */
3116         }
3117
3118         if ((v = c->vftbl) != NULL) {
3119                 if (v->arraydesc)
3120                         mem_free(v->arraydesc,sizeof(arraydescriptor));
3121                 
3122                 for (i = 0; i < v->interfacetablelength; i++) {
3123                         MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
3124                 }
3125                 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
3126
3127                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
3128                     sizeof(methodptr*) * (v->interfacetablelength -
3129                                          (v->interfacetablelength > 0));
3130                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
3131                                              (v->interfacetablelength > 1));
3132                 mem_free(v, i);
3133         }
3134
3135         if (c->innerclass)
3136                 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
3137
3138         /*      if (c->classvftbl)
3139                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
3140         
3141 /*      GCFREE(c); */
3142 }
3143
3144
3145 /************************* Function: class_findfield ***************************
3146         
3147         Searches a 'classinfo' structure for a field having the given name and
3148         type.
3149
3150 *******************************************************************************/
3151
3152 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
3153 {
3154         s4 i;
3155
3156         for (i = 0; i < c->fieldscount; i++) { 
3157                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
3158                         return &(c->fields[i]);                                                         
3159     }
3160
3161         panic("Can not find field given in CONSTANT_Fieldref");
3162
3163         /* keep compiler happy */
3164         return NULL;
3165 }
3166
3167
3168 /****************** Function: class_resolvefield_int ***************************
3169
3170     This is an internally used helper function. Do not use this directly.
3171
3172         Tries to resolve a field having the given name and type.
3173     If the field cannot be resolved, NULL is returned.
3174
3175 *******************************************************************************/
3176
3177 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
3178 {
3179         s4 i;
3180         fieldinfo *fi;
3181
3182         /* search for field in class c */
3183         for (i = 0; i < c->fieldscount; i++) { 
3184                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
3185                         return &(c->fields[i]);
3186                 }
3187     }
3188
3189         /* try superinterfaces recursively */
3190         for (i = 0; i < c->interfacescount; ++i) {
3191                 fi = class_resolvefield_int(c->interfaces[i], name, desc);
3192                 if (fi)
3193                         return fi;
3194         }
3195
3196         /* try superclass */
3197         if (c->super)
3198                 return class_resolvefield_int(c->super, name, desc);
3199
3200         /* not found */
3201         return NULL;
3202 }
3203
3204
3205 /********************* Function: class_resolvefield ***************************
3206         
3207         Resolves a reference from REFERER to a field with NAME and DESC in class C.
3208
3209     If the field cannot be resolved the return value is NULL. If EXCEPT is
3210     true *exceptionptr is set, too.
3211
3212 *******************************************************************************/
3213
3214 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
3215                                                           classinfo *referer, bool except)
3216 {
3217         fieldinfo *fi;
3218
3219         /* XXX resolve class c */
3220         /* XXX check access from REFERER to C */
3221         
3222         fi = class_resolvefield_int(c, name, desc);
3223
3224         if (!fi) {
3225                 if (except)
3226                         *exceptionptr =
3227                                 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
3228                                                                                  name);
3229
3230                 return NULL;
3231         }
3232
3233         /* XXX check access rights */
3234
3235         return fi;
3236 }
3237
3238
3239 /************************* Function: class_findmethod **************************
3240         
3241         Searches a 'classinfo' structure for a method having the given name and
3242         type and returns the index in the class info structure.
3243         If type is NULL, it is ignored.
3244
3245 *******************************************************************************/
3246
3247 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
3248 {
3249         s4 i;
3250
3251         for (i = 0; i < c->methodscount; i++) {
3252
3253 /*              utf_display_classname(c->name);printf("."); */
3254 /*              utf_display(c->methods[i].name);printf("."); */
3255 /*              utf_display(c->methods[i].descriptor); */
3256 /*              printf("\n"); */
3257
3258                 if ((c->methods[i].name == name) && ((desc == NULL) ||
3259                                                                                          (c->methods[i].descriptor == desc))) {
3260                         return i;
3261                 }
3262         }
3263
3264         return -1;
3265 }
3266
3267
3268 /************************* Function: class_findmethod **************************
3269         
3270         Searches a 'classinfo' structure for a method having the given name and
3271         type.
3272         If type is NULL, it is ignored.
3273
3274 *******************************************************************************/
3275
3276 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
3277 {
3278         s4 idx = class_findmethodIndex(c, name, desc);
3279
3280         if (idx == -1)
3281                 return NULL;
3282
3283         return &(c->methods[idx]);
3284 }
3285
3286
3287 /*********************** Function: class_fetchmethod **************************
3288         
3289     like class_findmethod, but aborts with an error if the method is not found
3290
3291 *******************************************************************************/
3292
3293 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
3294 {
3295         methodinfo *mi;
3296
3297         mi = class_findmethod(c, name, desc);
3298
3299         if (!mi) {
3300                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3301                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3302                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3303                 panic("Method not found");
3304         }
3305
3306         return mi;
3307 }
3308
3309
3310 /*********************** Function: class_findmethod_w**************************
3311
3312     like class_findmethod, but logs a warning if the method is not found
3313
3314 *******************************************************************************/
3315
3316 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
3317 {
3318         methodinfo *mi;
3319         mi = class_findmethod(c, name, desc);
3320
3321         if (!mi) {
3322                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
3323                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
3324                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
3325
3326                 if ( c->flags & ACC_PUBLIC )       log_plain(" PUBLIC ");
3327                 if ( c->flags & ACC_PRIVATE )      log_plain(" PRIVATE ");
3328                 if ( c->flags & ACC_PROTECTED )    log_plain(" PROTECTED ");
3329                 if ( c->flags & ACC_STATIC )       log_plain(" STATIC ");
3330                 if ( c->flags & ACC_FINAL )        log_plain(" FINAL ");
3331                 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
3332                 if ( c->flags & ACC_VOLATILE )     log_plain(" VOLATILE ");
3333                 if ( c->flags & ACC_TRANSIENT )    log_plain(" TRANSIENT ");
3334                 if ( c->flags & ACC_NATIVE )       log_plain(" NATIVE ");
3335                 if ( c->flags & ACC_INTERFACE )    log_plain(" INTERFACE ");
3336                 if ( c->flags & ACC_ABSTRACT )     log_plain(" ABSTRACT ");
3337
3338                 log_plain(from); 
3339                 log_plain(" : WARNING: Method not found");log_nl( );
3340         }
3341
3342         return mi;
3343 }
3344
3345
3346 /************************* Function: class_findmethod_approx ******************
3347         
3348         like class_findmethod but ignores the return value when comparing the
3349         descriptor.
3350
3351 *******************************************************************************/
3352
3353 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
3354 {
3355         s4 i;
3356
3357         for (i = 0; i < c->methodscount; i++) {
3358                 if (c->methods[i].name == name) {
3359                         utf *meth_descr = c->methods[i].descriptor;
3360                         
3361                         if (desc == NULL) 
3362                                 /* ignore type */
3363                                 return &(c->methods[i]);
3364
3365                         if (desc->blength <= meth_descr->blength) {
3366                                 /* current position in utf text   */
3367                                 char *desc_utf_ptr = desc->text;      
3368                                 char *meth_utf_ptr = meth_descr->text;                                    
3369                                 /* points behind utf strings */
3370                                 char *desc_end = utf_end(desc);         
3371                                 char *meth_end = utf_end(meth_descr);   
3372                                 char ch;
3373
3374                                 /* compare argument types */
3375                                 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
3376
3377                                         if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
3378                                                 break; /* no match */
3379
3380                                         if (ch == ')')
3381                                                 return &(c->methods[i]);   /* all parameter types equal */
3382                                 }
3383                         }
3384                 }
3385         }
3386
3387         return NULL;
3388 }
3389
3390
3391 /***************** Function: class_resolvemethod_approx ***********************
3392         
3393         Searches a class and every super class for a method (without paying
3394         attention to the return value)
3395
3396 *******************************************************************************/
3397
3398 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
3399 {
3400         while (c) {
3401                 /* search for method (ignore returntype) */
3402                 methodinfo *m = class_findmethod_approx(c, name, desc);
3403                 /* method found */
3404                 if (m) return m;
3405                 /* search superclass */
3406                 c = c->super;
3407         }
3408
3409         return NULL;
3410 }
3411
3412
3413 /************************* Function: class_resolvemethod ***********************
3414         
3415         Searches a class and every super class for a method.
3416
3417 *******************************************************************************/
3418
3419 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3420 {
3421         /*log_text("Trying to resolve a method");
3422         utf_display(c->name);
3423         utf_display(name);
3424         utf_display(desc);*/
3425
3426         while (c) {
3427                 /*log_text("Looking in:");
3428                 utf_display(c->name);*/
3429                 methodinfo *m = class_findmethod(c, name, desc);
3430                 if (m) return m;
3431                 /* search superclass */
3432                 c = c->super;
3433         }
3434         /*log_text("method not found:");*/
3435
3436         return NULL;
3437 }
3438
3439
3440 /****************** Function: class_resolveinterfacemethod_int ****************
3441
3442     Internally used helper function. Do not use this directly.
3443
3444 *******************************************************************************/
3445
3446 static
3447 methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
3448 {
3449         methodinfo *mi;
3450         int i;
3451         
3452         mi = class_findmethod(c,name,desc);
3453         if (mi)
3454                 return mi;
3455
3456         /* try the superinterfaces */
3457         for (i=0; i<c->interfacescount; ++i) {
3458                 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3459                 if (mi)
3460                         return mi;
3461         }
3462         
3463         return NULL;
3464 }
3465
3466 /******************** Function: class_resolveinterfacemethod ******************
3467
3468     Resolves a reference from REFERER to a method with NAME and DESC in
3469     interface C.
3470
3471     If the method cannot be resolved the return value is NULL. If EXCEPT is
3472     true *exceptionptr is set, too.
3473
3474 *******************************************************************************/
3475
3476 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3477                                                                                  classinfo *referer, bool except)
3478 {
3479         methodinfo *mi;
3480
3481         /* XXX resolve class c */
3482         /* XXX check access from REFERER to C */
3483         
3484         if (!(c->flags & ACC_INTERFACE)) {
3485                 if (except)
3486                         *exceptionptr =
3487                                 new_exception(string_java_lang_IncompatibleClassChangeError);
3488
3489                 return NULL;
3490         }
3491
3492         mi = class_resolveinterfacemethod_int(c, name, desc);
3493
3494         if (mi)
3495                 return mi;
3496
3497         /* try class java.lang.Object */
3498         mi = class_findmethod(class_java_lang_Object, name, desc);
3499
3500         if (mi)
3501                 return mi;
3502
3503         if (except)
3504                 *exceptionptr =
3505                         new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
3506
3507         return NULL;
3508 }
3509
3510
3511 /********************* Function: class_resolveclassmethod *********************
3512         
3513     Resolves a reference from REFERER to a method with NAME and DESC in
3514     class C.
3515
3516     If the method cannot be resolved the return value is NULL. If EXCEPT is
3517     true *exceptionptr is set, too.
3518
3519 *******************************************************************************/
3520
3521 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3522                                                                          classinfo *referer, bool except)
3523 {
3524         classinfo *cls;
3525         methodinfo *mi;
3526         s4 i;
3527         char msg[MAXLOGTEXT];
3528
3529         /* XXX resolve class c */
3530         /* XXX check access from REFERER to C */
3531         
3532 /*      if (c->flags & ACC_INTERFACE) { */
3533 /*              if (except) */
3534 /*                      *exceptionptr = */
3535 /*                              new_exception(string_java_lang_IncompatibleClassChangeError); */
3536 /*              return NULL; */
3537 /*      } */
3538
3539         /* try class c and its superclasses */
3540         cls = c;
3541         do {
3542                 mi = class_findmethod(cls, name, desc);
3543                 if (mi)
3544                         goto found;
3545         } while ((cls = cls->super) != NULL); /* try the superclass */
3546
3547         /* try the superinterfaces */
3548         for (i = 0; i < c->interfacescount; ++i) {
3549                 mi = class_resolveinterfacemethod_int(c->interfaces[i], name, desc);
3550                 if (mi)
3551                         goto found;
3552         }
3553         
3554         if (except) {
3555                 utf_sprint(msg, c->name);
3556                 sprintf(msg + strlen(msg), ".");
3557                 utf_sprint(msg + strlen(msg), name);
3558                 utf_sprint(msg + strlen(msg), desc);
3559
3560                 *exceptionptr =
3561                         new_exception_message(string_java_lang_NoSuchMethodError, msg);
3562         }
3563
3564         return NULL;
3565
3566  found:
3567         if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3568                 if (except)
3569                         *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3570
3571                 return NULL;
3572         }
3573
3574         /* XXX check access rights */
3575
3576         return mi;
3577 }
3578
3579
3580 /************************* Function: class_issubclass **************************
3581
3582         Checks if sub is a descendant of super.
3583         
3584 *******************************************************************************/
3585
3586 bool class_issubclass(classinfo *sub, classinfo *super)
3587 {
3588         for (;;) {
3589                 if (!sub) return false;
3590                 if (sub == super) return true;
3591                 sub = sub->super;
3592         }
3593 }
3594
3595
3596 /****************** Initialization function for classes ******************
3597
3598         In Java, every class can have a static initialization function. This
3599         function has to be called BEFORE calling other methods or accessing static
3600         variables.
3601
3602 *******************************************************************************/
3603
3604 static classinfo *class_init_intern(classinfo *c);
3605
3606 classinfo *class_init(classinfo *c)
3607 {
3608         classinfo *r;
3609
3610         if (!makeinitializations)
3611                 return c;
3612
3613         /* enter a monitor on the class */
3614
3615         builtin_monitorenter((java_objectheader *) c);
3616
3617         /* maybe the class is already initalized or the current thread, which can
3618            pass the monitor, is currently initalizing this class */
3619
3620         if (c->initialized || c->initializing) {
3621                 builtin_monitorexit((java_objectheader *) c);
3622
3623                 return c;
3624         }
3625
3626         /* this initalizing run begins NOW */
3627         c->initializing = true;
3628
3629         /* call the internal function */
3630         r = class_init_intern(c);
3631
3632         /* if return value is not NULL everything was ok and the class is
3633            initialized */
3634         if (r)
3635                 c->initialized = true;
3636
3637         /* this initalizing run is done */
3638         c->initializing = false;
3639
3640         /* leave the monitor */
3641
3642         builtin_monitorexit((java_objectheader *) c);
3643
3644         return r;
3645 }
3646
3647
3648 /* this function MUST NOT be called directly, because of thread <clinit>
3649    race conditions */
3650
3651 static classinfo *class_init_intern(classinfo *c)
3652 {
3653         methodinfo *m;
3654         s4 i;
3655 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3656         int b;
3657 #endif
3658
3659         if (!c->loaded)
3660                 if (!class_load(c))
3661                         return NULL;
3662
3663         if (!c->linked)
3664                 if (!class_link(c))
3665                         return NULL;
3666
3667 #if defined(STATISTICS)
3668         if (opt_stat)
3669                 count_class_inits++;
3670 #endif
3671
3672         /* initialize super class */
3673         if (c->super) {
3674                 if (!c->super->loaded)
3675                         if (!class_load(c->super))
3676                                 return NULL;
3677
3678                 if (!c->super->linked)
3679                         if (!class_link(c->super))
3680                                 return NULL;
3681
3682                 if (!c->super->initialized) {
3683                         if (initverbose) {
3684                                 char logtext[MAXLOGTEXT];
3685                                 sprintf(logtext, "Initialize super class ");
3686                                 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3687                                 sprintf(logtext + strlen(logtext), " from ");
3688                                 utf_sprint_classname(logtext + strlen(logtext), c->name);
3689                                 log_text(logtext);
3690                         }
3691
3692                         if (!class_init(c->super))
3693                                 return NULL;
3694                 }
3695         }
3696
3697         /* initialize interface classes */
3698         for (i = 0; i < c->interfacescount; i++) {
3699                 if (!c->interfaces[i]->loaded)
3700                         if (!class_load(c->interfaces[i]))
3701                                 return NULL;
3702
3703                 if (!c->interfaces[i]->linked)
3704                         if (!class_link(c->interfaces[i]))
3705                                 return NULL;
3706
3707                 if (!c->interfaces[i]->initialized) {
3708                         if (initverbose) {
3709                                 char logtext[MAXLOGTEXT];
3710                                 sprintf(logtext, "Initialize interface class ");
3711                                 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3712                                 sprintf(logtext + strlen(logtext), " from ");
3713                                 utf_sprint_classname(logtext + strlen(logtext), c->name);
3714                                 log_text(logtext);
3715                         }
3716                         
3717                         if (!class_init(c->interfaces[i]))
3718                                 return NULL;
3719                 }
3720         }
3721
3722         m = class_findmethod(c, utf_clinit, utf_fidesc);
3723
3724         if (!m) {
3725                 if (initverbose) {
3726                         char logtext[MAXLOGTEXT];
3727                         sprintf(logtext, "Class ");
3728                         utf_sprint_classname(logtext + strlen(logtext), c->name);
3729                         sprintf(logtext + strlen(logtext), " has no static class initializer");
3730                         log_text(logtext);
3731                 }
3732
3733                 return c;
3734         }
3735
3736         if (!(m->flags & ACC_STATIC))
3737                 panic("Class initializer is not static!");
3738
3739         if (initverbose)
3740                 log_message_class("Starting static class initializer for class: ", c);
3741
3742 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3743         b = blockInts;
3744         blockInts = 0;
3745 #endif
3746
3747         /* now call the initializer */
3748         asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3749
3750 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3751         assert(blockInts == 0);
3752         blockInts = b;
3753 #endif
3754
3755         /* we have an exception or error */
3756         if (*exceptionptr) {
3757                 /* is this an exception, than wrap it */
3758                 if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
3759                         java_objectheader *xptr;
3760                         java_objectheader *cause;
3761
3762                         /* class is NOT initialized */
3763                         c->initialized = false;
3764
3765                         /* get the cause */
3766                         cause = *exceptionptr;
3767
3768                         /* clear exception, because we are calling jit code again */
3769                         *exceptionptr = NULL;
3770
3771                         /* wrap the exception */
3772                         xptr =
3773                                 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3774                                                                                 (java_lang_Throwable *) cause);
3775
3776                         /* XXX should we exit here? */
3777                         if (*exceptionptr)
3778                                 throw_exception();
3779
3780                         /* set new exception */
3781                         *exceptionptr = xptr;
3782                 }
3783
3784                 return NULL;
3785         }
3786
3787         if (initverbose)
3788                 log_message_class("Finished static class initializer for class: ", c);
3789
3790         return c;
3791 }
3792
3793
3794 /********* Function: find_class_method_constant *********/
3795
3796 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)  
3797 {
3798         u4 i;
3799         voidptr e;
3800
3801         for (i=0; i<c->cpcount; i++) {
3802                 
3803                 e = c -> cpinfos [i];
3804                 if (e) {
3805                         
3806                         switch (c -> cptags [i]) {
3807                         case CONSTANT_Methodref:
3808                                 {
3809                                         constant_FMIref *fmi = e;
3810                                         if (       (fmi->class->name == c1)  
3811                                                            && (fmi->name == m1)
3812                                                            && (fmi->descriptor == d1)) {
3813                                         
3814                                                 return i;
3815                                         }
3816                                 }
3817                                 break;
3818
3819                         case CONSTANT_InterfaceMethodref:
3820                                 {
3821                                         constant_FMIref *fmi = e;
3822                                         if (       (fmi->class->name == c1)  
3823                                                            && (fmi->name == m1)
3824                                                            && (fmi->descriptor == d1)) {
3825
3826                                                 return i;
3827                                         }
3828                                 }
3829                                 break;
3830                         }
3831                 }
3832         }
3833
3834         return -1;
3835 }
3836
3837
3838 void class_showconstanti(classinfo *c, int ii) 
3839 {
3840         u4 i = ii;
3841         voidptr e;
3842                 
3843         e = c->cpinfos [i];
3844         printf ("#%d:  ", (int) i);
3845         if (e) {
3846                 switch (c->cptags [i]) {
3847                 case CONSTANT_Class:
3848                         printf("Classreference -> ");
3849                         utf_display(((classinfo*)e)->name);
3850                         break;
3851                                 
3852                 case CONSTANT_Fieldref:
3853                         printf("Fieldref -> "); goto displayFMIi;
3854                 case CONSTANT_Methodref:
3855                         printf("Methodref -> "); goto displayFMIi;
3856                 case CONSTANT_InterfaceMethodref:
3857                         printf("InterfaceMethod -> "); goto displayFMIi;
3858                 displayFMIi:
3859                         {
3860                                 constant_FMIref *fmi = e;
3861                                 utf_display(fmi->class->name);
3862                                 printf(".");
3863                                 utf_display(fmi->name);
3864                                 printf(" ");
3865                                 utf_display(fmi->descriptor);
3866                         }
3867                         break;
3868
3869                 case CONSTANT_String:
3870                         printf("String -> ");
3871                         utf_display(e);
3872                         break;
3873                 case CONSTANT_Integer:
3874                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3875                         break;
3876                 case CONSTANT_Float:
3877                         printf("Float -> %f", ((constant_float*)e)->value);
3878                         break;
3879                 case CONSTANT_Double:
3880                         printf("Double -> %f", ((constant_double*)e)->value);
3881                         break;
3882                 case CONSTANT_Long:
3883                         {
3884                                 u8 v = ((constant_long*)e)->value;
3885 #if U8_AVAILABLE
3886                                 printf("Long -> %ld", (long int) v);
3887 #else
3888                                 printf("Long -> HI: %ld, LO: %ld\n", 
3889                                             (long int) v.high, (long int) v.low);
3890 #endif 
3891                         }
3892                         break;
3893                 case CONSTANT_NameAndType:
3894                         { 
3895                                 constant_nameandtype *cnt = e;
3896                                 printf("NameAndType: ");
3897                                 utf_display(cnt->name);
3898                                 printf(" ");
3899                                 utf_display(cnt->descriptor);
3900                         }
3901                         break;
3902                 case CONSTANT_Utf8:
3903                         printf("Utf8 -> ");
3904                         utf_display(e);
3905                         break;
3906                 default: 
3907                         panic("Invalid type of ConstantPool-Entry");
3908                 }
3909         }
3910         printf("\n");
3911 }
3912
3913
3914 void class_showconstantpool (classinfo *c) 
3915 {
3916         u4 i;
3917         voidptr e;
3918
3919         printf ("---- dump of constant pool ----\n");
3920
3921         for (i=0; i<c->cpcount; i++) {
3922                 printf ("#%d:  ", (int) i);
3923                 
3924                 e = c -> cpinfos [i];
3925                 if (e) {
3926                         
3927                         switch (c -> cptags [i]) {
3928                         case CONSTANT_Class:
3929                                 printf ("Classreference -> ");
3930                                 utf_display ( ((classinfo*)e) -> name );
3931                                 break;
3932                                 
3933                         case CONSTANT_Fieldref:
3934                                 printf ("Fieldref -> "); goto displayFMI;
3935                         case CONSTANT_Methodref:
3936                                 printf ("Methodref -> "); goto displayFMI;
3937                         case CONSTANT_InterfaceMethodref:
3938                                 printf ("InterfaceMethod -> "); goto displayFMI;
3939                         displayFMI:
3940                                 {
3941                                         constant_FMIref *fmi = e;
3942                                         utf_display ( fmi->class->name );
3943                                         printf (".");
3944                                         utf_display ( fmi->name);
3945                                         printf (" ");
3946                                         utf_display ( fmi->descriptor );
3947                                 }
3948                                 break;
3949
3950                         case CONSTANT_String:
3951                                 printf ("String -> ");
3952                                 utf_display (e);
3953                                 break;
3954                         case CONSTANT_Integer:
3955                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3956                                 break;
3957                         case CONSTANT_Float:
3958                                 printf ("Float -> %f", ((constant_float*)e) -> value);
3959                                 break;
3960                         case CONSTANT_Double:
3961                                 printf ("Double -> %f", ((constant_double*)e) -> value);
3962                                 break;
3963                         case CONSTANT_Long:
3964                                 {
3965                                         u8 v = ((constant_long*)e) -> value;
3966 #if U8_AVAILABLE
3967                                         printf ("Long -> %ld", (long int) v);
3968 #else
3969                                         printf ("Long -> HI: %ld, LO: %ld\n", 
3970                                                         (long int) v.high, (long int) v.low);
3971 #endif 
3972                                 }
3973                                 break;
3974                         case CONSTANT_NameAndType:
3975                                 {
3976                                         constant_nameandtype *cnt = e;
3977                                         printf ("NameAndType: ");
3978                                         utf_display (cnt->name);
3979                                         printf (" ");
3980                                         utf_display (cnt->descriptor);
3981                                 }
3982                                 break;
3983                         case CONSTANT_Utf8:
3984                                 printf ("Utf8 -> ");
3985                                 utf_display (e);
3986                                 break;
3987                         default: 
3988                                 panic ("Invalid type of ConstantPool-Entry");
3989                         }
3990                 }
3991
3992                 printf ("\n");
3993         }
3994 }
3995
3996
3997
3998 /********** Function: class_showmethods   (debugging only) *************/
3999
4000 void class_showmethods (classinfo *c)
4001 {
4002         s4 i;
4003         
4004         printf ("--------- Fields and Methods ----------------\n");
4005         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
4006
4007         printf ("This: "); utf_display (c->name); printf ("\n");
4008         if (c->super) {
4009                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
4010                 }
4011         printf ("Index: %d\n", c->index);
4012         
4013         printf ("interfaces:\n");       
4014         for (i=0; i < c-> interfacescount; i++) {
4015                 printf ("   ");
4016                 utf_display (c -> interfaces[i] -> name);
4017                 printf (" (%d)\n", c->interfaces[i] -> index);
4018                 }
4019
4020         printf ("fields:\n");           
4021         for (i=0; i < c -> fieldscount; i++) {
4022                 field_display (&(c -> fields[i]));
4023                 }
4024
4025         printf ("methods:\n");
4026         for (i=0; i < c -> methodscount; i++) {
4027                 methodinfo *m = &(c->methods[i]);
4028                 if ( !(m->flags & ACC_STATIC)) 
4029                         printf ("vftblindex: %d   ", m->vftblindex);
4030
4031                 method_display ( m );
4032
4033                 }
4034
4035         printf ("Virtual function table:\n");
4036         for (i=0; i<c->vftbl->vftbllength; i++) {
4037                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
4038                 }
4039
4040 }
4041
4042
4043 /******************************************************************************/
4044 /******************* General functions for the class loader *******************/
4045 /******************************************************************************/
4046
4047 /**************** function: create_primitive_classes ***************************
4048
4049         create classes representing primitive types
4050
4051 *******************************************************************************/
4052
4053 void create_primitive_classes()
4054 {  
4055         int i;
4056
4057         for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
4058                 /* create primitive class */
4059                 classinfo *c =
4060                         class_new_intern(utf_new_char(primitivetype_table[i].name));
4061                 c->classUsed = NOTUSED; /* not used initially CO-RT */
4062                 c->impldBy = NULL;
4063                 
4064                 /* prevent loader from loading primitive class */
4065                 c->loaded = true;
4066                 class_link(c);
4067
4068                 primitivetype_table[i].class_primitive = c;
4069
4070                 /* create class for wrapping the primitive type */
4071                 c = class_new_intern(utf_new_char(primitivetype_table[i].wrapname));
4072                 primitivetype_table[i].class_wrap = c;
4073                 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
4074                 primitivetype_table[i].class_wrap->impldBy = NULL;
4075
4076                 /* create the primitive array class */
4077                 if (primitivetype_table[i].arrayname) {
4078                         c = class_new_intern(utf_new_char(primitivetype_table[i].arrayname));
4079                         primitivetype_table[i].arrayclass = c;
4080                         c->loaded = true;
4081                         if (!c->linked)
4082                                 class_link(c);
4083                         primitivetype_table[i].arrayvftbl = c->vftbl;
4084                 }
4085         }
4086 }
4087
4088
4089 /**************** function: class_primitive_from_sig ***************************
4090
4091         return the primitive class indicated by the given signature character
4092
4093     If the descriptor does not indicate a valid primitive type the
4094     return value is NULL.
4095
4096 ********************************************************************************/
4097
4098 classinfo *class_primitive_from_sig(char sig)
4099 {
4100         switch (sig) {
4101           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
4102           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
4103           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
4104           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
4105           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
4106           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
4107           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
4108           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
4109           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
4110         }
4111         return NULL;
4112 }
4113
4114 /****************** function: class_from_descriptor ****************************
4115
4116     return the class indicated by the given descriptor
4117
4118     utf_ptr....first character of descriptor
4119     end_ptr....first character after the end of the string
4120     next.......if non-NULL, *next is set to the first character after
4121                the descriptor. (Undefined if an error occurs.)
4122
4123     mode.......a combination (binary or) of the following flags:
4124
4125                (Flags marked with * are the default settings.)
4126
4127                What to do if a reference type descriptor is parsed successfully:
4128
4129                    CLASSLOAD_SKIP...skip it and return something != NULL
4130                                  * CLASSLOAD_NEW....get classinfo * via class_new
4131                    CLASSLOAD_LOAD...get classinfo * via loader_load
4132
4133                How to handle primitive types:
4134
4135                              * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
4136                    CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
4137
4138                How to handle "V" descriptors:
4139
4140                              * CLASSLOAD_VOID.....handle it like other primitive types
4141                    CLASSLOAD_NOVOID...treat it as an error
4142
4143                How to deal with extra characters after the end of the
4144                descriptor:
4145
4146                              * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
4147                    CLASSLOAD_CHECKEND.....treat them as an error
4148
4149                How to deal with errors:
4150
4151                              * CLASSLOAD_PANIC....abort execution with an error message
4152                    CLASSLOAD_NOPANIC..return NULL on error
4153
4154 *******************************************************************************/
4155
4156 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
4157                                                                  char **next, int mode)
4158 {
4159         char *start = utf_ptr;
4160         bool error = false;
4161         utf *name;
4162
4163         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
4164
4165         if (mode & CLASSLOAD_CHECKEND)
4166                 error |= (utf_ptr != end_ptr);
4167         
4168         if (!error) {
4169                 if (next) *next = utf_ptr;
4170                 
4171                 switch (*start) {
4172                   case 'V':
4173                           if (mode & CLASSLOAD_NOVOID)
4174                                   break;
4175                           /* FALLTHROUGH! */
4176                   case 'I':
4177                   case 'J':
4178                   case 'F':
4179                   case 'D':
4180                   case 'B':
4181                   case 'C':
4182                   case 'S':
4183                   case 'Z':
4184                           return (mode & CLASSLOAD_NULLPRIMITIVE)
4185                                   ? NULL
4186                                   : class_primitive_from_sig(*start);
4187                           
4188                   case 'L':
4189                           start++;
4190                           utf_ptr--;
4191                           /* FALLTHROUGH! */
4192                   case '[':
4193                           if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
4194                           name = utf_new(start, utf_ptr - start);
4195                           if (opt_eager) {
4196                                   classinfo *tc;
4197
4198                                   tc = class_new_intern(name);
4199                                   class_load(tc);
4200                                   list_addfirst(&unlinkedclasses, tc);
4201
4202                                   return tc;
4203
4204                           } else {
4205                                   return (mode & CLASSLOAD_LOAD)
4206                                           ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
4207                           }
4208                 }
4209         }
4210
4211         /* An error occurred */
4212         if (mode & CLASSLOAD_NOPANIC)
4213                 return NULL;
4214
4215         log_plain("Invalid descriptor at beginning of '");
4216         log_plain_utf(utf_new(start, end_ptr - start));
4217         log_plain("'");
4218         log_nl();
4219                                                   
4220         panic("Invalid descriptor");
4221
4222         /* keep compiler happy */
4223         return NULL;
4224 }
4225
4226
4227 /******************* function: type_from_descriptor ****************************
4228
4229     return the basic type indicated by the given descriptor
4230
4231     This function parses a descriptor and returns its basic type as
4232     TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
4233
4234     cls...if non-NULL the referenced variable is set to the classinfo *
4235           returned by class_from_descriptor.
4236
4237     For documentation of the arguments utf_ptr, end_ptr, next and mode
4238     see class_from_descriptor. The only difference is that
4239     type_from_descriptor always uses CLASSLOAD_PANIC.
4240
4241 ********************************************************************************/
4242
4243 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
4244                                                  char **next, int mode)
4245 {
4246         classinfo *mycls;
4247         if (!cls) cls = &mycls;
4248         *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
4249         switch (*utf_ptr) {
4250           case 'B': 
4251           case 'C':
4252           case 'I':
4253           case 'S':  
4254           case 'Z':
4255                   return TYPE_INT;
4256           case 'D':
4257                   return TYPE_DOUBLE;
4258           case 'F':
4259                   return TYPE_FLOAT;
4260           case 'J':
4261                   return TYPE_LONG;
4262           case 'V':
4263                   return TYPE_VOID;
4264         }
4265         return TYPE_ADDRESS;
4266 }
4267
4268
4269 /*************** function: create_pseudo_classes *******************************
4270
4271         create pseudo classes used by the typechecker
4272
4273 ********************************************************************************/
4274
4275 static void create_pseudo_classes()
4276 {
4277     /* pseudo class for Arraystubs (extends java.lang.Object) */
4278     
4279     pseudo_class_Arraystub = class_new_intern(utf_new_char("$ARRAYSTUB$"));
4280         pseudo_class_Arraystub->loaded = true;
4281     pseudo_class_Arraystub->super = class_java_lang_Object;
4282     pseudo_class_Arraystub->interfacescount = 2;
4283     pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
4284     pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
4285     pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
4286
4287     class_link(pseudo_class_Arraystub);
4288
4289         pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
4290
4291     /* pseudo class representing the null type */
4292     
4293         pseudo_class_Null = class_new_intern(utf_new_char("$NULL$"));
4294         pseudo_class_Null->loaded = true;
4295     pseudo_class_Null->super = class_java_lang_Object;
4296         class_link(pseudo_class_Null);  
4297
4298     /* pseudo class representing new uninitialized objects */
4299     
4300         pseudo_class_New = class_new_intern(utf_new_char("$NEW$"));
4301         pseudo_class_New->loaded = true;
4302         pseudo_class_New->linked = true;
4303         pseudo_class_New->super = class_java_lang_Object;
4304 /*      class_link(pseudo_class_New); */
4305 }
4306
4307
4308 /********************** Function: loader_init **********************************
4309
4310         Initializes all lists and loads all classes required for the system or the
4311         compiler.
4312
4313 *******************************************************************************/
4314  
4315 void loader_init(u1 *stackbottom)
4316 {
4317         interfaceindex = 0;
4318         
4319         /* create utf-symbols for pointer comparison of frequently used strings */
4320         utf_innerclasses    = utf_new_char("InnerClasses");
4321         utf_constantvalue   = utf_new_char("ConstantValue");
4322         utf_code            = utf_new_char("Code");
4323         utf_exceptions      = utf_new_char("Exceptions");
4324         utf_linenumbertable = utf_new_char("LineNumberTable");
4325         utf_sourcefile      = utf_new_char("SourceFile");
4326         utf_finalize        = utf_new_char("finalize");
4327         utf_fidesc              = utf_new_char("()V");
4328         utf_init                = utf_new_char("<init>");
4329         utf_clinit              = utf_new_char("<clinit>");
4330         utf_initsystemclass = utf_new_char("initializeSystemClass");
4331         utf_systemclass     = utf_new_char("java/lang/System");
4332         utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
4333         utf_initialize      = utf_new_char("initialize");
4334         utf_initializedesc  = utf_new_char("(I)V");
4335         utf_vmclass         = utf_new_char("java/lang/VMClass");
4336         utf_java_lang_Object= utf_new_char("java/lang/Object");
4337         array_packagename   = utf_new_char("<the array package>");
4338         utf_fillInStackTrace_name = utf_new_char("fillInStackTrace");
4339         utf_fillInStackTrace_desc = utf_new_char("()Ljava/lang/Throwable;");
4340
4341         /* create some important classes */
4342         /* These classes have to be created now because the classinfo
4343          * pointers are used in the loading code.
4344          */
4345         class_java_lang_Object =
4346                 class_new_intern(utf_java_lang_Object);
4347         class_load(class_java_lang_Object);
4348         class_link(class_java_lang_Object);
4349
4350         class_java_lang_String =
4351                 class_new_intern(utf_new_char("java/lang/String"));
4352         class_load(class_java_lang_String);
4353         class_link(class_java_lang_String);
4354
4355         class_java_lang_Cloneable =
4356                 class_new_intern(utf_new_char("java/lang/Cloneable"));
4357         class_load(class_java_lang_Cloneable);
4358         class_link(class_java_lang_Cloneable);
4359
4360         class_java_io_Serializable =
4361                 class_new_intern(utf_new_char("java/io/Serializable"));
4362         class_load(class_java_io_Serializable);
4363         class_link(class_java_io_Serializable);
4364
4365         /* create classes representing primitive types */
4366         create_primitive_classes();
4367
4368         /* create classes used by the typechecker */
4369         create_pseudo_classes();
4370
4371         /* correct vftbl-entries (retarded loading of class java/lang/String) */
4372         stringtable_update();
4373
4374 #if defined(USE_THREADS)
4375         if (stackbottom != 0)
4376                 initLocks();
4377 #endif
4378 }
4379
4380
4381 static void loader_compute_class_values(classinfo *c)
4382 {
4383         classinfo *subs;
4384
4385         c->vftbl->baseval = ++classvalue;
4386
4387         subs = c->sub;
4388         while (subs != NULL) {
4389                 loader_compute_class_values(subs);
4390                 subs = subs->nextsub;
4391         }
4392
4393         c->vftbl->diffval = classvalue - c->vftbl->baseval;
4394 }
4395
4396
4397 void loader_compute_subclasses(classinfo *c)
4398 {
4399 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4400         intsDisable();
4401 #endif
4402
4403         if (!(c->flags & ACC_INTERFACE)) {
4404                 c->nextsub = 0;
4405                 c->sub = 0;
4406         }
4407
4408         if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4409                 c->nextsub = c->super->sub;
4410                 c->super->sub = c;
4411         }
4412
4413         classvalue = 0;
4414
4415         /* this is the java.lang.Object special case */
4416         if (!class_java_lang_Object) {
4417                 loader_compute_class_values(c);
4418
4419         } else {
4420                 loader_compute_class_values(class_java_lang_Object);
4421         }
4422
4423 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4424         intsRestore();
4425 #endif
4426 }
4427
4428
4429 /******************** Function: loader_close ***********************************
4430
4431         Frees all resources
4432         
4433 *******************************************************************************/
4434
4435 void loader_close()
4436 {
4437         classinfo *c;
4438         s4 slot;
4439
4440         for (slot = 0; slot < class_hash.size; slot++) {
4441                 c = class_hash.ptr[slot];
4442
4443                 while (c) {
4444                         class_free(c);
4445                         c = c->hashlink;
4446                 }
4447         }
4448 }
4449
4450
4451 /*
4452  * These are local overrides for various environment variables in Emacs.
4453  * Please do not remove this and leave it at the end of the file, where
4454  * Emacs will automagically detect them.
4455  * ---------------------------------------------------------------------
4456  * Local variables:
4457  * mode: c
4458  * indent-tabs-mode: t
4459  * c-basic-offset: 4
4460  * tab-width: 4
4461  * End:
4462  */