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