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