* builtin_new: Check for java.lang.InstantiationError.
[cacao.git] / src / vm / class.c
1 /* src/vm/class.c - class related 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: Mark Probst
30             Andreas Krall
31             Christian Thalinger
32
33    $Id: class.c 3542 2005-11-03 20:34:14Z twisti $
34
35 */
36
37 #include <assert.h>
38 #include <string.h>
39
40 #include "config.h"
41 #include "vm/types.h"
42
43 #include "mm/memory.h"
44
45 #if defined(USE_THREADS)
46 # if defined(NATIVE_THREADS)
47 #  include "threads/native/threads.h"
48 # else
49 #  include "threads/green/threads.h"
50 #  include "threads/green/locks.h"
51 # endif
52 #endif
53
54 #include "toolbox/logging.h"
55 #include "vm/class.h"
56 #include "vm/classcache.h"
57 #include "vm/exceptions.h"
58 #include "vm/global.h"
59 #include "vm/loader.h"
60 #include "vm/options.h"
61 #include "vm/resolve.h"
62 #include "vm/statistics.h"
63 #include "vm/stringlocal.h"
64 #include "vm/tables.h"
65 #include "vm/utf8.h"
66
67
68 /******************************************************************************/
69 /* DEBUG HELPERS                                                              */
70 /******************************************************************************/
71
72 #ifndef NDEBUG
73 #define CLASS_DEBUG
74 #endif
75
76 #ifdef CLASS_DEBUG
77 #define CLASS_ASSERT(cond)  assert(cond)
78 #else
79 #define CLASS_ASSERT(cond)
80 #endif
81
82
83 /* global variables ***********************************************************/
84
85 list unlinkedclasses;                   /* this is only used for eager class  */
86                                         /* loading                            */
87
88
89 /* frequently used classes ****************************************************/
90
91 /* important system classes */
92
93 classinfo *class_java_lang_Object = NULL;
94 classinfo *class_java_lang_Class = NULL;
95 classinfo *class_java_lang_ClassLoader = NULL;
96 classinfo *class_java_lang_Cloneable = NULL;
97 classinfo *class_java_lang_SecurityManager = NULL;
98 classinfo *class_java_lang_String = NULL;
99 classinfo *class_java_lang_System = NULL;
100 classinfo *class_java_lang_Thread = NULL;
101 classinfo *class_java_lang_ThreadGroup = NULL;
102 classinfo *class_java_lang_VMThread = NULL;
103 classinfo *class_java_io_Serializable = NULL;
104
105
106 /* system exception classes required in cacao */
107
108 classinfo *class_java_lang_Throwable = NULL;
109 classinfo *class_java_lang_VMThrowable = NULL;
110 classinfo *class_java_lang_Error = NULL;
111 classinfo *class_java_lang_NoClassDefFoundError = NULL;
112 classinfo *class_java_lang_OutOfMemoryError = NULL;
113
114 classinfo *class_java_lang_Exception = NULL;
115 classinfo *class_java_lang_ClassNotFoundException = NULL;
116 classinfo *class_java_lang_IllegalArgumentException = NULL;
117 classinfo *class_java_lang_IllegalMonitorStateException = NULL;
118
119 classinfo *class_java_lang_Void = NULL;
120 classinfo *class_java_lang_Boolean = NULL;
121 classinfo *class_java_lang_Byte = NULL;
122 classinfo *class_java_lang_Character = NULL;
123 classinfo *class_java_lang_Short = NULL;
124 classinfo *class_java_lang_Integer = NULL;
125 classinfo *class_java_lang_Long = NULL;
126 classinfo *class_java_lang_Float = NULL;
127 classinfo *class_java_lang_Double = NULL;
128
129
130 /* some runtime exception */
131
132 classinfo *class_java_lang_NullPointerException = NULL;
133
134
135 /* some classes which may be used more often */
136
137 classinfo *class_java_lang_StackTraceElement = NULL;
138 classinfo *class_java_lang_reflect_Constructor = NULL;
139 classinfo *class_java_lang_reflect_Field = NULL;
140 classinfo *class_java_lang_reflect_Method = NULL;
141 classinfo *class_java_security_PrivilegedAction = NULL;
142 classinfo *class_java_util_Vector = NULL;
143
144 classinfo *arrayclass_java_lang_Object = NULL;
145
146
147 /* pseudo classes for the typechecker */
148
149 classinfo *pseudo_class_Arraystub = NULL;
150 classinfo *pseudo_class_Null = NULL;
151 classinfo *pseudo_class_New = NULL;
152
153
154 /* class_set_packagename *******************************************************
155
156    Derive the package name from the class name and store it in the struct.
157
158 *******************************************************************************/
159
160 void class_set_packagename(classinfo *c)
161 {
162         char *p = UTF_END(c->name) - 1;
163         char *start = c->name->text;
164
165         /* set the package name */
166         /* classes in the unnamed package keep packagename == NULL */
167
168         if (c->name->text[0] == '[') {
169                 /* set packagename of arrays to the element's package */
170
171                 for (; *start == '['; start++);
172
173                 /* skip the 'L' in arrays of references */
174                 if (*start == 'L')
175                         start++;
176
177                 for (; (p > start) && (*p != '/'); --p);
178
179                 c->packagename = utf_new(start, p - start);
180
181         } else {
182                 for (; (p > start) && (*p != '/'); --p);
183
184                 c->packagename = utf_new(start, p - start);
185         }
186 }
187
188
189 /* class_create_classinfo ******************************************************
190
191    Create a new classinfo struct. The class name is set to the given utf *,
192    most other fields are initialized to zero.
193
194    Note: classname may be NULL. In this case a not-yet-named classinfo is
195          created. The name must be filled in later and class_set_packagename
196                  must be called after that.
197
198 *******************************************************************************/
199
200 classinfo *class_create_classinfo(utf *classname)
201 {
202         classinfo *c;
203
204 #if defined(STATISTICS)
205         if (opt_stat)
206                 count_class_infos += sizeof(classinfo);
207 #endif
208
209         /* we use a safe name for temporarily unnamed classes */
210         if (!classname)
211                 classname = utf_not_named_yet;
212
213         if (initverbose)
214                 log_message_utf("Creating class: ", classname);
215
216         /* GCNEW_UNCOLLECTABLE clears the allocated memory */
217
218         c = GCNEW_UNCOLLECTABLE(classinfo, 1);
219         /*c=NEW(classinfo);*/
220         c->name = classname;
221         
222         if (classname != utf_not_named_yet) {
223                 class_set_packagename(c);
224         }
225
226 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
227         initObjectLock(&c->header);
228 #endif
229
230         return c;
231 }
232
233 /* class_freepool **************************************************************
234
235         Frees all resources used by this classes Constant Pool.
236
237 *******************************************************************************/
238
239 static void class_freecpool(classinfo *c)
240 {
241         u4 idx;
242         u4 tag;
243         voidptr info;
244         
245         if (c->cptags && c->cpinfos) {
246                 for (idx = 0; idx < c->cpcount; idx++) {
247                         tag = c->cptags[idx];
248                         info = c->cpinfos[idx];
249                 
250                         if (info != NULL) {
251                                 switch (tag) {
252                                 case CONSTANT_Fieldref:
253                                 case CONSTANT_Methodref:
254                                 case CONSTANT_InterfaceMethodref:
255                                         FREE(info, constant_FMIref);
256                                         break;
257                                 case CONSTANT_Integer:
258                                         FREE(info, constant_integer);
259                                         break;
260                                 case CONSTANT_Float:
261                                         FREE(info, constant_float);
262                                         break;
263                                 case CONSTANT_Long:
264                                         FREE(info, constant_long);
265                                         break;
266                                 case CONSTANT_Double:
267                                         FREE(info, constant_double);
268                                         break;
269                                 case CONSTANT_NameAndType:
270                                         FREE(info, constant_nameandtype);
271                                         break;
272                                 }
273                         }
274                 }
275         }
276
277         if (c->cptags)
278                 MFREE(c->cptags, u1, c->cpcount);
279
280         if (c->cpinfos)
281                 MFREE(c->cpinfos, voidptr, c->cpcount);
282 }
283
284
285 /* class_getconstant ***********************************************************
286
287    Retrieves the value at position 'pos' of the constantpool of a
288    class. If the type of the value is other than 'ctype', an error is
289    thrown.
290
291 *******************************************************************************/
292
293 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
294 {
295         /* check index and type of constantpool entry */
296         /* (pos == 0 is caught by type comparison) */
297
298         if (pos >= c->cpcount || c->cptags[pos] != ctype) {
299                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
300                 return NULL;
301         }
302
303         return c->cpinfos[pos];
304 }
305
306
307 /* innerclass_getconstant ******************************************************
308
309    Like class_getconstant, but if cptags is ZERO, null is returned.
310         
311 *******************************************************************************/
312
313 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
314 {
315         /* invalid position in constantpool */
316         if (pos >= c->cpcount) {
317                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
318                 return NULL;
319         }
320
321         /* constantpool entry of type 0 */      
322         if (!c->cptags[pos])
323                 return NULL;
324
325         /* check type of constantpool entry */
326         if (c->cptags[pos] != ctype) {
327                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
328                 return NULL;
329         }
330                 
331         return c->cpinfos[pos];
332 }
333
334
335 /* class_free ******************************************************************
336
337    Frees all resources used by the class.
338
339 *******************************************************************************/
340
341 void class_free(classinfo *c)
342 {
343         s4 i;
344         vftbl_t *v;
345                 
346         class_freecpool(c);
347
348         if (c->interfaces)
349                 MFREE(c->interfaces, classinfo*, c->interfacescount);
350
351         if (c->fields) {
352                 for (i = 0; i < c->fieldscount; i++)
353                         field_free(&(c->fields[i]));
354 /*      MFREE(c->fields, fieldinfo, c->fieldscount); */
355         }
356         
357         if (c->methods) {
358                 for (i = 0; i < c->methodscount; i++)
359                         method_free(&(c->methods[i]));
360                 MFREE(c->methods, methodinfo, c->methodscount);
361         }
362
363         if ((v = c->vftbl) != NULL) {
364                 if (v->arraydesc)
365                         mem_free(v->arraydesc,sizeof(arraydescriptor));
366                 
367                 for (i = 0; i < v->interfacetablelength; i++) {
368                         MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
369                 }
370                 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
371
372                 i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
373                     sizeof(methodptr*) * (v->interfacetablelength -
374                                          (v->interfacetablelength > 0));
375                 v = (vftbl_t*) (((methodptr*) v) -
376                                                 (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
377                 mem_free(v, i);
378         }
379
380         if (c->innerclass)
381                 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
382
383         /*      if (c->classvftbl)
384                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
385         
386 /*      GCFREE(c); */
387 }
388
389
390 /* get_array_class *************************************************************
391
392    Returns the array class with the given name for the given
393    classloader, or NULL if an exception occurred.
394
395    Note: This function does eager loading. 
396
397 *******************************************************************************/
398
399 static classinfo *get_array_class(utf *name,java_objectheader *initloader,
400                                                                                         java_objectheader *defloader,bool link)
401 {
402         classinfo *c;
403         
404         /* lookup this class in the classcache */
405         c = classcache_lookup(initloader,name);
406         if (!c)
407                 c = classcache_lookup_defined(defloader,name);
408
409         if (!c) {
410                 /* we have to create it */
411                 c = class_create_classinfo(name);
412                 c = load_newly_created_array(c,initloader);
413                 if (c == NULL)
414                         return NULL;
415         }
416
417         CLASS_ASSERT(c);
418         CLASS_ASSERT(c->loaded);
419         CLASS_ASSERT(c->classloader == defloader);
420
421         if (link && !c->linked)
422                 if (!link_class(c))
423                         return NULL;
424
425         CLASS_ASSERT(!link || c->linked);
426
427         return c;
428 }
429
430
431 /* class_array_of **************************************************************
432
433    Returns an array class with the given component class. The array
434    class is dynamically created if neccessary.
435
436 *******************************************************************************/
437
438 classinfo *class_array_of(classinfo *component, bool link)
439 {
440     s4 namelen;
441     char *namebuf;
442
443     /* Assemble the array class name */
444     namelen = component->name->blength;
445     
446     if (component->name->text[0] == '[') {
447         /* the component is itself an array */
448         namebuf = DMNEW(char, namelen + 1);
449         namebuf[0] = '[';
450         MCOPY(namebuf + 1, component->name->text, char, namelen);
451         namelen++;
452
453     } else {
454         /* the component is a non-array class */
455         namebuf = DMNEW(char, namelen + 3);
456         namebuf[0] = '[';
457         namebuf[1] = 'L';
458         MCOPY(namebuf + 2, component->name->text, char, namelen);
459         namebuf[2 + namelen] = ';';
460         namelen += 3;
461     }
462
463         return get_array_class(utf_new(namebuf, namelen),
464                                                    component->classloader,
465                                                    component->classloader,
466                                                    link);
467 }
468
469
470 /* class_multiarray_of *********************************************************
471
472    Returns an array class with the given dimension and element class.
473    The array class is dynamically created if neccessary.
474
475 *******************************************************************************/
476
477 classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
478 {
479     s4 namelen;
480     char *namebuf;
481
482         if (dim < 1) {
483                 log_text("Invalid array dimension requested");
484                 assert(0);
485         }
486
487     /* Assemble the array class name */
488     namelen = element->name->blength;
489     
490     if (element->name->text[0] == '[') {
491         /* the element is itself an array */
492         namebuf = DMNEW(char, namelen + dim);
493         memcpy(namebuf + dim, element->name->text, namelen);
494         namelen += dim;
495     }
496     else {
497         /* the element is a non-array class */
498         namebuf = DMNEW(char, namelen + 2 + dim);
499         namebuf[dim] = 'L';
500         memcpy(namebuf + dim + 1, element->name->text, namelen);
501         namelen += (2 + dim);
502         namebuf[namelen - 1] = ';';
503     }
504         memset(namebuf, '[', dim);
505
506         return get_array_class(utf_new(namebuf, namelen),
507                                                    element->classloader,
508                                                    element->classloader,
509                                                    link);
510 }
511
512
513 /* class_lookup_classref *******************************************************
514
515    Looks up the constant_classref for a given classname in the classref
516    tables of a class.
517
518    IN:
519        cls..............the class containing the reference
520            name.............the name of the class refered to
521
522     RETURN VALUE:
523            a pointer to a constant_classref, or 
524            NULL if the reference was not found
525    
526 *******************************************************************************/
527
528 constant_classref *class_lookup_classref(classinfo *cls, utf *name)
529 {
530         constant_classref *ref;
531         extra_classref *xref;
532         int count;
533
534         CLASS_ASSERT(cls);
535         CLASS_ASSERT(name);
536         CLASS_ASSERT(!cls->classrefcount || cls->classrefs);
537         
538         /* first search the main classref table */
539         count = cls->classrefcount;
540         ref = cls->classrefs;
541         for (; count; --count, ++ref)
542                 if (ref->name == name)
543                         return ref;
544
545         /* next try the list of extra classrefs */
546         for (xref = cls->extclassrefs; xref; xref = xref->next) {
547                 if (xref->classref.name == name)
548                         return &(xref->classref);
549         }
550
551         /* not found */
552         return NULL;
553 }
554
555
556 /* class_get_classref **********************************************************
557
558    Returns the constant_classref for a given classname.
559
560    IN:
561        cls..............the class containing the reference
562            name.............the name of the class refered to
563
564    RETURN VALUE:
565        a pointer to a constant_classref (never NULL)
566
567    NOTE:
568        The given name is not checked for validity!
569    
570 *******************************************************************************/
571
572 constant_classref *class_get_classref(classinfo *cls, utf *name)
573 {
574         constant_classref *ref;
575         extra_classref *xref;
576
577         CLASS_ASSERT(cls);
578         CLASS_ASSERT(name);
579
580         ref = class_lookup_classref(cls,name);
581         if (ref)
582                 return ref;
583
584         xref = NEW(extra_classref);
585         CLASSREF_INIT(xref->classref,cls,name);
586
587         xref->next = cls->extclassrefs;
588         cls->extclassrefs = xref;
589
590         return &(xref->classref);
591 }
592
593
594 /* class_get_self_classref *****************************************************
595
596    Returns the constant_classref to the class itself.
597
598    IN:
599        cls..............the class containing the reference
600
601    RETURN VALUE:
602        a pointer to a constant_classref (never NULL)
603
604 *******************************************************************************/
605
606 constant_classref *class_get_self_classref(classinfo *cls)
607 {
608         /* XXX this should be done in a faster way. Maybe always make */
609         /* the classref of index 0 a self reference.                  */
610         return class_get_classref(cls,cls->name);
611 }
612
613 /* class_get_classref_multiarray_of ********************************************
614
615    Returns an array type reference with the given dimension and element class
616    reference.
617
618    IN:
619        dim..............the requested dimension
620                             dim must be in [1;255]. This is NOT checked!
621            ref..............the component class reference
622
623    RETURN VALUE:
624        a pointer to the class reference for the array type
625
626    NOTE:
627        The referer of `ref` is used as the referer for the new classref.
628
629 *******************************************************************************/
630
631 constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
632 {
633     s4 namelen;
634     char *namebuf;
635
636         CLASS_ASSERT(ref);
637         CLASS_ASSERT(dim >= 1 && dim <= 255);
638
639     /* Assemble the array class name */
640     namelen = ref->name->blength;
641     
642     if (ref->name->text[0] == '[') {
643         /* the element is itself an array */
644         namebuf = DMNEW(char, namelen + dim);
645         memcpy(namebuf + dim, ref->name->text, namelen);
646         namelen += dim;
647     }
648     else {
649         /* the element is a non-array class */
650         namebuf = DMNEW(char, namelen + 2 + dim);
651         namebuf[dim] = 'L';
652         memcpy(namebuf + dim + 1, ref->name->text, namelen);
653         namelen += (2 + dim);
654         namebuf[namelen - 1] = ';';
655     }
656         memset(namebuf, '[', dim);
657
658     return class_get_classref(ref->referer,utf_new(namebuf, namelen));
659 }
660
661
662 /* class_get_classref_component_of *********************************************
663
664    Returns the component classref of a given array type reference
665
666    IN:
667        ref..............the array type reference
668
669    RETURN VALUE:
670        a reference to the component class, or
671            NULL if `ref` is not an object array type reference
672
673    NOTE:
674        The referer of `ref` is used as the referer for the new classref.
675
676 *******************************************************************************/
677
678 constant_classref *class_get_classref_component_of(constant_classref *ref)
679 {
680         s4 namelen;
681         char *name;
682         
683         CLASS_ASSERT(ref);
684
685         name = ref->name->text;
686         if (*name++ != '[')
687                 return NULL;
688         
689         namelen = ref->name->blength - 1;
690         if (*name == 'L') {
691                 name++;
692                 namelen -= 2;
693         }
694         else if (*name != '[') {
695                 return NULL;
696         }
697
698     return class_get_classref(ref->referer, utf_new(name, namelen));
699 }
700
701
702 /* class_findmethod ************************************************************
703         
704    Searches a 'classinfo' structure for a method having the given name
705    and descriptor. If descriptor is NULL, it is ignored.
706
707 *******************************************************************************/
708
709 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
710 {
711         methodinfo *m;
712         s4          i;
713
714         for (i = 0; i < c->methodscount; i++) {
715                 m = &(c->methods[i]);
716
717                 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
718                         return m;
719         }
720
721         return NULL;
722 }
723
724
725 /************************* Function: class_findmethod_approx ******************
726         
727         like class_findmethod but ignores the return value when comparing the
728         descriptor.
729
730 *******************************************************************************/
731
732 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
733 {
734         s4 i;
735
736         for (i = 0; i < c->methodscount; i++) {
737                 if (c->methods[i].name == name) {
738                         utf *meth_descr = c->methods[i].descriptor;
739                         
740                         if (desc == NULL) 
741                                 /* ignore type */
742                                 return &(c->methods[i]);
743
744                         if (desc->blength <= meth_descr->blength) {
745                                 /* current position in utf text   */
746                                 char *desc_utf_ptr = desc->text;      
747                                 char *meth_utf_ptr = meth_descr->text;                                    
748                                 /* points behind utf strings */
749                                 char *desc_end = UTF_END(desc);         
750                                 char *meth_end = UTF_END(meth_descr);   
751                                 char ch;
752
753                                 /* compare argument types */
754                                 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
755
756                                         if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
757                                                 break; /* no match */
758
759                                         if (ch == ')')
760                                                 return &(c->methods[i]); /* all parameter types equal */
761                                 }
762                         }
763                 }
764         }
765
766         return NULL;
767 }
768
769
770 /* class_resolvemethod *********************************************************
771         
772    Searches a class and it's super classes for a method.
773
774    Superinterfaces are *not* searched.
775
776 *******************************************************************************/
777
778 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
779 {
780         methodinfo *m;
781
782         while (c) {
783                 m = class_findmethod(c, name, desc);
784
785                 if (m)
786                         return m;
787
788                 /* JVM Specification bug: 
789
790                    It is important NOT to resolve special <init> and <clinit>
791                    methods to super classes or interfaces; yet, this is not
792                    explicited in the specification.  Section 5.4.3.3 should be
793                    updated appropriately.  */
794
795                 if (name == utf_init || name == utf_clinit)
796                         return NULL;
797
798                 c = c->super.cls;
799         }
800
801         return NULL;
802 }
803
804
805 /* class_resolveinterfacemethod_intern *****************************************
806
807    Internally used helper function. Do not use this directly.
808
809 *******************************************************************************/
810
811 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
812                                                                                                            utf *name, utf *desc)
813 {
814         methodinfo *m;
815         s4          i;
816         
817         m = class_findmethod(c, name, desc);
818
819         if (m)
820                 return m;
821
822         /* try the superinterfaces */
823
824         for (i = 0; i < c->interfacescount; i++) {
825                 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
826                                                                                                 name, desc);
827
828                 if (m)
829                         return m;
830         }
831         
832         return NULL;
833 }
834
835
836 /* class_resolveclassmethod ****************************************************
837         
838    Resolves a reference from REFERER to a method with NAME and DESC in
839    class C.
840
841    If the method cannot be resolved the return value is NULL. If
842    EXCEPT is true *exceptionptr is set, too.
843
844 *******************************************************************************/
845
846 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
847                                                                          classinfo *referer, bool except)
848 {
849         classinfo  *cls;
850         methodinfo *m;
851         s4          i;
852         char       *msg;
853         s4          msglen;
854
855         /* XXX resolve class c */
856         /* XXX check access from REFERER to C */
857         
858 /*      if (c->flags & ACC_INTERFACE) { */
859 /*              if (except) */
860 /*                      *exceptionptr = */
861 /*                              new_exception(string_java_lang_IncompatibleClassChangeError); */
862 /*              return NULL; */
863 /*      } */
864
865         /* try class c and its superclasses */
866
867         cls = c;
868
869         m = class_resolvemethod(cls, name, desc);
870
871         if (m)
872                 goto found;
873
874         /* try the superinterfaces */
875
876         for (i = 0; i < c->interfacescount; i++) {
877                 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
878                                                                                                  name, desc);
879
880                 if (m)
881                         goto found;
882         }
883         
884         if (except) {
885                 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
886                         utf_strlen(desc) + strlen("0");
887
888                 msg = MNEW(char, msglen);
889
890                 utf_sprint(msg, c->name);
891                 strcat(msg, ".");
892                 utf_sprint(msg + strlen(msg), name);
893                 utf_sprint(msg + strlen(msg), desc);
894
895                 *exceptionptr =
896                         new_exception_message(string_java_lang_NoSuchMethodError, msg);
897
898                 MFREE(msg, char, msglen);
899         }
900
901         return NULL;
902
903  found:
904         if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
905                 if (except)
906                         *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
907
908                 return NULL;
909         }
910
911         /* XXX check access rights */
912
913         return m;
914 }
915
916
917 /* class_resolveinterfacemethod ************************************************
918
919    Resolves a reference from REFERER to a method with NAME and DESC in
920    interface C.
921
922    If the method cannot be resolved the return value is NULL. If
923    EXCEPT is true *exceptionptr is set, too.
924
925 *******************************************************************************/
926
927 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
928                                                                                  classinfo *referer, bool except)
929 {
930         methodinfo *mi;
931
932         /* XXX resolve class c */
933         /* XXX check access from REFERER to C */
934         
935         if (!(c->flags & ACC_INTERFACE)) {
936                 if (except)
937                         *exceptionptr =
938                                 new_exception(string_java_lang_IncompatibleClassChangeError);
939
940                 return NULL;
941         }
942
943         mi = class_resolveinterfacemethod_intern(c, name, desc);
944
945         if (mi)
946                 return mi;
947
948         /* try class java.lang.Object */
949
950         mi = class_findmethod(class_java_lang_Object, name, desc);
951
952         if (mi)
953                 return mi;
954
955         if (except)
956                 *exceptionptr =
957                         new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
958
959         return NULL;
960 }
961
962
963 /* class_findfield *************************************************************
964         
965    Searches for field with specified name and type in a classinfo
966    structure. If no such field is found NULL is returned.
967
968 *******************************************************************************/
969
970 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
971 {
972         s4 i;
973
974         for (i = 0; i < c->fieldscount; i++)
975                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
976                         return &(c->fields[i]);
977
978         if (c->super.cls)
979                 return class_findfield(c->super.cls, name, desc);
980
981         return NULL;
982 }
983
984
985 /* class_findfield_approx ******************************************************
986         
987    Searches in 'classinfo'-structure for a field with the specified
988    name.
989
990 *******************************************************************************/
991  
992 fieldinfo *class_findfield_by_name(classinfo *c, utf *name)
993 {
994         s4 i;
995
996         /* get field index */
997
998         i = class_findfield_index_by_name(c, name);
999
1000         /* field was not found, return */
1001
1002         if (i == -1)
1003                 return NULL;
1004
1005         /* return field address */
1006
1007         return &(c->fields[i]);
1008 }
1009
1010
1011 s4 class_findfield_index_by_name(classinfo *c, utf *name)
1012 {
1013         s4 i;
1014
1015         for (i = 0; i < c->fieldscount; i++) {
1016                 /* compare field names */
1017
1018                 if ((c->fields[i].name == name))
1019                         return i;
1020         }
1021
1022         /* field was not found, raise exception */      
1023
1024         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
1025
1026         return -1;
1027 }
1028
1029
1030 /****************** Function: class_resolvefield_int ***************************
1031
1032     This is an internally used helper function. Do not use this directly.
1033
1034         Tries to resolve a field having the given name and type.
1035     If the field cannot be resolved, NULL is returned.
1036
1037 *******************************************************************************/
1038
1039 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
1040 {
1041         fieldinfo *fi;
1042         s4         i;
1043
1044         /* search for field in class c */
1045
1046         for (i = 0; i < c->fieldscount; i++) { 
1047                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
1048                         return &(c->fields[i]);
1049                 }
1050     }
1051
1052         /* try superinterfaces recursively */
1053
1054         for (i = 0; i < c->interfacescount; i++) {
1055                 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
1056                 if (fi)
1057                         return fi;
1058         }
1059
1060         /* try superclass */
1061
1062         if (c->super.cls)
1063                 return class_resolvefield_int(c->super.cls, name, desc);
1064
1065         /* not found */
1066
1067         return NULL;
1068 }
1069
1070
1071 /********************* Function: class_resolvefield ***************************
1072         
1073         Resolves a reference from REFERER to a field with NAME and DESC in class C.
1074
1075     If the field cannot be resolved the return value is NULL. If EXCEPT is
1076     true *exceptionptr is set, too.
1077
1078 *******************************************************************************/
1079
1080 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
1081                                                           classinfo *referer, bool except)
1082 {
1083         fieldinfo *fi;
1084
1085         /* XXX resolve class c */
1086         /* XXX check access from REFERER to C */
1087         
1088         fi = class_resolvefield_int(c, name, desc);
1089
1090         if (!fi) {
1091                 if (except)
1092                         *exceptionptr =
1093                                 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
1094                                                                                  name);
1095
1096                 return NULL;
1097         }
1098
1099         /* XXX check access rights */
1100
1101         return fi;
1102 }
1103
1104
1105 /* class_issubclass ************************************************************
1106
1107    Checks if sub is a descendant of super.
1108         
1109 *******************************************************************************/
1110
1111 bool class_issubclass(classinfo *sub, classinfo *super)
1112 {
1113         for (;;) {
1114                 if (!sub)
1115                         return false;
1116
1117                 if (sub == super)
1118                         return true;
1119
1120                 sub = sub->super.cls;
1121         }
1122 }
1123
1124
1125 void class_showconstanti(classinfo *c, int ii) 
1126 {
1127         u4 i = ii;
1128         voidptr e;
1129                 
1130         e = c->cpinfos [i];
1131         printf ("#%d:  ", (int) i);
1132         if (e) {
1133                 switch (c->cptags [i]) {
1134                 case CONSTANT_Class:
1135                         printf("Classreference -> ");
1136                         utf_display(((constant_classref*)e)->name);
1137                         break;
1138                                 
1139                 case CONSTANT_Fieldref:
1140                         printf("Fieldref -> "); goto displayFMIi;
1141                 case CONSTANT_Methodref:
1142                         printf("Methodref -> "); goto displayFMIi;
1143                 case CONSTANT_InterfaceMethodref:
1144                         printf("InterfaceMethod -> "); goto displayFMIi;
1145                 displayFMIi:
1146                         {
1147                                 constant_FMIref *fmi = e;
1148                                 utf_display(fmi->classref->name);
1149                                 printf(".");
1150                                 utf_display(fmi->name);
1151                                 printf(" ");
1152                                 utf_display(fmi->descriptor);
1153                         }
1154                         break;
1155
1156                 case CONSTANT_String:
1157                         printf("String -> ");
1158                         utf_display(e);
1159                         break;
1160                 case CONSTANT_Integer:
1161                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
1162                         break;
1163                 case CONSTANT_Float:
1164                         printf("Float -> %f", ((constant_float*)e)->value);
1165                         break;
1166                 case CONSTANT_Double:
1167                         printf("Double -> %f", ((constant_double*)e)->value);
1168                         break;
1169                 case CONSTANT_Long:
1170                         {
1171                                 u8 v = ((constant_long*)e)->value;
1172 #if U8_AVAILABLE
1173                                 printf("Long -> %ld", (long int) v);
1174 #else
1175                                 printf("Long -> HI: %ld, LO: %ld\n", 
1176                                             (long int) v.high, (long int) v.low);
1177 #endif 
1178                         }
1179                         break;
1180                 case CONSTANT_NameAndType:
1181                         { 
1182                                 constant_nameandtype *cnt = e;
1183                                 printf("NameAndType: ");
1184                                 utf_display(cnt->name);
1185                                 printf(" ");
1186                                 utf_display(cnt->descriptor);
1187                         }
1188                         break;
1189                 case CONSTANT_Utf8:
1190                         printf("Utf8 -> ");
1191                         utf_display(e);
1192                         break;
1193                 default: 
1194                         log_text("Invalid type of ConstantPool-Entry");
1195                         assert(0);
1196                 }
1197         }
1198         printf("\n");
1199 }
1200
1201
1202 void class_showconstantpool (classinfo *c) 
1203 {
1204         u4 i;
1205         voidptr e;
1206
1207         printf ("---- dump of constant pool ----\n");
1208
1209         for (i=0; i<c->cpcount; i++) {
1210                 printf ("#%d:  ", (int) i);
1211                 
1212                 e = c -> cpinfos [i];
1213                 if (e) {
1214                         
1215                         switch (c -> cptags [i]) {
1216                         case CONSTANT_Class:
1217                                 printf ("Classreference -> ");
1218                                 utf_display ( ((constant_classref*)e) -> name );
1219                                 break;
1220                                 
1221                         case CONSTANT_Fieldref:
1222                                 printf ("Fieldref -> "); goto displayFMI;
1223                         case CONSTANT_Methodref:
1224                                 printf ("Methodref -> "); goto displayFMI;
1225                         case CONSTANT_InterfaceMethodref:
1226                                 printf ("InterfaceMethod -> "); goto displayFMI;
1227                         displayFMI:
1228                                 {
1229                                         constant_FMIref *fmi = e;
1230                                         utf_display ( fmi->classref->name );
1231                                         printf (".");
1232                                         utf_display ( fmi->name);
1233                                         printf (" ");
1234                                         utf_display ( fmi->descriptor );
1235                                 }
1236                                 break;
1237
1238                         case CONSTANT_String:
1239                                 printf ("String -> ");
1240                                 utf_display (e);
1241                                 break;
1242                         case CONSTANT_Integer:
1243                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
1244                                 break;
1245                         case CONSTANT_Float:
1246                                 printf ("Float -> %f", ((constant_float*)e) -> value);
1247                                 break;
1248                         case CONSTANT_Double:
1249                                 printf ("Double -> %f", ((constant_double*)e) -> value);
1250                                 break;
1251                         case CONSTANT_Long:
1252                                 {
1253                                         u8 v = ((constant_long*)e) -> value;
1254 #if U8_AVAILABLE
1255                                         printf ("Long -> %ld", (long int) v);
1256 #else
1257                                         printf ("Long -> HI: %ld, LO: %ld\n", 
1258                                                         (long int) v.high, (long int) v.low);
1259 #endif 
1260                                 }
1261                                 break;
1262                         case CONSTANT_NameAndType:
1263                                 {
1264                                         constant_nameandtype *cnt = e;
1265                                         printf ("NameAndType: ");
1266                                         utf_display (cnt->name);
1267                                         printf (" ");
1268                                         utf_display (cnt->descriptor);
1269                                 }
1270                                 break;
1271                         case CONSTANT_Utf8:
1272                                 printf ("Utf8 -> ");
1273                                 utf_display (e);
1274                                 break;
1275                         default: 
1276                                 log_text("Invalid type of ConstantPool-Entry");
1277                                 assert(0);
1278                         }
1279                 }
1280
1281                 printf ("\n");
1282         }
1283 }
1284
1285
1286
1287 /********** Function: class_showmethods   (debugging only) *************/
1288
1289 void class_showmethods (classinfo *c)
1290 {
1291         s4 i;
1292         
1293         printf ("--------- Fields and Methods ----------------\n");
1294         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
1295
1296         printf ("This: "); utf_display (c->name); printf ("\n");
1297         if (c->super.cls) {
1298                 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
1299                 }
1300         printf ("Index: %d\n", c->index);
1301         
1302         printf ("interfaces:\n");       
1303         for (i=0; i < c-> interfacescount; i++) {
1304                 printf ("   ");
1305                 utf_display (c -> interfaces[i].cls -> name);
1306                 printf (" (%d)\n", c->interfaces[i].cls -> index);
1307                 }
1308
1309         printf ("fields:\n");           
1310         for (i=0; i < c -> fieldscount; i++) {
1311                 field_display (&(c -> fields[i]));
1312                 }
1313
1314         printf ("methods:\n");
1315         for (i=0; i < c -> methodscount; i++) {
1316                 methodinfo *m = &(c->methods[i]);
1317                 if ( !(m->flags & ACC_STATIC)) 
1318                         printf ("vftblindex: %d   ", m->vftblindex);
1319
1320                 method_display ( m );
1321
1322                 }
1323
1324         printf ("Virtual function table:\n");
1325         for (i=0; i<c->vftbl->vftbllength; i++) {
1326                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
1327                 }
1328
1329 }
1330
1331
1332 /*
1333  * These are local overrides for various environment variables in Emacs.
1334  * Please do not remove this and leave it at the end of the file, where
1335  * Emacs will automagically detect them.
1336  * ---------------------------------------------------------------------
1337  * Local variables:
1338  * mode: c
1339  * indent-tabs-mode: t
1340  * c-basic-offset: 4
1341  * tab-width: 4
1342  * End:
1343  */