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