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