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