classinfo: changed type of super and interfaces to classref_or_classinfo
[cacao.git] / src / vm / loader.c
1 /* src/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 2186 2005-04-02 00:43:25Z edwin $
36
37 */
38
39
40 #include <stdlib.h>
41 #include <string.h>
42 #include <assert.h>
43 #include <sys/stat.h>
44
45 #include "config.h"
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "native/include/java_lang_Throwable.h"
49
50 #if defined(USE_THREADS)
51 # if defined(NATIVE_THREADS)
52 #  include "threads/native/threads.h"
53 # else
54 #  include "threads/green/threads.h"
55 #  include "threads/green/locks.h"
56 # endif
57 #endif
58
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
61 #include "vm/exceptions.h"
62 #include "vm/builtin.h"
63 #include "vm/global.h"
64 #include "vm/linker.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/statistics.h"
68 #include "vm/stringlocal.h"
69 #include "vm/tables.h"
70
71 #if defined(USE_ZLIB)
72 # include "vm/unzip.h"
73 #endif
74
75 #include "vm/jit/asmpart.h"
76 #include "vm/jit/codegen.inc.h"
77
78
79 #undef JOWENN_DEBUG
80 #undef JOWENN_DEBUG1
81 #undef JOWENN_DEBUG2
82
83
84 /********************************************************************
85    list of classpath entries (either filesystem directories or 
86    ZIP/JAR archives
87 ********************************************************************/
88
89 classpath_info *classpath_entries = NULL;
90
91 /* loader_init *****************************************************************
92
93    Initializes all lists and loads all classes required for the system
94    or the compiler.
95
96 *******************************************************************************/
97  
98 bool loader_init(u1 *stackbottom)
99 {
100         classpath_info *cpi;
101
102 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
103         /* Initialize the monitor pointer for zip/jar file locking.               */
104
105         for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
106                 if (cpi->type == CLASSPATH_ARCHIVE)
107                         initObjectLock(&cpi->header);
108         }
109 #endif
110
111         /* load some important classes */
112
113         if (!load_class_bootstrap(class_java_lang_Object))
114                 return false;
115
116         if (!load_class_bootstrap(class_java_lang_String))
117                 return false;
118
119         if (!load_class_bootstrap(class_java_lang_Cloneable))
120                 return false;
121
122         if (!load_class_bootstrap(class_java_io_Serializable))
123                 return false;
124
125
126         /* load classes for wrapping primitive types */
127
128         if (!load_class_bootstrap(class_java_lang_Void))
129                 return false;
130
131         if (!load_class_bootstrap(class_java_lang_Boolean))
132                 return false;
133
134         if (!load_class_bootstrap(class_java_lang_Byte))
135                 return false;
136
137         if (!load_class_bootstrap(class_java_lang_Character))
138                 return false;
139
140         if (!load_class_bootstrap(class_java_lang_Short))
141                 return false;
142
143         if (!load_class_bootstrap(class_java_lang_Integer))
144                 return false;
145
146         if (!load_class_bootstrap(class_java_lang_Long))
147                 return false;
148
149         if (!load_class_bootstrap(class_java_lang_Float))
150                 return false;
151
152         if (!load_class_bootstrap(class_java_lang_Double))
153                 return false;
154
155
156 #if defined(USE_THREADS)
157         if (stackbottom != 0)
158                 initLocks();
159 #endif
160
161         return true;
162 }
163
164
165 /************* functions for reading classdata *********************************
166
167     getting classdata in blocks of variable size
168     (8,16,32,64-bit integer or float)
169
170 *******************************************************************************/
171
172 /* check_classbuffer_size ******************************************************
173
174    assert that at least <len> bytes are left to read
175    <len> is limited to the range of non-negative s4 values
176
177 *******************************************************************************/
178
179 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
180 {
181         if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
182                 *exceptionptr =
183                         new_classformaterror((cb)->class, "Truncated class file");
184
185                 return false;
186         }
187
188         return true;
189 }
190
191
192 /* suck_nbytes *****************************************************************
193
194    transfer block of classfile data into a buffer
195
196 *******************************************************************************/
197
198 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
199 {
200         memcpy(buffer, cb->pos + 1, len);
201         cb->pos += len;
202 }
203
204
205 /* skip_nbytes ****************************************************************
206
207    skip block of classfile data
208
209 *******************************************************************************/
210
211 inline void skip_nbytes(classbuffer *cb, s4 len)
212 {
213         cb->pos += len;
214 }
215
216
217 inline u1 suck_u1(classbuffer *cb)
218 {
219         return *++(cb->pos);
220 }
221
222
223 inline u2 suck_u2(classbuffer *cb)
224 {
225         u1 a = suck_u1(cb);
226         u1 b = suck_u1(cb);
227         return ((u2) a << 8) + (u2) b;
228 }
229
230
231 inline u4 suck_u4(classbuffer *cb)
232 {
233         u1 a = suck_u1(cb);
234         u1 b = suck_u1(cb);
235         u1 c = suck_u1(cb);
236         u1 d = suck_u1(cb);
237         return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
238 }
239
240
241 /* get u8 from classfile data */
242 static u8 suck_u8(classbuffer *cb)
243 {
244 #if U8_AVAILABLE
245         u8 lo, hi;
246         hi = suck_u4(cb);
247         lo = suck_u4(cb);
248         return (hi << 32) + lo;
249 #else
250         u8 v;
251         v.high = suck_u4(cb);
252         v.low = suck_u4(cb);
253         return v;
254 #endif
255 }
256
257
258 /* get float from classfile data */
259 static float suck_float(classbuffer *cb)
260 {
261         float f;
262
263 #if !WORDS_BIGENDIAN 
264         u1 buffer[4];
265         u2 i;
266
267         for (i = 0; i < 4; i++)
268                 buffer[3 - i] = suck_u1(cb);
269
270         memcpy((u1*) (&f), buffer, 4);
271 #else
272         suck_nbytes((u1*) (&f), cb, 4);
273 #endif
274
275         if (sizeof(float) != 4) {
276                 *exceptionptr = new_exception_message(string_java_lang_InternalError,
277                                                                                           "Incompatible float-format");
278
279                 /* XXX should we exit in such a case? */
280                 throw_exception_exit();
281         }
282         
283         return f;
284 }
285
286
287 /* get double from classfile data */
288 static double suck_double(classbuffer *cb)
289 {
290         double d;
291
292 #if !WORDS_BIGENDIAN 
293         u1 buffer[8];
294         u2 i;   
295
296         for (i = 0; i < 8; i++)
297                 buffer[7 - i] = suck_u1(cb);
298
299         memcpy((u1*) (&d), buffer, 8);
300 #else 
301         suck_nbytes((u1*) (&d), cb, 8);
302 #endif
303
304         if (sizeof(double) != 8) {
305                 *exceptionptr = new_exception_message(string_java_lang_InternalError,
306                                                                                           "Incompatible double-format");
307
308                 /* XXX should we exit in such a case? */
309                 throw_exception_exit();
310         }
311         
312         return d;
313 }
314
315
316 /************************** function suck_init *********************************
317
318         called once at startup, sets the searchpath for the classfiles
319
320 *******************************************************************************/
321
322 void suck_init(char *classpath)
323 {
324         char           *start;
325         char           *end;
326         char           *filename;
327         s4              filenamelen;
328         bool            is_zip;
329         classpath_info *cpi;
330         classpath_info *lastcpi;
331         char           *cwd;
332         s4              cwdlen;
333
334         /* search for last classpath entry (only if there already some) */
335
336         if ((lastcpi = classpath_entries)) {
337                 while (lastcpi->next)
338                         lastcpi = lastcpi->next;
339         }
340
341         for (start = classpath; (*start) != '\0';) {
342
343                 /* search for ':' delimiter to get the end of the current entry */
344                 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
345
346                 if (start != end) {
347                         is_zip = false;
348                         filenamelen = end - start;
349
350                         if (filenamelen > 3) {
351                                 if (strncasecmp(end - 3, "zip", 3) == 0 ||
352                                         strncasecmp(end - 3, "jar", 3) == 0) {
353                                         is_zip = true;
354                                 }
355                         }
356
357                         /* save classpath entries as absolute pathnames */
358
359                         cwd = NULL;
360                         cwdlen = 0;
361
362                         if (*start != '/') {                      /* XXX fix me for win32 */
363                                 cwd = _Jv_getcwd();
364                                 cwdlen = strlen(cwd) + strlen("/");
365                         }
366
367                         /* allocate memory for filename and fill it */
368
369                         filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
370                                                         strlen("0"));
371
372                         if (cwd) {
373                                 strcpy(filename, cwd);
374                                 strcat(filename, "/");
375                                 strncat(filename, start, filenamelen);
376
377                                 /* add cwd length to file length */
378                                 filenamelen += cwdlen;
379
380                         } else {
381                                 strncpy(filename, start, filenamelen);
382                                 filename[filenamelen] = '\0';
383                         }
384
385                         cpi = NULL;
386
387                         if (is_zip) {
388 #if defined(USE_ZLIB)
389                                 unzFile uf = unzOpen(filename);
390
391                                 if (uf) {
392                                         cpi = NEW(classpath_info);
393                                         cpi->type = CLASSPATH_ARCHIVE;
394                                         cpi->uf = uf;
395                                         cpi->next = NULL;
396                                         cpi->path = filename;
397                                         cpi->pathlen = filenamelen;
398                                 }
399
400 #else
401                                 throw_cacao_exception_exit(string_java_lang_InternalError,
402                                                                                    "zip/jar files not supported");
403 #endif
404                                 
405                         } else {
406                                 cpi = NEW(classpath_info);
407                                 cpi->type = CLASSPATH_PATH;
408                                 cpi->next = NULL;
409
410                                 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
411                                         filename[filenamelen] = '/';
412                                         filename[filenamelen + 1] = '\0';
413                                         filenamelen++;
414                                 }
415
416                                 cpi->path = filename;
417                                 cpi->pathlen = filenamelen;
418                         }
419
420                         /* attach current classpath entry */
421
422                         if (cpi) {
423                                 if (!classpath_entries)
424                                         classpath_entries = cpi;
425                                 else
426                                         lastcpi->next = cpi;
427
428                                 lastcpi = cpi;
429                         }
430                 }
431
432                 /* goto next classpath entry, skip ':' delimiter */
433
434                 if ((*end) == ':') {
435                         start = end + 1;
436
437                 } else {
438                         start = end;
439                 }
440         }
441 }
442
443
444 void create_all_classes()
445 {
446         classpath_info *cpi;
447
448         for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
449 #if defined(USE_ZLIB)
450                 if (cpi->type == CLASSPATH_ARCHIVE) {
451                         cacao_entry_s *ce;
452                         unz_s *s;
453
454                         s = (unz_s *) cpi->uf;
455                         ce = s->cacao_dir_list;
456                                 
457                         while (ce) {
458                                 (void) class_new(ce->name);
459                                 ce = ce->next;
460                         }
461
462                 } else {
463 #endif
464 #if defined(USE_ZLIB)
465                 }
466 #endif
467         }
468 }
469
470
471 /* suck_start ******************************************************************
472
473    Returns true if classbuffer is already loaded or a file for the
474    specified class has succussfully been read in. All directories of
475    the searchpath are used to find the classfile (<classname>.class).
476    Returns false if no classfile is found and writes an error message.
477         
478 *******************************************************************************/
479
480 classbuffer *suck_start(classinfo *c)
481 {
482         classpath_info *cpi;
483         char           *filename;
484         s4             filenamelen;
485         char *path;
486         FILE *classfile;
487         bool found;
488         s4 len;
489         struct stat buffer;
490         classbuffer *cb;
491
492         /* initialize return value */
493
494         found = false;
495         cb = NULL;
496
497         filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
498         filename = MNEW(char, filenamelen);
499
500         utf_sprint(filename, c->name);
501         strcat(filename, ".class");
502
503         /* walk through all classpath entries */
504
505         for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
506 #if defined(USE_ZLIB)
507                 if (cpi->type == CLASSPATH_ARCHIVE) {
508
509 #if defined(USE_THREADS)
510                         /* enter a monitor on zip/jar archives */
511
512                         builtin_monitorenter((java_objectheader *) cpi);
513 #endif
514
515                         if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
516                                 unz_file_info file_info;
517
518                                 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
519                                                                                   sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
520                                         if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
521                                                 cb = NEW(classbuffer);
522                                                 cb->class = c;
523                                                 cb->size = file_info.uncompressed_size;
524                                                 cb->data = MNEW(u1, cb->size);
525                                                 cb->pos = cb->data - 1;
526
527                                                 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
528
529                                                 if (len != cb->size) {
530                                                         suck_stop(cb);
531                                                         log_text("Error while unzipping");
532
533                                                 } else {
534                                                         found = true;
535                                                 }
536
537                                         } else {
538                                                 log_text("Error while opening file in archive");
539                                         }
540
541                                 } else {
542                                         log_text("Error while retrieving fileinfo");
543                                 }
544                         }
545                         unzCloseCurrentFile(cpi->uf);
546
547 #if defined(USE_THREADS)
548                         /* leave the monitor */
549
550                         builtin_monitorexit((java_objectheader *) cpi);
551 #endif
552
553                 } else {
554 #endif /* defined(USE_ZLIB) */
555                         
556                         path = MNEW(char, cpi->pathlen + filenamelen);
557                         strcpy(path, cpi->path);
558                         strcat(path, filename);
559
560                         classfile = fopen(path, "r");
561
562                         if (classfile) {                                   /* file exists */
563                                 if (!stat(path, &buffer)) {            /* read classfile data */
564                                         cb = NEW(classbuffer);
565                                         cb->class = c;
566                                         cb->size = buffer.st_size;
567                                         cb->data = MNEW(u1, cb->size);
568                                         cb->pos = cb->data - 1;
569
570                                         /* read class data */
571                                         len = fread(cb->data, 1, cb->size, classfile);
572
573                                         if (len != buffer.st_size) {
574                                                 suck_stop(cb);
575 /*                                              if (ferror(classfile)) { */
576 /*                                              } */
577
578                                         } else {
579                                                 found = true;
580                                         }
581                                 }
582                         }
583
584                         MFREE(path, char, cpi->pathlen + filenamelen);
585 #if defined(USE_ZLIB)
586                 }
587 #endif
588         }
589
590         if (opt_verbose)
591                 if (!found)
592                         dolog("Warning: Can not open class file '%s'", filename);
593
594         MFREE(filename, char, filenamelen);
595
596         return cb;
597 }
598
599
600 /************************** function suck_stop *********************************
601
602         frees memory for buffer with classfile data.
603         Caution: this function may only be called if buffer has been allocated
604                  by suck_start with reading a file
605         
606 *******************************************************************************/
607
608 void suck_stop(classbuffer *cb)
609 {
610         /* free memory */
611
612         MFREE(cb->data, u1, cb->size);
613         FREE(cb, classbuffer);
614 }
615
616
617 /******************************************************************************/
618 /******************* Some support functions ***********************************/
619 /******************************************************************************/
620
621 void fprintflags (FILE *fp, u2 f)
622 {
623    if ( f & ACC_PUBLIC )       fprintf (fp," PUBLIC");
624    if ( f & ACC_PRIVATE )      fprintf (fp," PRIVATE");
625    if ( f & ACC_PROTECTED )    fprintf (fp," PROTECTED");
626    if ( f & ACC_STATIC )       fprintf (fp," STATIC");
627    if ( f & ACC_FINAL )        fprintf (fp," FINAL");
628    if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
629    if ( f & ACC_VOLATILE )     fprintf (fp," VOLATILE");
630    if ( f & ACC_TRANSIENT )    fprintf (fp," TRANSIENT");
631    if ( f & ACC_NATIVE )       fprintf (fp," NATIVE");
632    if ( f & ACC_INTERFACE )    fprintf (fp," INTERFACE");
633    if ( f & ACC_ABSTRACT )     fprintf (fp," ABSTRACT");
634 }
635
636
637 /********** internal function: printflags  (only for debugging) ***************/
638
639 void printflags(u2 f)
640 {
641         fprintflags(stdout,f);
642 }
643
644
645 /********************** Function: skipattributebody ****************************
646
647         skips an attribute after the 16 bit reference to attribute_name has already
648         been read
649         
650 *******************************************************************************/
651
652 static bool skipattributebody(classbuffer *cb)
653 {
654         u4 len;
655
656         if (!check_classbuffer_size(cb, 4))
657                 return false;
658
659         len = suck_u4(cb);
660
661         if (!check_classbuffer_size(cb, len))
662                 return false;
663
664         skip_nbytes(cb, len);
665
666         return true;
667 }
668
669
670 /************************* Function: skipattributes ****************************
671
672         skips num attribute structures
673         
674 *******************************************************************************/
675
676 static bool skipattributes(classbuffer *cb, u4 num)
677 {
678         u4 i;
679         u4 len;
680
681         for (i = 0; i < num; i++) {
682                 if (!check_classbuffer_size(cb, 2 + 4))
683                         return false;
684
685                 suck_u2(cb);
686                 len = suck_u4(cb);
687
688                 if (!check_classbuffer_size(cb, len))
689                         return false;
690
691                 skip_nbytes(cb, len);
692         }
693
694         return true;
695 }
696
697
698 /******************** function:: class_getconstant *****************************
699
700         retrieves the value at position 'pos' of the constantpool of a class
701         if the type of the value is other than 'ctype' the system is stopped
702
703 *******************************************************************************/
704
705 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
706 {
707         /* check index and type of constantpool entry */
708         /* (pos == 0 is caught by type comparison) */
709         if (pos >= c->cpcount || c->cptags[pos] != ctype) {
710                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
711                 return NULL;
712         }
713
714         return c->cpinfos[pos];
715 }
716
717
718 /******************** function: innerclass_getconstant ************************
719
720     like class_getconstant, but if cptags is ZERO null is returned
721         
722 *******************************************************************************/
723
724 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
725 {
726         /* invalid position in constantpool */
727         if (pos >= c->cpcount) {
728                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
729                 return NULL;
730         }
731
732         /* constantpool entry of type 0 */      
733         if (!c->cptags[pos])
734                 return NULL;
735
736         /* check type of constantpool entry */
737         if (c->cptags[pos] != ctype) {
738                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
739                 return NULL;
740         }
741                 
742         return c->cpinfos[pos];
743 }
744
745
746 /********************* Function: class_constanttype ****************************
747
748         Determines the type of a class entry in the ConstantPool
749         
750 *******************************************************************************/
751
752 u4 class_constanttype(classinfo *c, u4 pos)
753 {
754         if (pos <= 0 || pos >= c->cpcount) {
755                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
756                 return 0;
757         }
758
759         return c->cptags[pos];
760 }
761
762
763 /* load_constantpool ***********************************************************
764
765    Loads the constantpool of a class, the entries are transformed into
766    a simpler format by resolving references (a detailed overview of
767    the compact structures can be found in global.h).
768
769 *******************************************************************************/
770
771 static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
772 {
773
774         /* The following structures are used to save information which cannot be 
775            processed during the first pass. After the complete constantpool has 
776            been traversed the references can be resolved. 
777            (only in specific order)                                                */
778         
779         /* CONSTANT_Class entries */
780         typedef struct forward_class {
781                 struct forward_class *next;
782                 u2 thisindex;
783                 u2 name_index;
784         } forward_class;
785
786         /* CONSTANT_String */
787         typedef struct forward_string {
788                 struct forward_string *next;
789                 u2 thisindex;
790                 u2 string_index;
791         } forward_string;
792
793         /* CONSTANT_NameAndType */
794         typedef struct forward_nameandtype {
795                 struct forward_nameandtype *next;
796                 u2 thisindex;
797                 u2 name_index;
798                 u2 sig_index;
799         } forward_nameandtype;
800
801         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
802         typedef struct forward_fieldmethint {
803                 struct forward_fieldmethint *next;
804                 u2 thisindex;
805                 u1 tag;
806                 u2 class_index;
807                 u2 nameandtype_index;
808         } forward_fieldmethint;
809
810
811         classinfo *c;
812         u4 idx;
813
814         forward_class *forward_classes = NULL;
815         forward_string *forward_strings = NULL;
816         forward_nameandtype *forward_nameandtypes = NULL;
817         forward_fieldmethint *forward_fieldmethints = NULL;
818
819         forward_class *nfc;
820         forward_string *nfs;
821         forward_nameandtype *nfn;
822         forward_fieldmethint *nff;
823
824         u4 cpcount;
825         u1 *cptags;
826         voidptr *cpinfos;
827
828         c = cb->class;
829
830         /* number of entries in the constant_pool table plus one */
831         if (!check_classbuffer_size(cb, 2))
832                 return false;
833
834         cpcount = c->cpcount = suck_u2(cb);
835
836         /* allocate memory */
837         cptags  = c->cptags  = MNEW(u1, cpcount);
838         cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
839
840         if (cpcount < 1) {
841                 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
842                 return false;
843         }
844         
845 #if defined(STATISTICS)
846         if (opt_stat)
847                 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
848 #endif
849         
850         /* initialize constantpool */
851         for (idx = 0; idx < cpcount; idx++) {
852                 cptags[idx] = CONSTANT_UNUSED;
853                 cpinfos[idx] = NULL;
854         }
855
856                         
857         /******* first pass *******/
858         /* entries which cannot be resolved now are written into 
859            temporary structures and traversed again later        */
860                    
861         idx = 1;
862         while (idx < cpcount) {
863                 u4 t;
864
865                 /* get constant type */
866                 if (!check_classbuffer_size(cb, 1))
867                         return false;
868
869                 t = suck_u1(cb);
870
871                 switch (t) {
872                 case CONSTANT_Class:
873                         nfc = NEW(forward_class);
874
875                         nfc->next = forward_classes;
876                         forward_classes = nfc;
877
878                         nfc->thisindex = idx;
879                         /* reference to CONSTANT_NameAndType */
880                         if (!check_classbuffer_size(cb, 2))
881                                 return false;
882
883                         nfc->name_index = suck_u2(cb);
884
885                         idx++;
886                         break;
887                         
888                 case CONSTANT_String:
889                         nfs = NEW(forward_string);
890                                 
891                         nfs->next = forward_strings;
892                         forward_strings = nfs;
893                                 
894                         nfs->thisindex = idx;
895
896                         /* reference to CONSTANT_Utf8_info with string characters */
897                         if (!check_classbuffer_size(cb, 2))
898                                 return false;
899
900                         nfs->string_index = suck_u2(cb);
901                                 
902                         idx++;
903                         break;
904
905                 case CONSTANT_NameAndType:
906                         nfn = NEW(forward_nameandtype);
907                                 
908                         nfn->next = forward_nameandtypes;
909                         forward_nameandtypes = nfn;
910                                 
911                         nfn->thisindex = idx;
912
913                         if (!check_classbuffer_size(cb, 2 + 2))
914                                 return false;
915
916                         /* reference to CONSTANT_Utf8_info containing simple name */
917                         nfn->name_index = suck_u2(cb);
918
919                         /* reference to CONSTANT_Utf8_info containing field or method
920                            descriptor */
921                         nfn->sig_index = suck_u2(cb);
922                                 
923                         idx++;
924                         break;
925
926                 case CONSTANT_Fieldref:
927                 case CONSTANT_Methodref:
928                 case CONSTANT_InterfaceMethodref:
929                         nff = NEW(forward_fieldmethint);
930                         
931                         nff->next = forward_fieldmethints;
932                         forward_fieldmethints = nff;
933
934                         nff->thisindex = idx;
935                         /* constant type */
936                         nff->tag = t;
937
938                         if (!check_classbuffer_size(cb, 2 + 2))
939                                 return false;
940
941                         /* class or interface type that contains the declaration of the
942                            field or method */
943                         nff->class_index = suck_u2(cb);
944
945                         /* name and descriptor of the field or method */
946                         nff->nameandtype_index = suck_u2(cb);
947
948                         idx++;
949                         break;
950                                 
951                 case CONSTANT_Integer: {
952                         constant_integer *ci = NEW(constant_integer);
953
954 #if defined(STATISTICS)
955                         if (opt_stat)
956                                 count_const_pool_len += sizeof(constant_integer);
957 #endif
958
959                         if (!check_classbuffer_size(cb, 4))
960                                 return false;
961
962                         ci->value = suck_s4(cb);
963                         cptags[idx] = CONSTANT_Integer;
964                         cpinfos[idx] = ci;
965
966                         idx++;
967                         break;
968                 }
969                                 
970                 case CONSTANT_Float: {
971                         constant_float *cf = NEW(constant_float);
972
973 #if defined(STATISTICS)
974                         if (opt_stat)
975                                 count_const_pool_len += sizeof(constant_float);
976 #endif
977
978                         if (!check_classbuffer_size(cb, 4))
979                                 return false;
980
981                         cf->value = suck_float(cb);
982                         cptags[idx] = CONSTANT_Float;
983                         cpinfos[idx] = cf;
984
985                         idx++;
986                         break;
987                 }
988                                 
989                 case CONSTANT_Long: {
990                         constant_long *cl = NEW(constant_long);
991                                         
992 #if defined(STATISTICS)
993                         if (opt_stat)
994                                 count_const_pool_len += sizeof(constant_long);
995 #endif
996
997                         if (!check_classbuffer_size(cb, 8))
998                                 return false;
999
1000                         cl->value = suck_s8(cb);
1001                         cptags[idx] = CONSTANT_Long;
1002                         cpinfos[idx] = cl;
1003                         idx += 2;
1004                         if (idx > cpcount) {
1005                                 *exceptionptr =
1006                                         new_classformaterror(c, "Invalid constant pool entry");
1007                                 return false;
1008                         }
1009                         break;
1010                 }
1011                         
1012                 case CONSTANT_Double: {
1013                         constant_double *cd = NEW(constant_double);
1014                                 
1015 #if defined(STATISTICS)
1016                         if (opt_stat)
1017                                 count_const_pool_len += sizeof(constant_double);
1018 #endif
1019
1020                         if (!check_classbuffer_size(cb, 8))
1021                                 return false;
1022
1023                         cd->value = suck_double(cb);
1024                         cptags[idx] = CONSTANT_Double;
1025                         cpinfos[idx] = cd;
1026                         idx += 2;
1027                         if (idx > cpcount) {
1028                                 *exceptionptr =
1029                                         new_classformaterror(c, "Invalid constant pool entry");
1030                                 return false;
1031                         }
1032                         break;
1033                 }
1034                                 
1035                 case CONSTANT_Utf8: { 
1036                         u4 length;
1037
1038                         /* number of bytes in the bytes array (not string-length) */
1039                         if (!check_classbuffer_size(cb, 2))
1040                                 return false;
1041
1042                         length = suck_u2(cb);
1043                         cptags[idx] = CONSTANT_Utf8;
1044
1045                         /* validate the string */
1046                         if (!check_classbuffer_size(cb, length))
1047                                 return false;
1048
1049                         if (opt_verify &&
1050                                 !is_valid_utf((char *) (cb->pos + 1),
1051                                                           (char *) (cb->pos + 1 + length))) {
1052                                 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1053                                 panic("Invalid UTF-8 string");
1054                         }
1055                         /* insert utf-string into the utf-symboltable */
1056                         cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1057
1058                         /* skip bytes of the string (buffer size check above) */
1059                         skip_nbytes(cb, length);
1060                         idx++;
1061                         break;
1062                 }
1063                                                                                 
1064                 default:
1065                         *exceptionptr =
1066                                 new_classformaterror(c, "Illegal constant pool type");
1067                         return false;
1068                 }  /* end switch */
1069         } /* end while */
1070
1071         /* add all class references to the descriptor_pool */
1072         for (nfc=forward_classes; nfc; nfc=nfc->next) {
1073                 utf *name = class_getconstant(c,nfc->name_index,CONSTANT_Utf8);
1074                 if (!descriptor_pool_add_class(descpool,name))
1075                         return false;
1076         }
1077         /* add all descriptors in NameAndTypes to the descriptor_pool */
1078         for (nfn=forward_nameandtypes; nfn; nfn=nfn->next) {
1079                 utf *desc = class_getconstant(c,nfn->sig_index,CONSTANT_Utf8);
1080                 if (!descriptor_pool_add(descpool,desc,NULL))
1081                         return false;
1082         }
1083
1084         /* resolve entries in temporary structures */
1085
1086         while (forward_classes) {
1087                 utf *name =
1088                         class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1089
1090                 if (opt_verify && !is_valid_name_utf(name))
1091                         panic("Class reference with invalid name");
1092
1093                 cptags[forward_classes->thisindex] = CONSTANT_Class;
1094                 /* retrieve class from class-table */
1095                 if (opt_eager) {
1096                         classinfo *tc;
1097                         tc = class_new_intern(name);
1098
1099                         if (!load_class_from_classloader(tc, c->classloader))
1100                                 return false;
1101
1102                         /* link the class later, because we cannot link the class currently
1103                            loading */
1104                         list_addfirst(&unlinkedclasses, tc);
1105
1106                         cpinfos[forward_classes->thisindex] = tc;
1107
1108                 } else {
1109                         cpinfos[forward_classes->thisindex] = class_new(name);
1110                 }
1111
1112                 nfc = forward_classes;
1113                 forward_classes = forward_classes->next;
1114                 FREE(nfc, forward_class);
1115         }
1116
1117         while (forward_strings) {
1118                 utf *text =
1119                         class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1120
1121                 /* resolve utf-string */
1122                 cptags[forward_strings->thisindex] = CONSTANT_String;
1123                 cpinfos[forward_strings->thisindex] = text;
1124                 
1125                 nfs = forward_strings;
1126                 forward_strings = forward_strings->next;
1127                 FREE(nfs, forward_string);
1128         }
1129
1130         while (forward_nameandtypes) {
1131                 constant_nameandtype *cn = NEW(constant_nameandtype);   
1132
1133 #if defined(STATISTICS)
1134                 if (opt_stat)
1135                         count_const_pool_len += sizeof(constant_nameandtype);
1136 #endif
1137
1138                 /* resolve simple name and descriptor */
1139                 cn->name = class_getconstant(c,
1140                                                                          forward_nameandtypes->name_index,
1141                                                                          CONSTANT_Utf8);
1142
1143                 cn->descriptor = class_getconstant(c,
1144                                                                                    forward_nameandtypes->sig_index,
1145                                                                                    CONSTANT_Utf8);
1146
1147                 if (opt_verify) {
1148                         /* check name */
1149                         if (!is_valid_name_utf(cn->name)) {
1150                                 *exceptionptr =
1151                                         new_classformaterror(c,
1152                                                                                  "Illegal Field name \"%s\"",
1153                                                                                  cn->name->text);
1154
1155                                 return false;
1156                         }
1157
1158                         /* disallow referencing <clinit> among others */
1159                         if (cn->name->text[0] == '<' && cn->name != utf_init) {
1160                                 *exceptionptr =
1161                                         new_exception_utfmessage(string_java_lang_InternalError,
1162                                                                                          cn->name);
1163                                 return false;
1164                         }
1165                 }
1166
1167                 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1168                 cpinfos[forward_nameandtypes->thisindex] = cn;
1169
1170                 nfn = forward_nameandtypes;
1171                 forward_nameandtypes = forward_nameandtypes->next;
1172                 FREE(nfn, forward_nameandtype);
1173         }
1174
1175         while (forward_fieldmethints) {
1176                 constant_nameandtype *nat;
1177                 constant_FMIref *fmi = NEW(constant_FMIref);
1178
1179 #if defined(STATISTICS)
1180                 if (opt_stat)
1181                         count_const_pool_len += sizeof(constant_FMIref);
1182 #endif
1183                 /* resolve simple name and descriptor */
1184                 nat = class_getconstant(c,
1185                                                                 forward_fieldmethints->nameandtype_index,
1186                                                                 CONSTANT_NameAndType);
1187
1188                 fmi->class = class_getconstant(c,
1189                                                                            forward_fieldmethints->class_index,
1190                                                                            CONSTANT_Class);
1191                 fmi->name = nat->name;
1192                 fmi->descriptor = nat->descriptor;
1193
1194                 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1195                 cpinfos[forward_fieldmethints->thisindex] = fmi;
1196         
1197                 nff = forward_fieldmethints;
1198                 forward_fieldmethints = forward_fieldmethints->next;
1199                 FREE(nff, forward_fieldmethint);
1200         }
1201
1202         /* everything was ok */
1203
1204         return true;
1205 }
1206
1207
1208 /* load_field ******************************************************************
1209
1210    Load everything about a class field from the class file and fill a
1211    'fieldinfo' structure. For static fields, space in the data segment
1212    is allocated.
1213
1214 *******************************************************************************/
1215
1216 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
1217
1218 static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
1219 {
1220         classinfo *c;
1221         u4 attrnum, i;
1222         u4 jtype;
1223         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
1224         utf *u;
1225
1226         c = cb->class;
1227
1228         if (!check_classbuffer_size(cb, 2 + 2 + 2))
1229                 return false;
1230
1231         f->flags = suck_u2(cb);
1232
1233         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1234                 return false;
1235         f->name = u;
1236
1237         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1238                 return false;
1239         f->descriptor = u;
1240         f->parseddesc = NULL;
1241         if (!descriptor_pool_add(descpool,u,NULL))
1242                 return false;
1243
1244         if (opt_verify) {
1245                 /* check name */
1246                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1247                         *exceptionptr = new_classformaterror(c,
1248                                                                                                  "Illegal Field name \"%s\"",
1249                                                                                                  f->name->text);
1250                         return false;
1251                 }
1252
1253                 /* check flag consistency */
1254                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1255
1256                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1257                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1258                         *exceptionptr =
1259                                 new_classformaterror(c,
1260                                                                          "Illegal field modifiers: 0x%X",
1261                                                                          f->flags);
1262                         return false;
1263                 }
1264
1265                 if (c->flags & ACC_INTERFACE) {
1266                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1267                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1268                                 f->flags & ACC_TRANSIENT) {
1269                                 *exceptionptr =
1270                                         new_classformaterror(c,
1271                                                                                  "Illegal field modifiers: 0x%X",
1272                                                                                  f->flags);
1273                                 return false;
1274                         }
1275                 }
1276         }
1277                 
1278         f->type = jtype = desc_to_type(f->descriptor);    /* data type            */
1279         f->offset = 0;                             /* offset from start of object */
1280         f->class = c;
1281         f->xta = NULL;
1282         
1283         switch (f->type) {
1284         case TYPE_INT:     f->value.i = 0; break;
1285         case TYPE_FLOAT:   f->value.f = 0.0; break;
1286         case TYPE_DOUBLE:  f->value.d = 0.0; break;
1287         case TYPE_ADDRESS: f->value.a = NULL; break;
1288         case TYPE_LONG:
1289 #if U8_AVAILABLE
1290                 f->value.l = 0; break;
1291 #else
1292                 f->value.l.low = 0; f->value.l.high = 0; break;
1293 #endif
1294         }
1295
1296         /* read attributes */
1297         if (!check_classbuffer_size(cb, 2))
1298                 return false;
1299
1300         attrnum = suck_u2(cb);
1301         for (i = 0; i < attrnum; i++) {
1302                 if (!check_classbuffer_size(cb, 2))
1303                         return false;
1304
1305                 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1306                         return false;
1307
1308                 if (u == utf_ConstantValue) {
1309                         if (!check_classbuffer_size(cb, 4 + 2))
1310                                 return false;
1311
1312                         /* check attribute length */
1313                         if (suck_u4(cb) != 2) {
1314                                 *exceptionptr =
1315                                         new_classformaterror(c, "Wrong size for VALUE attribute");
1316                                 return false;
1317                         }
1318                         
1319                         /* constant value attribute */
1320                         if (pindex != field_load_NOVALUE) {
1321                                 *exceptionptr =
1322                                         new_classformaterror(c,
1323                                                                                  "Multiple ConstantValue attributes");
1324                                 return false;
1325                         }
1326                         
1327                         /* index of value in constantpool */            
1328                         pindex = suck_u2(cb);
1329                 
1330                         /* initialize field with value from constantpool */             
1331                         switch (jtype) {
1332                         case TYPE_INT: {
1333                                 constant_integer *ci; 
1334
1335                                 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1336                                         return false;
1337
1338                                 f->value.i = ci->value;
1339                         }
1340                         break;
1341                                         
1342                         case TYPE_LONG: {
1343                                 constant_long *cl; 
1344
1345                                 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1346                                         return false;
1347
1348                                 f->value.l = cl->value;
1349                         }
1350                         break;
1351
1352                         case TYPE_FLOAT: {
1353                                 constant_float *cf;
1354
1355                                 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1356                                         return false;
1357
1358                                 f->value.f = cf->value;
1359                         }
1360                         break;
1361                                                                                         
1362                         case TYPE_DOUBLE: {
1363                                 constant_double *cd;
1364
1365                                 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1366                                         return false;
1367
1368                                 f->value.d = cd->value;
1369                         }
1370                         break;
1371                                                 
1372                         case TYPE_ADDRESS:
1373                                 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1374                                         return false;
1375
1376                                 /* create javastring from compressed utf8-string */
1377                                 f->value.a = literalstring_new(u);
1378                                 break;
1379         
1380                         default: 
1381                                 log_text("Invalid Constant - Type");
1382                         }
1383
1384                 } else {
1385                         /* unknown attribute */
1386                         if (!skipattributebody(cb))
1387                                 return false;
1388                 }
1389         }
1390
1391         /* everything was ok */
1392
1393         return true;
1394 }
1395
1396
1397 /* load_method *****************************************************************
1398
1399    Loads a method from the class file and fills an existing
1400    'methodinfo' structure. For native methods, the function pointer
1401    field is set to the real function pointer, for JavaVM methods a
1402    pointer to the compiler is used preliminarily.
1403         
1404 *******************************************************************************/
1405
1406 static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool)
1407 {
1408         classinfo *c;
1409         int argcount;
1410         s4 i, j;
1411         u4 attrnum;
1412         u4 codeattrnum;
1413         utf *u;
1414
1415         c = cb->class;
1416
1417 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1418         initObjectLock(&m->header);
1419 #endif
1420
1421 #ifdef STATISTICS
1422         if (opt_stat)
1423                 count_all_methods++;
1424 #endif
1425
1426         m->thrownexceptionscount = 0;
1427         m->linenumbercount = 0;
1428         m->linenumbers = 0;
1429         m->class = c;
1430         m->nativelyoverloaded = false;
1431         
1432         if (!check_classbuffer_size(cb, 2 + 2 + 2))
1433                 return false;
1434
1435         m->flags = suck_u2(cb);
1436
1437         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1438                 return false;
1439         m->name = u;
1440
1441         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1442                 return false;
1443         m->descriptor = u;
1444         m->parseddesc = NULL;
1445         if (!descriptor_pool_add(descpool,u,&argcount))
1446                 return false;
1447
1448         if (opt_verify) {
1449                 if (!is_valid_name_utf(m->name))
1450                         panic("Method with invalid name");
1451
1452                 if (m->name->text[0] == '<'
1453                         && m->name != utf_init && m->name != utf_clinit)
1454                         panic("Method with invalid special name");
1455         }
1456         
1457         if (!(m->flags & ACC_STATIC))
1458                 argcount++; /* count the 'this' argument */
1459
1460         if (opt_verify) {
1461                 if (argcount > 255) {
1462                         *exceptionptr =
1463                                 new_classformaterror(c, "Too many arguments in signature");
1464                         return false;
1465                 }
1466
1467                 /* check flag consistency */
1468                 if (m->name != utf_clinit) {
1469                         i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1470
1471                         if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1472                                 *exceptionptr =
1473                                         new_classformaterror(c,
1474                                                                                  "Illegal method modifiers: 0x%X",
1475                                                                                  m->flags);
1476                                 return false;
1477                         }
1478
1479                         if (m->flags & ACC_ABSTRACT) {
1480                                 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1481                                                                  ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1482                                         *exceptionptr =
1483                                                 new_classformaterror(c,
1484                                                                                          "Illegal method modifiers: 0x%X",
1485                                                                                          m->flags);
1486                                         return false;
1487                                 }
1488                         }
1489
1490                         if (c->flags & ACC_INTERFACE) {
1491                                 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1492                                         *exceptionptr =
1493                                                 new_classformaterror(c,
1494                                                                                          "Illegal method modifiers: 0x%X",
1495                                                                                          m->flags);
1496                                         return false;
1497                                 }
1498                         }
1499
1500                         if (m->name == utf_init) {
1501                                 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1502                                                                 ACC_NATIVE | ACC_ABSTRACT))
1503                                         panic("Instance initialization method has invalid flags set");
1504                         }
1505                 }
1506         }
1507                 
1508         m->jcode = NULL;
1509         m->basicblockcount = 0;
1510         m->basicblocks = NULL;
1511         m->basicblockindex = NULL;
1512         m->instructioncount = 0;
1513         m->instructions = NULL;
1514         m->stackcount = 0;
1515         m->stack = NULL;
1516         m->exceptiontable = NULL;
1517         m->stubroutine = NULL;
1518         m->mcode = NULL;
1519         m->entrypoint = NULL;
1520         m->methodUsed = NOTUSED;    
1521         m->monoPoly = MONO;    
1522         m->subRedefs = 0;
1523         m->subRedefsUsed = 0;
1524
1525         m->xta = NULL;
1526
1527         if (!check_classbuffer_size(cb, 2))
1528                 return false;
1529         
1530         attrnum = suck_u2(cb);
1531         for (i = 0; i < attrnum; i++) {
1532                 utf *aname;
1533
1534                 if (!check_classbuffer_size(cb, 2))
1535                         return false;
1536
1537                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1538                         return false;
1539
1540                 if (aname == utf_Code) {
1541                         if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1542                                         *exceptionptr =
1543                                                 new_classformaterror(c,
1544                                                                                          "Code attribute in native or abstract methods");
1545
1546                                         return false;
1547                         }
1548                         
1549                         if (m->jcode) {
1550                                 *exceptionptr =
1551                                         new_classformaterror(c, "Multiple Code attributes");
1552
1553                                 return false;
1554                         }
1555
1556                         if (!check_classbuffer_size(cb, 4 + 2 + 2))
1557                                 return false;
1558
1559                         suck_u4(cb);
1560                         m->maxstack = suck_u2(cb);
1561                         m->maxlocals = suck_u2(cb);
1562
1563                         if (m->maxlocals < argcount) {
1564                                 *exceptionptr =
1565                                         new_classformaterror(c, "Arguments can't fit into locals");
1566
1567                                 return false;
1568                         }
1569                         
1570                         if (!check_classbuffer_size(cb, 4))
1571                                 return false;
1572
1573                         m->jcodelength = suck_u4(cb);
1574
1575                         if (m->jcodelength == 0) {
1576                                 *exceptionptr =
1577                                         new_classformaterror(c, "Code of a method has length 0");
1578
1579                                 return false;
1580                         }
1581                         
1582                         if (m->jcodelength > 65535) {
1583                                 *exceptionptr =
1584                                         new_classformaterror(c,
1585                                                                                  "Code of a method longer than 65535 bytes");
1586
1587                                 return false;
1588                         }
1589
1590                         if (!check_classbuffer_size(cb, m->jcodelength))
1591                                 return false;
1592
1593                         m->jcode = MNEW(u1, m->jcodelength);
1594                         suck_nbytes(m->jcode, cb, m->jcodelength);
1595
1596                         if (!check_classbuffer_size(cb, 2))
1597                                 return false;
1598
1599                         m->exceptiontablelength = suck_u2(cb);
1600                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1601                                 return false;
1602
1603                         m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1604
1605 #if defined(STATISTICS)
1606                         if (opt_stat) {
1607                                 count_vmcode_len += m->jcodelength + 18;
1608                                 count_extable_len += 8 * m->exceptiontablelength;
1609                         }
1610 #endif
1611
1612                         for (j = 0; j < m->exceptiontablelength; j++) {
1613                                 u4 idx;
1614                                 m->exceptiontable[j].startpc = suck_u2(cb);
1615                                 m->exceptiontable[j].endpc = suck_u2(cb);
1616                                 m->exceptiontable[j].handlerpc = suck_u2(cb);
1617
1618                                 idx = suck_u2(cb);
1619                                 if (!idx) {
1620                                         m->exceptiontable[j].catchtype = NULL;
1621
1622                                 } else {
1623                                         if (!(m->exceptiontable[j].catchtype =
1624                                                   class_getconstant(c, idx, CONSTANT_Class)))
1625                                                 return false;
1626                                 }
1627                         }
1628
1629                         if (!check_classbuffer_size(cb, 2))
1630                                 return false;
1631
1632                         codeattrnum = suck_u2(cb);
1633
1634                         for (; codeattrnum > 0; codeattrnum--) {
1635                                 utf *caname;
1636
1637                                 if (!check_classbuffer_size(cb, 2))
1638                                         return false;
1639
1640                                 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1641                                         return false;
1642
1643                                 if (caname == utf_LineNumberTable) {
1644                                         u2 lncid;
1645
1646                                         if (!check_classbuffer_size(cb, 4 + 2))
1647                                                 return false;
1648
1649                                         suck_u4(cb);
1650                                         m->linenumbercount = suck_u2(cb);
1651
1652                                         if (!check_classbuffer_size(cb,
1653                                                                                                 (2 + 2) * m->linenumbercount))
1654                                                 return false;
1655
1656                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1657                                         
1658                                         for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1659                                                 m->linenumbers[lncid].start_pc = suck_u2(cb);
1660                                                 m->linenumbers[lncid].line_number = suck_u2(cb);
1661                                         }
1662                                         codeattrnum--;
1663
1664                                         if (!skipattributes(cb, codeattrnum))
1665                                                 return false;
1666                                         
1667                                         break;
1668
1669                                 } else {
1670                                         if (!skipattributebody(cb))
1671                                                 return false;
1672                                 }
1673                         }
1674
1675                 } else if (aname == utf_Exceptions) {
1676                         s4 j;
1677
1678                         if (m->thrownexceptions) {
1679                                 *exceptionptr =
1680                                         new_classformaterror(c, "Multiple Exceptions attributes");
1681                                 return false;
1682                         }
1683
1684                         if (!check_classbuffer_size(cb, 4 + 2))
1685                                 return false;
1686
1687                         suck_u4(cb); /* length */
1688                         m->thrownexceptionscount = suck_u2(cb);
1689
1690                         if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1691                                 return false;
1692
1693                         m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
1694
1695                         for (j = 0; j < m->thrownexceptionscount; j++) {
1696                                 if (!((m->thrownexceptions)[j] =
1697                                           class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1698                                         return false;
1699                         }
1700                                 
1701                 } else {
1702                         if (!skipattributebody(cb))
1703                                 return false;
1704                 }
1705         }
1706
1707         if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1708                 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1709
1710                 return false;
1711         }
1712
1713         /* everything was ok */
1714
1715         return true;
1716 }
1717
1718
1719 /* load_attribute **************************************************************
1720
1721    Read attributes from classfile.
1722         
1723 *******************************************************************************/
1724
1725 static bool load_attributes(classbuffer *cb, u4 num)
1726 {
1727         classinfo *c;
1728         utf       *aname;
1729         u4 i, j;
1730
1731         c = cb->class;
1732
1733         for (i = 0; i < num; i++) {
1734                 /* retrieve attribute name */
1735                 if (!check_classbuffer_size(cb, 2))
1736                         return false;
1737
1738                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1739                         return false;
1740
1741                 if (aname == utf_InnerClasses) {
1742                         /* innerclasses attribute */
1743                         if (c->innerclass) {
1744                                 *exceptionptr =
1745                                         new_classformaterror(c, "Multiple InnerClasses attributes");
1746                                 return false;
1747                         }
1748                                 
1749                         if (!check_classbuffer_size(cb, 4 + 2))
1750                                 return false;
1751
1752                         /* skip attribute length */
1753                         suck_u4(cb);
1754
1755                         /* number of records */
1756                         c->innerclasscount = suck_u2(cb);
1757
1758                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1759                                 return false;
1760
1761                         /* allocate memory for innerclass structure */
1762                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1763
1764                         for (j = 0; j < c->innerclasscount; j++) {
1765                                 /* The innerclass structure contains a class with an encoded
1766                                    name, its defining scope, its simple name and a bitmask of
1767                                    the access flags. If an inner class is not a member, its
1768                                    outer_class is NULL, if a class is anonymous, its name is
1769                                    NULL. */
1770                                                                 
1771                                 innerclassinfo *info = c->innerclass + j;
1772
1773                                 info->inner_class =
1774                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1775                                 info->outer_class =
1776                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1777                                 info->name =
1778                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1779                                 info->flags = suck_u2(cb);
1780                         }
1781
1782                 } else if (aname == utf_SourceFile) {
1783                         if (!check_classbuffer_size(cb, 4 + 2))
1784                                 return false;
1785
1786                         if (suck_u4(cb) != 2) {
1787                                 *exceptionptr =
1788                                         new_classformaterror(c, "Wrong size for VALUE attribute");
1789                                 return false;
1790                         }
1791
1792                         if (c->sourcefile) {
1793                                 *exceptionptr =
1794                                         new_classformaterror(c, "Multiple SourceFile attributes");
1795                                 return false;
1796                         }
1797
1798                         if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1799                                 return false;
1800
1801                 } else {
1802                         /* unknown attribute */
1803                         if (!skipattributebody(cb))
1804                                 return false;
1805                 }
1806         }
1807
1808         return true;
1809 }
1810
1811
1812 /* load_class_from_classloader *************************************************
1813
1814    XXX
1815         
1816 *******************************************************************************/
1817
1818 classinfo *load_class_from_classloader(classinfo *c, java_objectheader *cl)
1819 {
1820         classinfo *r;
1821
1822         /* if other class loader than bootstrap, call it */
1823
1824         if (cl) {
1825                 methodinfo *lc;
1826
1827                 lc = class_resolveclassmethod(cl->vftbl->class,
1828                                                                           utf_loadClass,
1829                                                                           utf_java_lang_String__java_lang_Class,
1830                                                                           class_java_lang_Object,
1831                                                                           true);
1832
1833                 if (!lc)
1834                         return NULL;
1835
1836                 r = (classinfo *) asm_calljavafunction(lc,
1837                                                                                            cl,
1838                                                                                            javastring_new(c->name),
1839                                                                                            NULL, NULL);
1840
1841                 return r;
1842
1843         } else {
1844                 return load_class_bootstrap(c);
1845         }
1846 }
1847
1848
1849 /* load_class_bootstrap ********************************************************
1850         
1851    XXX
1852
1853 *******************************************************************************/
1854
1855 classinfo *load_class_bootstrap(classinfo *c)
1856 {
1857         classbuffer *cb;
1858         classinfo *r;
1859
1860 #if defined(USE_THREADS)
1861         /* enter a monitor on the class */
1862
1863         builtin_monitorenter((java_objectheader *) c);
1864 #endif
1865
1866         /* maybe the class is already loaded */
1867
1868         if (c->loaded) {
1869 #if defined(USE_THREADS)
1870                 builtin_monitorexit((java_objectheader *) c);
1871 #endif
1872
1873                 return c;
1874         }
1875
1876 #if defined(STATISTICS)
1877         /* measure time */
1878
1879         if (getcompilingtime)
1880                 compilingtime_stop();
1881
1882         if (getloadingtime)
1883                 loadingtime_start();
1884 #endif
1885
1886         /* load classdata, throw exception on error */
1887
1888         if ((cb = suck_start(c)) == NULL) {
1889                 /* this means, the classpath was not set properly */
1890                 if (c->name == utf_java_lang_Object)
1891                         throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1892                                                                            "java/lang/Object");
1893
1894                 *exceptionptr =
1895                         new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
1896                                                                          c->name);
1897
1898 #if defined(USE_THREADS)
1899                 builtin_monitorexit((java_objectheader *) c);
1900 #endif
1901
1902                 return NULL;
1903         }
1904         
1905         /* load the class from the buffer */
1906
1907         r = load_class_from_classbuffer(cb);
1908
1909         /* if return value is NULL, we had a problem and the class is not loaded */
1910         if (!r) {
1911                 c->loaded = false;
1912
1913                 /* now free the allocated memory, otherwise we could ran into a DOS */
1914                 class_remove(c);
1915         }
1916
1917         /* free memory */
1918         suck_stop(cb);
1919
1920 #if defined(STATISTICS)
1921         /* measure time */
1922
1923         if (getloadingtime)
1924                 loadingtime_stop();
1925
1926         if (getcompilingtime)
1927                 compilingtime_start();
1928 #endif
1929
1930 #if defined(USE_THREADS)
1931         /* leave the monitor */
1932
1933         builtin_monitorexit((java_objectheader *) c);
1934 #endif
1935
1936         return r;
1937 }
1938
1939
1940 /* load_class_from_classbuffer *************************************************
1941         
1942    Loads everything interesting about a class from the class file. The
1943    'classinfo' structure must have been allocated previously.
1944
1945    The super class and the interfaces implemented by this class need
1946    not be loaded. The link is set later by the function 'class_link'.
1947
1948    The loaded class is removed from the list 'unloadedclasses' and
1949    added to the list 'unlinkedclasses'.
1950         
1951 *******************************************************************************/
1952
1953 classinfo *load_class_from_classbuffer(classbuffer *cb)
1954 {
1955         classinfo *c;
1956         classinfo *tc;
1957         u4 i;
1958         u4 ma, mi;
1959         s4 dumpsize;
1960         descriptor_pool *descpool;
1961         char msg[MAXLOGTEXT];               /* maybe we get an exception */
1962 #if defined(STATISTICS)
1963         u4 classrefsize;
1964         u4 descsize;
1965 #endif
1966
1967         /* get the classbuffer's class */
1968         c = cb->class;
1969
1970         /* maybe the class is already loaded */
1971         if (c->loaded)
1972                 return c;
1973
1974 #if defined(STATISTICS)
1975         if (opt_stat)
1976                 count_class_loads++;
1977 #endif
1978
1979         /* output for debugging purposes */
1980         if (loadverbose)
1981                 log_message_class("Loading class: ", c);
1982         
1983         /* mark start of dump memory area */
1984         dumpsize = dump_size();
1985
1986         /* class is somewhat loaded */
1987         c->loaded = true;
1988
1989         if (!check_classbuffer_size(cb, 4 + 2 + 2))
1990                 goto return_exception;
1991
1992         /* check signature */
1993         if (suck_u4(cb) != MAGIC) {
1994                 *exceptionptr = new_classformaterror(c, "Bad magic number");
1995
1996                 goto return_exception;
1997         }
1998
1999         /* check version */
2000         mi = suck_u2(cb);
2001         ma = suck_u2(cb);
2002
2003         if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2004                 *exceptionptr =
2005                         new_unsupportedclassversionerror(c,
2006                                                                                          "Unsupported major.minor version %d.%d",
2007                                                                                          ma, mi);
2008
2009                 goto return_exception;
2010         }
2011
2012         /* create a new descriptor pool */
2013         descpool = descriptor_pool_new(c);
2014         
2015         /* load the constant pool */
2016         if (!load_constantpool(cb,descpool))
2017                 goto return_exception;
2018
2019         /*JOWENN*/
2020         c->erroneous_state = 0;
2021         c->initializing_thread = 0;     
2022         /*JOWENN*/
2023         c->classUsed = NOTUSED; /* not used initially CO-RT */
2024         c->impldBy = NULL;
2025
2026         /* ACC flags */
2027         if (!check_classbuffer_size(cb, 2))
2028                 goto return_exception;
2029
2030         c->flags = suck_u2(cb);
2031         /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
2032
2033         /* check ACC flags consistency */
2034         if (c->flags & ACC_INTERFACE) {
2035                 if (!(c->flags & ACC_ABSTRACT)) {
2036                         /* We work around this because interfaces in JDK 1.1 are
2037                          * not declared abstract. */
2038
2039                         c->flags |= ACC_ABSTRACT;
2040                         /* panic("Interface class not declared abstract"); */
2041                 }
2042
2043                 if (c->flags & ACC_FINAL) {
2044                         *exceptionptr =
2045                                 new_classformaterror(c,
2046                                                                          "Illegal class modifiers: 0x%X", c->flags);
2047
2048                         goto return_exception;
2049                 }
2050
2051                 if (c->flags & ACC_SUPER) {
2052                         c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2053                 }
2054         }
2055
2056         if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2057                 *exceptionptr =
2058                         new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2059
2060                 goto return_exception;
2061         }
2062
2063         if (!check_classbuffer_size(cb, 2 + 2))
2064                 goto return_exception;
2065
2066         /* this class */
2067         i = suck_u2(cb);
2068         if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
2069                 goto return_exception;
2070
2071         if (tc != c) {
2072                 utf_sprint(msg, c->name);
2073                 sprintf(msg + strlen(msg), " (wrong name: ");
2074                 utf_sprint(msg + strlen(msg), tc->name);
2075                 sprintf(msg + strlen(msg), ")");
2076
2077                 *exceptionptr =
2078                         new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2079
2080                 goto return_exception;
2081         }
2082         
2083         /* retrieve superclass */
2084         if ((i = suck_u2(cb))) {
2085                 if (!(c->super.cls = class_getconstant(c, i, CONSTANT_Class)))
2086                         goto return_exception;
2087
2088                 /* java.lang.Object may not have a super class. */
2089                 if (c->name == utf_java_lang_Object) {
2090                         *exceptionptr =
2091                                 new_exception_message(string_java_lang_ClassFormatError,
2092                                                                           "java.lang.Object with superclass");
2093
2094                         goto return_exception;
2095                 }
2096
2097                 /* Interfaces must have java.lang.Object as super class. */
2098                 if ((c->flags & ACC_INTERFACE) &&
2099                         c->super.cls->name != utf_java_lang_Object) {
2100                         *exceptionptr =
2101                                 new_exception_message(string_java_lang_ClassFormatError,
2102                                                                           "Interfaces must have java.lang.Object as superclass");
2103
2104                         goto return_exception;
2105                 }
2106
2107         } else {
2108                 c->super.any = NULL;
2109
2110                 /* This is only allowed for java.lang.Object. */
2111                 if (c->name != utf_java_lang_Object) {
2112                         *exceptionptr = new_classformaterror(c, "Bad superclass index");
2113
2114                         goto return_exception;
2115                 }
2116         }
2117                          
2118         /* retrieve interfaces */
2119         if (!check_classbuffer_size(cb, 2))
2120                 goto return_exception;
2121
2122         c->interfacescount = suck_u2(cb);
2123
2124         if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2125                 goto return_exception;
2126
2127         c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2128         for (i = 0; i < c->interfacescount; i++) {
2129                 if (!(c->interfaces[i].cls = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2130                         goto return_exception;
2131         }
2132
2133         /* load fields */
2134         if (!check_classbuffer_size(cb, 2))
2135                 goto return_exception;
2136
2137         c->fieldscount = suck_u2(cb);
2138         c->fields = GCNEW(fieldinfo, c->fieldscount);
2139 /*      c->fields = MNEW(fieldinfo, c->fieldscount); */
2140         for (i = 0; i < c->fieldscount; i++) {
2141                 if (!load_field(cb, &(c->fields[i]),descpool))
2142                         goto return_exception;
2143         }
2144
2145         /* load methods */
2146         if (!check_classbuffer_size(cb, 2))
2147                 goto return_exception;
2148
2149         c->methodscount = suck_u2(cb);
2150 /*      c->methods = GCNEW(methodinfo, c->methodscount); */
2151         c->methods = MNEW(methodinfo, c->methodscount);
2152         for (i = 0; i < c->methodscount; i++) {
2153                 if (!load_method(cb, &(c->methods[i]),descpool))
2154                         goto return_exception;
2155         }
2156
2157         /* create the class reference table */
2158         c->classrefs = descriptor_pool_create_classrefs(descpool,&(c->classrefcount));
2159
2160         /* allocate space for the parsed descriptors */
2161         descriptor_pool_alloc_parsed_descriptors(descpool);
2162         c->parseddescs = descriptor_pool_get_parsed_descriptors(descpool,&(c->parseddescsize));
2163
2164 #if defined(STATISTICS)
2165         if (opt_stat) {
2166                 descriptor_pool_get_sizes(descpool,&classrefsize,&descsize);
2167                 count_classref_len += classrefsize;
2168                 count_parsed_desc_len += descsize;
2169         }
2170 #endif
2171
2172         /* parse the loaded descriptors */
2173         for (i=0; i<c->cpcount; ++i) {
2174                 constant_FMIref *fmi;
2175                 
2176                 switch (c->cptags[i]) {
2177                         case CONSTANT_Class:
2178                                 /* XXX set classref */
2179                                 break;
2180                         case CONSTANT_Fieldref:
2181                                 fmi = (constant_FMIref *)c->cpinfos[i];
2182                                 fmi->parseddesc.fd = 
2183                                         descriptor_pool_parse_field_descriptor(descpool,fmi->descriptor);
2184                                 if (!fmi->parseddesc.fd)
2185                                         goto return_exception;
2186                                 fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
2187                                 break;
2188                         case CONSTANT_Methodref:
2189                         case CONSTANT_InterfaceMethodref:
2190                                 fmi = (constant_FMIref *)c->cpinfos[i];
2191                                 fmi->parseddesc.md = 
2192                                         descriptor_pool_parse_method_descriptor(descpool,fmi->descriptor);
2193                                 if (!fmi->parseddesc.md)
2194                                         goto return_exception;
2195                                 fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
2196                                 break;
2197                 }
2198         }
2199         for (i = 0; i < c->fieldscount; i++) {
2200                 c->fields[i].parseddesc = descriptor_pool_parse_field_descriptor(descpool,c->fields[i].descriptor);
2201                 if (!c->fields[i].parseddesc)
2202                         goto return_exception;
2203         }
2204         for (i = 0; i < c->methodscount; i++) {
2205                 c->methods[i].parseddesc = descriptor_pool_parse_method_descriptor(descpool,c->methods[i].descriptor);
2206                 if (!c->methods[i].parseddesc)
2207                         goto return_exception;
2208         }
2209
2210         /* Check if all fields and methods can be uniquely
2211          * identified by (name,descriptor). */
2212         if (opt_verify) {
2213                 /* We use a hash table here to avoid making the
2214                  * average case quadratic in # of methods, fields.
2215                  */
2216                 static int shift = 0;
2217                 u2 *hashtab;
2218                 u2 *next; /* for chaining colliding hash entries */
2219                 size_t len;
2220                 size_t hashlen;
2221                 u2 index;
2222                 u2 old;
2223
2224                 /* Allocate hashtable */
2225                 len = c->methodscount;
2226                 if (len < c->fieldscount) len = c->fieldscount;
2227                 hashlen = 5 * len;
2228                 hashtab = MNEW(u2,(hashlen + len));
2229                 next = hashtab + hashlen;
2230
2231                 /* Determine bitshift (to get good hash values) */
2232                 if (!shift) {
2233                         len = sizeof(utf);
2234                         while (len) {
2235                                 len >>= 1;
2236                                 shift++;
2237                         }
2238                 }
2239
2240                 /* Check fields */
2241                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2242
2243                 for (i = 0; i < c->fieldscount; ++i) {
2244                         fieldinfo *fi = c->fields + i;
2245
2246                         /* It's ok if we lose bits here */
2247                         index = ((((size_t) fi->name) +
2248                                           ((size_t) fi->descriptor)) >> shift) % hashlen;
2249
2250                         if ((old = hashtab[index])) {
2251                                 old--;
2252                                 next[i] = old;
2253                                 do {
2254                                         if (c->fields[old].name == fi->name &&
2255                                                 c->fields[old].descriptor == fi->descriptor) {
2256                                                 *exceptionptr =
2257                                                         new_classformaterror(c,
2258                                                                                                  "Repetitive field name/signature");
2259
2260                                                 goto return_exception;
2261                                         }
2262                                 } while ((old = next[old]));
2263                         }
2264                         hashtab[index] = i + 1;
2265                 }
2266                 
2267                 /* Check methods */
2268                 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2269
2270                 for (i = 0; i < c->methodscount; ++i) {
2271                         methodinfo *mi = c->methods + i;
2272
2273                         /* It's ok if we lose bits here */
2274                         index = ((((size_t) mi->name) +
2275                                           ((size_t) mi->descriptor)) >> shift) % hashlen;
2276
2277                         /*{ JOWENN
2278                                 int dbg;
2279                                 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2280                                         printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2281                                 }
2282                         }*/
2283
2284                         if ((old = hashtab[index])) {
2285                                 old--;
2286                                 next[i] = old;
2287                                 do {
2288                                         if (c->methods[old].name == mi->name &&
2289                                                 c->methods[old].descriptor == mi->descriptor) {
2290                                                 *exceptionptr =
2291                                                         new_classformaterror(c,
2292                                                                                                  "Repetitive method name/signature");
2293
2294                                                 goto return_exception;
2295                                         }
2296                                 } while ((old = next[old]));
2297                         }
2298                         hashtab[index] = i + 1;
2299                 }
2300                 
2301                 MFREE(hashtab, u2, (hashlen + len));
2302         }
2303
2304 #if defined(STATISTICS)
2305         if (opt_stat) {
2306                 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2307                 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2308                 count_class_infos += sizeof(methodinfo) * c->methodscount;
2309         }
2310 #endif
2311
2312         /* load attribute structures */
2313         if (!check_classbuffer_size(cb, 2))
2314                 goto return_exception;
2315
2316         if (!load_attributes(cb, suck_u2(cb)))
2317                 goto return_exception;
2318
2319 #if 0
2320         /* Pre java 1.5 version don't check this. This implementation is like
2321            java 1.5 do it: for class file version 45.3 we don't check it, older
2322            versions are checked.
2323          */
2324         if ((ma == 45 && mi > 3) || ma > 45) {
2325                 /* check if all data has been read */
2326                 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2327
2328                 if (classdata_left > 0) {
2329                         *exceptionptr =
2330                                 new_classformaterror(c, "Extra bytes at the end of class file");
2331                         goto return_exception;
2332                 }
2333         }
2334 #endif
2335
2336         /* release dump area */
2337         dump_release(dumpsize);
2338         
2339         if (loadverbose)
2340                 log_message_class("Loading done class: ", c);
2341
2342         return c;
2343
2344 return_exception:
2345         /* release dump area */
2346         dump_release(dumpsize);
2347
2348         /* an exception has been thrown */
2349         return NULL;
2350 }
2351
2352
2353
2354 /******************* Function: class_new_array *********************************
2355
2356     This function is called by class_new to setup an array class.
2357
2358 *******************************************************************************/
2359
2360 void class_new_array(classinfo *c)
2361 {
2362         classinfo *comp = NULL;
2363         methodinfo *clone;
2364         methoddesc *clonedesc;
2365         constant_classref *classrefs;
2366         int namelen;
2367
2368         /* Check array class name */
2369         namelen = c->name->blength;
2370         if (namelen < 2 || c->name->text[0] != '[')
2371                 panic("Invalid array class name");
2372
2373         /* Check the component type */
2374         switch (c->name->text[1]) {
2375         case '[':
2376                 /* c is an array of arrays. We have to create the component class. */
2377                 if (opt_eager) {
2378                         comp = class_new_intern(utf_new_intern(c->name->text + 1,
2379                                                                                                    namelen - 1));
2380                         load_class_from_classloader(comp, c->classloader);
2381                         list_addfirst(&unlinkedclasses, comp);
2382
2383                 } else {
2384                         comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2385                 }
2386                 break;
2387
2388         case 'L':
2389                 /* c is an array of objects. */
2390                 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2391                         panic("Invalid array class name");
2392
2393                 if (opt_eager) {
2394                         comp = class_new_intern(utf_new_intern(c->name->text + 2,
2395                                                                                                    namelen - 3));
2396                         load_class_from_classloader(comp, c->classloader);
2397                         list_addfirst(&unlinkedclasses, comp);
2398
2399                 } else {
2400                         comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2401                 }
2402                 break;
2403         }
2404
2405         /* Setup the array class */
2406         c->super.cls = class_java_lang_Object;
2407         c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2408
2409     c->interfacescount = 2;
2410     c->interfaces = MNEW(classref_or_classinfo, 2);
2411
2412         if (opt_eager) {
2413                 classinfo *tc;
2414
2415                 tc = class_java_lang_Cloneable;
2416                 load_class_bootstrap(tc);
2417                 list_addfirst(&unlinkedclasses, tc);
2418                 c->interfaces[0].cls = tc;
2419
2420                 tc = class_java_io_Serializable;
2421                 load_class_bootstrap(tc);
2422                 list_addfirst(&unlinkedclasses, tc);
2423                 c->interfaces[1].cls = tc;
2424
2425         } else {
2426                 c->interfaces[0].cls = class_java_lang_Cloneable;
2427                 c->interfaces[1].cls = class_java_io_Serializable;
2428         }
2429
2430         c->methodscount = 1;
2431         c->methods = MNEW(methodinfo, c->methodscount);
2432
2433         classrefs = MNEW(constant_classref,1);
2434         CLASSREF_INIT(classrefs[0],c,utf_java_lang_Object);
2435
2436         clonedesc = NEW(methoddesc);
2437         clonedesc->returntype.type = TYPE_ADDRESS;
2438         clonedesc->returntype.classref = classrefs;
2439         clonedesc->returntype.arraydim = 0;
2440         clonedesc->paramcount = 0;
2441         clonedesc->paramslots = 0;
2442
2443         clone = c->methods;
2444         MSET(clone, 0, methodinfo, 1);
2445         clone->flags = ACC_PUBLIC;
2446         clone->name = utf_new_char("clone");
2447         clone->descriptor = utf_void__java_lang_Object;
2448         clone->parseddesc = clonedesc;
2449         clone->class = c;
2450         clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2451         clone->monoPoly = MONO;
2452
2453         /* XXX: field: length? */
2454
2455         /* array classes are not loaded from class files */
2456         c->loaded = true;
2457         c->parseddescs = (u1*) clonedesc;
2458         c->parseddescsize = sizeof(methodinfo);
2459         c->classrefs = classrefs;
2460         c->classrefcount = 1;
2461
2462         /* XXX insert class into the loaded class cache */
2463 }
2464
2465
2466 /************************* Function: class_findfield ***************************
2467         
2468         Searches a 'classinfo' structure for a field having the given name and
2469         type.
2470
2471 *******************************************************************************/
2472
2473 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2474 {
2475         s4 i;
2476
2477         for (i = 0; i < c->fieldscount; i++) { 
2478                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
2479                         return &(c->fields[i]);                                                         
2480     }
2481
2482         panic("Can not find field given in CONSTANT_Fieldref");
2483
2484         /* keep compiler happy */
2485         return NULL;
2486 }
2487
2488
2489 /****************** Function: class_resolvefield_int ***************************
2490
2491     This is an internally used helper function. Do not use this directly.
2492
2493         Tries to resolve a field having the given name and type.
2494     If the field cannot be resolved, NULL is returned.
2495
2496 *******************************************************************************/
2497
2498 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2499 {
2500         fieldinfo *fi;
2501         s4         i;
2502
2503         /* search for field in class c */
2504
2505         for (i = 0; i < c->fieldscount; i++) { 
2506                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2507                         return &(c->fields[i]);
2508                 }
2509     }
2510
2511         /* try superinterfaces recursively */
2512
2513         for (i = 0; i < c->interfacescount; i++) {
2514                 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
2515                 if (fi)
2516                         return fi;
2517         }
2518
2519         /* try superclass */
2520
2521         if (c->super.cls)
2522                 return class_resolvefield_int(c->super.cls, name, desc);
2523
2524         /* not found */
2525
2526         return NULL;
2527 }
2528
2529
2530 /********************* Function: class_resolvefield ***************************
2531         
2532         Resolves a reference from REFERER to a field with NAME and DESC in class C.
2533
2534     If the field cannot be resolved the return value is NULL. If EXCEPT is
2535     true *exceptionptr is set, too.
2536
2537 *******************************************************************************/
2538
2539 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2540                                                           classinfo *referer, bool except)
2541 {
2542         fieldinfo *fi;
2543
2544         /* XXX resolve class c */
2545         /* XXX check access from REFERER to C */
2546         
2547         fi = class_resolvefield_int(c, name, desc);
2548
2549         if (!fi) {
2550                 if (except)
2551                         *exceptionptr =
2552                                 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2553                                                                                  name);
2554
2555                 return NULL;
2556         }
2557
2558         /* XXX check access rights */
2559
2560         return fi;
2561 }
2562
2563
2564 /* class_findmethod ************************************************************
2565         
2566    Searches a 'classinfo' structure for a method having the given name
2567    and descriptor. If descriptor is NULL, it is ignored.
2568
2569 *******************************************************************************/
2570
2571 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2572 {
2573         methodinfo *m;
2574         s4 i;
2575
2576         for (i = 0; i < c->methodscount; i++) {
2577                 m = &(c->methods[i]);
2578
2579                 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
2580                         return m;
2581         }
2582
2583         return NULL;
2584 }
2585
2586
2587 /*********************** Function: class_fetchmethod **************************
2588         
2589     like class_findmethod, but aborts with an error if the method is not found
2590
2591 *******************************************************************************/
2592
2593 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2594 {
2595         methodinfo *mi;
2596
2597         mi = class_findmethod(c, name, desc);
2598
2599         if (!mi) {
2600                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2601                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2602                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2603                 panic("Method not found");
2604         }
2605
2606         return mi;
2607 }
2608
2609
2610 /************************* Function: class_findmethod_approx ******************
2611         
2612         like class_findmethod but ignores the return value when comparing the
2613         descriptor.
2614
2615 *******************************************************************************/
2616
2617 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2618 {
2619         s4 i;
2620
2621         for (i = 0; i < c->methodscount; i++) {
2622                 if (c->methods[i].name == name) {
2623                         utf *meth_descr = c->methods[i].descriptor;
2624                         
2625                         if (desc == NULL) 
2626                                 /* ignore type */
2627                                 return &(c->methods[i]);
2628
2629                         if (desc->blength <= meth_descr->blength) {
2630                                 /* current position in utf text   */
2631                                 char *desc_utf_ptr = desc->text;      
2632                                 char *meth_utf_ptr = meth_descr->text;                                    
2633                                 /* points behind utf strings */
2634                                 char *desc_end = utf_end(desc);         
2635                                 char *meth_end = utf_end(meth_descr);   
2636                                 char ch;
2637
2638                                 /* compare argument types */
2639                                 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2640
2641                                         if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2642                                                 break; /* no match */
2643
2644                                         if (ch == ')')
2645                                                 return &(c->methods[i]);   /* all parameter types equal */
2646                                 }
2647                         }
2648                 }
2649         }
2650
2651         return NULL;
2652 }
2653
2654
2655 /***************** Function: class_resolvemethod_approx ***********************
2656         
2657         Searches a class and every super class for a method (without paying
2658         attention to the return value)
2659
2660 *******************************************************************************/
2661
2662 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2663 {
2664         while (c) {
2665                 /* search for method (ignore returntype) */
2666                 methodinfo *m = class_findmethod_approx(c, name, desc);
2667                 /* method found */
2668                 if (m) return m;
2669                 /* search superclass */
2670                 c = c->super.cls;
2671         }
2672
2673         return NULL;
2674 }
2675
2676
2677 /* class_resolvemethod *********************************************************
2678         
2679    Searches a class and it's super classes for a method.
2680
2681 *******************************************************************************/
2682
2683 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2684 {
2685         methodinfo *m;
2686
2687         while (c) {
2688                 m = class_findmethod(c, name, desc);
2689
2690                 if (m)
2691                         return m;
2692
2693                 c = c->super.cls;
2694         }
2695
2696         return NULL;
2697 }
2698
2699
2700 /* class_resolveinterfacemethod_intern *****************************************
2701
2702    Internally used helper function. Do not use this directly.
2703
2704 *******************************************************************************/
2705
2706 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
2707                                                                                                            utf *name, utf *desc)
2708 {
2709         methodinfo *m;
2710         s4 i;
2711         
2712         m = class_findmethod(c, name, desc);
2713
2714         if (m)
2715                 return m;
2716
2717         /* try the superinterfaces */
2718
2719         for (i = 0; i < c->interfacescount; i++) {
2720                 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls, name, desc);
2721
2722                 if (m)
2723                         return m;
2724         }
2725         
2726         return NULL;
2727 }
2728
2729 /* class_resolveinterfacemethod ************************************************
2730
2731    Resolves a reference from REFERER to a method with NAME and DESC in
2732    interface C.
2733
2734    If the method cannot be resolved the return value is NULL. If
2735    EXCEPT is true *exceptionptr is set, too.
2736
2737 *******************************************************************************/
2738
2739 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2740                                                                                  classinfo *referer, bool except)
2741 {
2742         methodinfo *mi;
2743
2744         /* XXX resolve class c */
2745         /* XXX check access from REFERER to C */
2746         
2747         if (!(c->flags & ACC_INTERFACE)) {
2748                 if (except)
2749                         *exceptionptr =
2750                                 new_exception(string_java_lang_IncompatibleClassChangeError);
2751
2752                 return NULL;
2753         }
2754
2755         mi = class_resolveinterfacemethod_intern(c, name, desc);
2756
2757         if (mi)
2758                 return mi;
2759
2760         /* try class java.lang.Object */
2761         mi = class_findmethod(class_java_lang_Object, name, desc);
2762
2763         if (mi)
2764                 return mi;
2765
2766         if (except)
2767                 *exceptionptr =
2768                         new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
2769
2770         return NULL;
2771 }
2772
2773
2774 /* class_resolveclassmethod ****************************************************
2775         
2776     Resolves a reference from REFERER to a method with NAME and DESC in
2777     class C.
2778
2779     If the method cannot be resolved the return value is NULL. If EXCEPT is
2780     true *exceptionptr is set, too.
2781
2782 *******************************************************************************/
2783
2784 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
2785                                                                          classinfo *referer, bool except)
2786 {
2787         classinfo  *cls;
2788         methodinfo *mi;
2789         s4          i;
2790         char       *msg;
2791         s4          msglen;
2792
2793         /* XXX resolve class c */
2794         /* XXX check access from REFERER to C */
2795         
2796 /*      if (c->flags & ACC_INTERFACE) { */
2797 /*              if (except) */
2798 /*                      *exceptionptr = */
2799 /*                              new_exception(string_java_lang_IncompatibleClassChangeError); */
2800 /*              return NULL; */
2801 /*      } */
2802
2803         /* try class c and its superclasses */
2804
2805         cls = c;
2806
2807         while (cls) {
2808                 mi = class_findmethod(cls, name, desc);
2809
2810                 if (mi)
2811                         goto found;
2812
2813                 cls = cls->super.cls;
2814         }
2815
2816         /* try the superinterfaces */
2817
2818         for (i = 0; i < c->interfacescount; i++) {
2819                 mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls, name, desc);
2820
2821                 if (mi)
2822                         goto found;
2823         }
2824         
2825         if (except) {
2826                 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
2827                         utf_strlen(desc) + strlen("0");
2828
2829                 msg = MNEW(char, msglen);
2830
2831                 utf_sprint(msg, c->name);
2832                 strcat(msg, ".");
2833                 utf_sprint(msg + strlen(msg), name);
2834                 utf_sprint(msg + strlen(msg), desc);
2835
2836                 *exceptionptr =
2837                         new_exception_message(string_java_lang_NoSuchMethodError, msg);
2838
2839                 MFREE(msg, char, msglen);
2840         }
2841
2842         return NULL;
2843
2844  found:
2845         if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
2846                 if (except)
2847                         *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
2848
2849                 return NULL;
2850         }
2851
2852         /* XXX check access rights */
2853
2854         return mi;
2855 }
2856
2857
2858 /************************* Function: class_issubclass **************************
2859
2860         Checks if sub is a descendant of super.
2861         
2862 *******************************************************************************/
2863
2864 bool class_issubclass(classinfo *sub, classinfo *super)
2865 {
2866         for (;;) {
2867                 if (!sub) return false;
2868                 if (sub == super) return true;
2869                 sub = sub->super.cls;
2870         }
2871 }
2872
2873
2874 /****************** Initialization function for classes ******************
2875
2876         In Java, every class can have a static initialization function. This
2877         function has to be called BEFORE calling other methods or accessing static
2878         variables.
2879
2880 *******************************************************************************/
2881
2882 static classinfo *class_init_intern(classinfo *c);
2883
2884 classinfo *class_init(classinfo *c)
2885 {
2886         classinfo *r;
2887
2888         if (!makeinitializations)
2889                 return c;
2890
2891 #if defined(USE_THREADS)
2892         /* enter a monitor on the class */
2893
2894         builtin_monitorenter((java_objectheader *) c);
2895 #endif
2896
2897         /* maybe the class is already initalized or the current thread, which can
2898            pass the monitor, is currently initalizing this class */
2899
2900         /* JOWENN: In future we need an additinal flag: initializationfailed,
2901                 since further access to the class should cause a NoClassDefFound,
2902                 if the static initializer failed once
2903         */
2904
2905         if (c->initialized || c->initializing) {
2906 #if defined(USE_THREADS)
2907                 builtin_monitorexit((java_objectheader *) c);
2908 #endif
2909
2910                 return c;
2911         }
2912
2913         /* this initalizing run begins NOW */
2914         c->initializing = true;
2915
2916         /* call the internal function */
2917         r = class_init_intern(c);
2918
2919         /* if return value is not NULL everything was ok and the class is
2920            initialized */
2921         if (r)
2922                 c->initialized = true;
2923
2924         /* this initalizing run is done */
2925         c->initializing = false;
2926
2927 #if defined(USE_THREADS)
2928         /* leave the monitor */
2929
2930         builtin_monitorexit((java_objectheader *) c);
2931 #endif
2932
2933         return r;
2934 }
2935
2936
2937 /* this function MUST NOT be called directly, because of thread <clinit>
2938    race conditions */
2939
2940 static classinfo *class_init_intern(classinfo *c)
2941 {
2942         methodinfo *m;
2943         s4 i;
2944 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2945         int b;
2946 #endif
2947
2948         /* maybe the class is not already loaded */
2949         if (!c->loaded)
2950                 if (!load_class_bootstrap(c))
2951                         return NULL;
2952
2953         /* maybe the class is not already linked */
2954         if (!c->linked)
2955                 if (!link_class(c))
2956                         return NULL;
2957
2958 #if defined(STATISTICS)
2959         if (opt_stat)
2960                 count_class_inits++;
2961 #endif
2962
2963         /* initialize super class */
2964
2965         if (c->super.cls) {
2966                 if (!c->super.cls->initialized) {
2967                         if (initverbose) {
2968                                 char logtext[MAXLOGTEXT];
2969                                 sprintf(logtext, "Initialize super class ");
2970                                 utf_sprint_classname(logtext + strlen(logtext), c->super.cls->name);
2971                                 sprintf(logtext + strlen(logtext), " from ");
2972                                 utf_sprint_classname(logtext + strlen(logtext), c->name);
2973                                 log_text(logtext);
2974                         }
2975
2976                         if (!class_init(c->super.cls))
2977                                 return NULL;
2978                 }
2979         }
2980
2981         /* initialize interface classes */
2982
2983         for (i = 0; i < c->interfacescount; i++) {
2984                 if (!c->interfaces[i].cls->initialized) {
2985                         if (initverbose) {
2986                                 char logtext[MAXLOGTEXT];
2987                                 sprintf(logtext, "Initialize interface class ");
2988                                 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i].cls->name);
2989                                 sprintf(logtext + strlen(logtext), " from ");
2990                                 utf_sprint_classname(logtext + strlen(logtext), c->name);
2991                                 log_text(logtext);
2992                         }
2993                         
2994                         if (!class_init(c->interfaces[i].cls))
2995                                 return NULL;
2996                 }
2997         }
2998
2999         m = class_findmethod(c, utf_clinit, utf_void__void);
3000
3001         if (!m) {
3002                 if (initverbose) {
3003                         char logtext[MAXLOGTEXT];
3004                         sprintf(logtext, "Class ");
3005                         utf_sprint_classname(logtext + strlen(logtext), c->name);
3006                         sprintf(logtext + strlen(logtext), " has no static class initializer");
3007                         log_text(logtext);
3008                 }
3009
3010                 return c;
3011         }
3012
3013         /* Sun's and IBM's JVM don't care about the static flag */
3014 /*      if (!(m->flags & ACC_STATIC)) { */
3015 /*              panic("Class initializer is not static!"); */
3016
3017         if (initverbose)
3018                 log_message_class("Starting static class initializer for class: ", c);
3019
3020 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3021         b = blockInts;
3022         blockInts = 0;
3023 #endif
3024
3025         /* now call the initializer */
3026         asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3027
3028 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3029         assert(blockInts == 0);
3030         blockInts = b;
3031 #endif
3032
3033         /* we have an exception or error */
3034         if (*exceptionptr) {
3035                 /* class is NOT initialized */
3036                 c->initialized = false;
3037
3038                 /* is this an exception, than wrap it */
3039                 if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
3040                         java_objectheader *xptr;
3041                         java_objectheader *cause;
3042
3043                         /* get the cause */
3044                         cause = *exceptionptr;
3045
3046                         /* clear exception, because we are calling jit code again */
3047                         *exceptionptr = NULL;
3048
3049                         /* wrap the exception */
3050                         xptr =
3051                                 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3052                                                                                 (java_lang_Throwable *) cause);
3053
3054                         /* XXX should we exit here? */
3055                         if (*exceptionptr)
3056                                 throw_exception();
3057
3058                         /* set new exception */
3059                         *exceptionptr = xptr;
3060                 }
3061
3062                 return NULL;
3063         }
3064
3065         if (initverbose)
3066                 log_message_class("Finished static class initializer for class: ", c);
3067
3068         return c;
3069 }
3070
3071
3072 void class_showconstanti(classinfo *c, int ii) 
3073 {
3074         u4 i = ii;
3075         voidptr e;
3076                 
3077         e = c->cpinfos [i];
3078         printf ("#%d:  ", (int) i);
3079         if (e) {
3080                 switch (c->cptags [i]) {
3081                 case CONSTANT_Class:
3082                         printf("Classreference -> ");
3083                         utf_display(((classinfo*)e)->name);
3084                         break;
3085                                 
3086                 case CONSTANT_Fieldref:
3087                         printf("Fieldref -> "); goto displayFMIi;
3088                 case CONSTANT_Methodref:
3089                         printf("Methodref -> "); goto displayFMIi;
3090                 case CONSTANT_InterfaceMethodref:
3091                         printf("InterfaceMethod -> "); goto displayFMIi;
3092                 displayFMIi:
3093                         {
3094                                 constant_FMIref *fmi = e;
3095                                 utf_display(fmi->class->name);
3096                                 printf(".");
3097                                 utf_display(fmi->name);
3098                                 printf(" ");
3099                                 utf_display(fmi->descriptor);
3100                         }
3101                         break;
3102
3103                 case CONSTANT_String:
3104                         printf("String -> ");
3105                         utf_display(e);
3106                         break;
3107                 case CONSTANT_Integer:
3108                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3109                         break;
3110                 case CONSTANT_Float:
3111                         printf("Float -> %f", ((constant_float*)e)->value);
3112                         break;
3113                 case CONSTANT_Double:
3114                         printf("Double -> %f", ((constant_double*)e)->value);
3115                         break;
3116                 case CONSTANT_Long:
3117                         {
3118                                 u8 v = ((constant_long*)e)->value;
3119 #if U8_AVAILABLE
3120                                 printf("Long -> %ld", (long int) v);
3121 #else
3122                                 printf("Long -> HI: %ld, LO: %ld\n", 
3123                                             (long int) v.high, (long int) v.low);
3124 #endif 
3125                         }
3126                         break;
3127                 case CONSTANT_NameAndType:
3128                         { 
3129                                 constant_nameandtype *cnt = e;
3130                                 printf("NameAndType: ");
3131                                 utf_display(cnt->name);
3132                                 printf(" ");
3133                                 utf_display(cnt->descriptor);
3134                         }
3135                         break;
3136                 case CONSTANT_Utf8:
3137                         printf("Utf8 -> ");
3138                         utf_display(e);
3139                         break;
3140                 default: 
3141                         panic("Invalid type of ConstantPool-Entry");
3142                 }
3143         }
3144         printf("\n");
3145 }
3146
3147
3148 void class_showconstantpool (classinfo *c) 
3149 {
3150         u4 i;
3151         voidptr e;
3152
3153         printf ("---- dump of constant pool ----\n");
3154
3155         for (i=0; i<c->cpcount; i++) {
3156                 printf ("#%d:  ", (int) i);
3157                 
3158                 e = c -> cpinfos [i];
3159                 if (e) {
3160                         
3161                         switch (c -> cptags [i]) {
3162                         case CONSTANT_Class:
3163                                 printf ("Classreference -> ");
3164                                 utf_display ( ((classinfo*)e) -> name );
3165                                 break;
3166                                 
3167                         case CONSTANT_Fieldref:
3168                                 printf ("Fieldref -> "); goto displayFMI;
3169                         case CONSTANT_Methodref:
3170                                 printf ("Methodref -> "); goto displayFMI;
3171                         case CONSTANT_InterfaceMethodref:
3172                                 printf ("InterfaceMethod -> "); goto displayFMI;
3173                         displayFMI:
3174                                 {
3175                                         constant_FMIref *fmi = e;
3176                                         utf_display ( fmi->class->name );
3177                                         printf (".");
3178                                         utf_display ( fmi->name);
3179                                         printf (" ");
3180                                         utf_display ( fmi->descriptor );
3181                                 }
3182                                 break;
3183
3184                         case CONSTANT_String:
3185                                 printf ("String -> ");
3186                                 utf_display (e);
3187                                 break;
3188                         case CONSTANT_Integer:
3189                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3190                                 break;
3191                         case CONSTANT_Float:
3192                                 printf ("Float -> %f", ((constant_float*)e) -> value);
3193                                 break;
3194                         case CONSTANT_Double:
3195                                 printf ("Double -> %f", ((constant_double*)e) -> value);
3196                                 break;
3197                         case CONSTANT_Long:
3198                                 {
3199                                         u8 v = ((constant_long*)e) -> value;
3200 #if U8_AVAILABLE
3201                                         printf ("Long -> %ld", (long int) v);
3202 #else
3203                                         printf ("Long -> HI: %ld, LO: %ld\n", 
3204                                                         (long int) v.high, (long int) v.low);
3205 #endif 
3206                                 }
3207                                 break;
3208                         case CONSTANT_NameAndType:
3209                                 {
3210                                         constant_nameandtype *cnt = e;
3211                                         printf ("NameAndType: ");
3212                                         utf_display (cnt->name);
3213                                         printf (" ");
3214                                         utf_display (cnt->descriptor);
3215                                 }
3216                                 break;
3217                         case CONSTANT_Utf8:
3218                                 printf ("Utf8 -> ");
3219                                 utf_display (e);
3220                                 break;
3221                         default: 
3222                                 panic ("Invalid type of ConstantPool-Entry");
3223                         }
3224                 }
3225
3226                 printf ("\n");
3227         }
3228 }
3229
3230
3231
3232 /********** Function: class_showmethods   (debugging only) *************/
3233
3234 void class_showmethods (classinfo *c)
3235 {
3236         s4 i;
3237         
3238         printf ("--------- Fields and Methods ----------------\n");
3239         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
3240
3241         printf ("This: "); utf_display (c->name); printf ("\n");
3242         if (c->super.cls) {
3243                 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
3244                 }
3245         printf ("Index: %d\n", c->index);
3246         
3247         printf ("interfaces:\n");       
3248         for (i=0; i < c-> interfacescount; i++) {
3249                 printf ("   ");
3250                 utf_display (c -> interfaces[i].cls -> name);
3251                 printf (" (%d)\n", c->interfaces[i].cls -> index);
3252                 }
3253
3254         printf ("fields:\n");           
3255         for (i=0; i < c -> fieldscount; i++) {
3256                 field_display (&(c -> fields[i]));
3257                 }
3258
3259         printf ("methods:\n");
3260         for (i=0; i < c -> methodscount; i++) {
3261                 methodinfo *m = &(c->methods[i]);
3262                 if ( !(m->flags & ACC_STATIC)) 
3263                         printf ("vftblindex: %d   ", m->vftblindex);
3264
3265                 method_display ( m );
3266
3267                 }
3268
3269         printf ("Virtual function table:\n");
3270         for (i=0; i<c->vftbl->vftbllength; i++) {
3271                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
3272                 }
3273
3274 }
3275
3276
3277 /******************************************************************************/
3278 /******************* General functions for the class loader *******************/
3279 /******************************************************************************/
3280
3281 /******************** Function: loader_close ***********************************
3282
3283         Frees all resources
3284         
3285 *******************************************************************************/
3286
3287 void loader_close()
3288 {
3289         classinfo *c;
3290         s4 slot;
3291
3292         for (slot = 0; slot < class_hash.size; slot++) {
3293                 c = class_hash.ptr[slot];
3294
3295                 while (c) {
3296                         class_free(c);
3297                         c = c->hashlink;
3298                 }
3299         }
3300 }
3301
3302
3303 /*
3304  * These are local overrides for various environment variables in Emacs.
3305  * Please do not remove this and leave it at the end of the file, where
3306  * Emacs will automagically detect them.
3307  * ---------------------------------------------------------------------
3308  * Local variables:
3309  * mode: c
3310  * indent-tabs-mode: t
3311  * c-basic-offset: 4
3312  * tab-width: 4
3313  * End:
3314  */