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