* src/threads/lock-common.h: New file.
[cacao.git] / src / vmcore / class.c
1 /* src/vmcore/class.c - class related functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: class.c 7813 2007-04-25 19:20:13Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "vm/types.h"
38
39 #include "arch.h"
40
41 #include "mm/memory.h"
42
43 #include "threads/lock-common.h"
44
45 #include "toolbox/logging.h"
46
47 #include "vm/exceptions.h"
48 #include "vm/global.h"
49
50 #include "vm/jit/asmpart.h"
51
52 #include "vmcore/class.h"
53 #include "vmcore/classcache.h"
54 #include "vmcore/loader.h"
55 #include "vmcore/options.h"
56
57 #if defined(ENABLE_STATISTICS)
58 # include "vmcore/statistics.h"
59 #endif
60
61 #include "vmcore/suck.h"
62 #include "vmcore/utf8.h"
63
64
65 /* global variables ***********************************************************/
66
67 list_t unlinkedclasses;                 /* this is only used for eager class  */
68                                         /* loading                            */
69
70
71 /* frequently used classes ****************************************************/
72
73 /* important system classes */
74
75 classinfo *class_java_lang_Object;
76 classinfo *class_java_lang_Class;
77 classinfo *class_java_lang_ClassLoader;
78 classinfo *class_java_lang_Cloneable;
79 classinfo *class_java_lang_SecurityManager;
80 classinfo *class_java_lang_String;
81 classinfo *class_java_lang_System;
82 classinfo *class_java_lang_Thread;
83 classinfo *class_java_lang_ThreadGroup;
84 classinfo *class_java_lang_VMSystem;
85 classinfo *class_java_lang_VMThread;
86 classinfo *class_java_io_Serializable;
87
88
89 /* system exception classes required in cacao */
90
91 classinfo *class_java_lang_Throwable;
92 classinfo *class_java_lang_Error;
93 classinfo *class_java_lang_LinkageError;
94 classinfo *class_java_lang_NoClassDefFoundError;
95 classinfo *class_java_lang_OutOfMemoryError;
96 classinfo *class_java_lang_VirtualMachineError;
97
98 #if defined(WITH_CLASSPATH_GNU)
99 classinfo *class_java_lang_VMThrowable;
100 #endif
101
102 classinfo *class_java_lang_Exception;
103 classinfo *class_java_lang_ClassCastException;
104 classinfo *class_java_lang_ClassNotFoundException;
105
106 #if defined(ENABLE_JAVASE)
107 classinfo *class_java_lang_Void;
108 #endif
109 classinfo *class_java_lang_Boolean;
110 classinfo *class_java_lang_Byte;
111 classinfo *class_java_lang_Character;
112 classinfo *class_java_lang_Short;
113 classinfo *class_java_lang_Integer;
114 classinfo *class_java_lang_Long;
115 classinfo *class_java_lang_Float;
116 classinfo *class_java_lang_Double;
117
118
119 /* some runtime exception */
120
121 classinfo *class_java_lang_NullPointerException;
122
123
124 /* some classes which may be used more often */
125
126 #if defined(ENABLE_JAVASE)
127 classinfo *class_java_lang_StackTraceElement;
128 classinfo *class_java_lang_reflect_Constructor;
129 classinfo *class_java_lang_reflect_Field;
130 classinfo *class_java_lang_reflect_Method;
131 classinfo *class_java_security_PrivilegedAction;
132 classinfo *class_java_util_Vector;
133
134 classinfo *arrayclass_java_lang_Object;
135 #endif
136
137
138 /* pseudo classes for the typechecker */
139
140 classinfo *pseudo_class_Arraystub;
141 classinfo *pseudo_class_Null;
142 classinfo *pseudo_class_New;
143
144
145 /* class_set_packagename *******************************************************
146
147    Derive the package name from the class name and store it in the struct.
148
149 *******************************************************************************/
150
151 void class_set_packagename(classinfo *c)
152 {
153         char *p = UTF_END(c->name) - 1;
154         char *start = c->name->text;
155
156         /* set the package name */
157         /* classes in the unnamed package keep packagename == NULL */
158
159         if (c->name->text[0] == '[') {
160                 /* set packagename of arrays to the element's package */
161
162                 for (; *start == '['; start++);
163
164                 /* skip the 'L' in arrays of references */
165                 if (*start == 'L')
166                         start++;
167
168                 for (; (p > start) && (*p != '/'); --p);
169
170                 c->packagename = utf_new(start, p - start);
171
172         } else {
173                 for (; (p > start) && (*p != '/'); --p);
174
175                 c->packagename = utf_new(start, p - start);
176         }
177 }
178
179
180 /* class_create_classinfo ******************************************************
181
182    Create a new classinfo struct. The class name is set to the given utf *,
183    most other fields are initialized to zero.
184
185    Note: classname may be NULL. In this case a not-yet-named classinfo is
186          created. The name must be filled in later and class_set_packagename
187                  must be called after that.
188
189 *******************************************************************************/
190
191 classinfo *class_create_classinfo(utf *classname)
192 {
193         classinfo *c;
194
195 #if defined(ENABLE_STATISTICS)
196         if (opt_stat)
197                 size_classinfo += sizeof(classinfo);
198 #endif
199
200         /* we use a safe name for temporarily unnamed classes */
201
202         if (classname == NULL)
203                 classname = utf_not_named_yet;
204
205 #if !defined(NDEBUG)
206         if (initverbose)
207                 log_message_utf("Creating class: ", classname);
208 #endif
209
210         /* GCNEW_UNCOLLECTABLE clears the allocated memory */
211
212         c = GCNEW_UNCOLLECTABLE(classinfo, 1);
213         /*c=NEW(classinfo);*/
214         c->name = classname;
215
216         /* Set the header.vftbl of all loaded classes to the one of
217        java.lang.Class, so Java code can use a class as object. */
218
219         if (class_java_lang_Class != NULL)
220                 if (class_java_lang_Class->vftbl != NULL)
221                         c->object.header.vftbl = class_java_lang_Class->vftbl;
222
223 #if defined(ENABLE_JAVASE)
224         /* check if the class is a reference class and flag it */
225
226         if (classname == utf_java_lang_ref_SoftReference) {
227                 c->flags |= ACC_CLASS_SOFT_REFERENCE;
228         }
229         else if (classname == utf_java_lang_ref_WeakReference) {
230                 c->flags |= ACC_CLASS_WEAK_REFERENCE;
231         }
232         else if (classname == utf_java_lang_ref_PhantomReference) {
233                 c->flags |= ACC_CLASS_PHANTOM_REFERENCE;
234         }
235 #endif
236
237         if (classname != utf_not_named_yet)
238                 class_set_packagename(c);
239
240         LOCK_INIT_OBJECT_LOCK(&c->object.header);
241
242         return c;
243 }
244
245
246 /* class_postset_header_vftbl **************************************************
247
248    Set the header.vftbl of all classes created before java.lang.Class
249    was linked.  This is necessary that Java code can use a class as
250    object.
251
252 *******************************************************************************/
253
254 void class_postset_header_vftbl(void)
255 {
256         classinfo *c;
257         u4 slot;
258         classcache_name_entry *nmen;
259         classcache_class_entry *clsen;
260
261         assert(class_java_lang_Class);
262
263         for (slot = 0; slot < hashtable_classcache.size; slot++) {
264                 nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
265
266                 for (; nmen; nmen = nmen->hashlink) {
267                         /* iterate over all class entries */
268
269                         for (clsen = nmen->classes; clsen; clsen = clsen->next) {
270                                 c = clsen->classobj;
271
272                                 /* now set the the vftbl */
273
274                                 if (c->object.header.vftbl == NULL)
275                                         c->object.header.vftbl = class_java_lang_Class->vftbl;
276                         }
277                 }
278         }
279 }
280
281
282 /* class_load_attribute_sourcefile *********************************************
283
284    SourceFile_attribute {
285        u2 attribute_name_index;
286        u4 attribute_length;
287            u2 sourcefile_index;
288    }
289
290 *******************************************************************************/
291
292 static bool class_load_attribute_sourcefile(classbuffer *cb)
293 {
294         classinfo *c;
295         u4         attribute_length;
296         u2         sourcefile_index;
297         utf       *sourcefile;
298
299         /* get classinfo */
300
301         c = cb->class;
302
303         /* check buffer size */
304
305         if (!suck_check_classbuffer_size(cb, 4 + 2))
306                 return false;
307
308         /* check attribute length */
309
310         attribute_length = suck_u4(cb);
311
312         if (attribute_length != 2) {
313                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
314                 return false;
315         }
316
317         /* there can be no more than one SourceFile attribute */
318
319         if (c->sourcefile != NULL) {
320                 exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
321                 return false;
322         }
323
324         /* get sourcefile */
325
326         sourcefile_index = suck_u2(cb);
327         sourcefile = class_getconstant(c, sourcefile_index, CONSTANT_Utf8);
328
329         if (sourcefile == NULL)
330                 return false;
331
332         /* store sourcefile */
333
334         c->sourcefile = sourcefile;
335
336         return true;
337 }
338
339
340 /* class_load_attribute_enclosingmethod ****************************************
341
342    EnclosingMethod_attribute {
343        u2 attribute_name_index;
344        u4 attribute_length;
345            u2 class_index;
346            u2 method_index;
347    }
348
349 *******************************************************************************/
350
351 #if defined(ENABLE_JAVASE)
352 static bool class_load_attribute_enclosingmethod(classbuffer *cb)
353 {
354         classinfo             *c;
355         u4                     attribute_length;
356         u2                     class_index;
357         u2                     method_index;
358         classref_or_classinfo  cr;
359         constant_nameandtype  *cn;
360
361         /* get classinfo */
362
363         c = cb->class;
364
365         /* check buffer size */
366
367         if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
368                 return false;
369
370         /* check attribute length */
371
372         attribute_length = suck_u4(cb);
373
374         if (attribute_length != 4) {
375                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
376                 return false;
377         }
378
379         /* there can be no more than one EnclosingMethod attribute */
380
381         if (c->enclosingmethod != NULL) {
382                 exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes");
383                 return false;
384         }
385
386         /* get class index */
387
388         class_index = suck_u2(cb);
389         cr.ref = innerclass_getconstant(c, class_index, CONSTANT_Class);
390
391         /* get method index */
392
393         method_index = suck_u2(cb);
394         cn = innerclass_getconstant(c, method_index, CONSTANT_NameAndType);
395
396         /* store info in classinfo */
397
398         c->enclosingclass.any = cr.any;
399         c->enclosingmethod    = cn;
400
401         return true;
402 }
403 #endif /* defined(ENABLE_JAVASE) */
404
405
406 /* class_load_attributes *******************************************************
407
408    Read attributes from ClassFile.
409
410    attribute_info {
411        u2 attribute_name_index;
412        u4 attribute_length;
413        u1 info[attribute_length];
414    }
415
416    InnerClasses_attribute {
417        u2 attribute_name_index;
418        u4 attribute_length;
419    }
420
421 *******************************************************************************/
422
423 bool class_load_attributes(classbuffer *cb)
424 {
425         classinfo *c;
426         u4         i, j;
427         u2         attributes_count;
428         u2         attribute_name_index;
429         utf       *attribute_name;
430
431         c = cb->class;
432
433         /* get attributes count */
434
435         if (!suck_check_classbuffer_size(cb, 2))
436                 return false;
437
438         attributes_count = suck_u2(cb);
439
440         for (i = 0; i < attributes_count; i++) {
441                 /* get attribute name */
442
443                 if (!suck_check_classbuffer_size(cb, 2))
444                         return false;
445
446                 attribute_name_index = suck_u2(cb);
447                 attribute_name =
448                         class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
449
450                 if (attribute_name == NULL)
451                         return false;
452
453                 if (attribute_name == utf_InnerClasses) {
454                         /* InnerClasses */
455
456                         if (c->innerclass != NULL) {
457                                 exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
458                                 return false;
459                         }
460                                 
461                         if (!suck_check_classbuffer_size(cb, 4 + 2))
462                                 return false;
463
464                         /* skip attribute length */
465                         suck_u4(cb);
466
467                         /* number of records */
468                         c->innerclasscount = suck_u2(cb);
469
470                         if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
471                                 return false;
472
473                         /* allocate memory for innerclass structure */
474                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
475
476                         for (j = 0; j < c->innerclasscount; j++) {
477                                 /* The innerclass structure contains a class with an encoded
478                                    name, its defining scope, its simple name and a bitmask of
479                                    the access flags. If an inner class is not a member, its
480                                    outer_class is NULL, if a class is anonymous, its name is
481                                    NULL. */
482                                                                 
483                                 innerclassinfo *info = c->innerclass + j;
484
485                                 info->inner_class.ref =
486                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
487                                 info->outer_class.ref =
488                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
489                                 info->name =
490                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
491                                 info->flags = suck_u2(cb);
492                         }
493                 }
494                 else if (attribute_name == utf_SourceFile) {
495                         /* SourceFile */
496
497                         if (!class_load_attribute_sourcefile(cb))
498                                 return false;
499                 }
500 #if defined(ENABLE_JAVASE)
501                 else if (attribute_name == utf_EnclosingMethod) {
502                         /* EnclosingMethod */
503
504                         if (!class_load_attribute_enclosingmethod(cb))
505                                 return false;
506                 }
507                 else if (attribute_name == utf_Signature) {
508                         /* Signature */
509
510                         if (!loader_load_attribute_signature(cb, &(c->signature)))
511                                 return false;
512                 }
513                 else if (attribute_name == utf_RuntimeVisibleAnnotations) {
514                         /* RuntimeVisibleAnnotations */
515
516                         if (!annotation_load_attribute_runtimevisibleannotations(cb))
517                                 return false;
518                 }
519 #endif
520                 else {
521                         /* unknown attribute */
522
523                         if (!loader_skip_attribute_body(cb))
524                                 return false;
525                 }
526         }
527
528         return true;
529 }
530
531
532 /* class_freepool **************************************************************
533
534         Frees all resources used by this classes Constant Pool.
535
536 *******************************************************************************/
537
538 static void class_freecpool(classinfo *c)
539 {
540         u4 idx;
541         u4 tag;
542         voidptr info;
543         
544         if (c->cptags && c->cpinfos) {
545                 for (idx = 0; idx < c->cpcount; idx++) {
546                         tag = c->cptags[idx];
547                         info = c->cpinfos[idx];
548                 
549                         if (info != NULL) {
550                                 switch (tag) {
551                                 case CONSTANT_Fieldref:
552                                 case CONSTANT_Methodref:
553                                 case CONSTANT_InterfaceMethodref:
554                                         FREE(info, constant_FMIref);
555                                         break;
556                                 case CONSTANT_Integer:
557                                         FREE(info, constant_integer);
558                                         break;
559                                 case CONSTANT_Float:
560                                         FREE(info, constant_float);
561                                         break;
562                                 case CONSTANT_Long:
563                                         FREE(info, constant_long);
564                                         break;
565                                 case CONSTANT_Double:
566                                         FREE(info, constant_double);
567                                         break;
568                                 case CONSTANT_NameAndType:
569                                         FREE(info, constant_nameandtype);
570                                         break;
571                                 }
572                         }
573                 }
574         }
575
576         if (c->cptags)
577                 MFREE(c->cptags, u1, c->cpcount);
578
579         if (c->cpinfos)
580                 MFREE(c->cpinfos, voidptr, c->cpcount);
581 }
582
583
584 /* class_getconstant ***********************************************************
585
586    Retrieves the value at position 'pos' of the constantpool of a
587    class. If the type of the value is other than 'ctype', an error is
588    thrown.
589
590 *******************************************************************************/
591
592 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
593 {
594         /* check index and type of constantpool entry */
595         /* (pos == 0 is caught by type comparison) */
596
597         if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
598                 exceptions_throw_classformaterror(c, "Illegal constant pool index");
599                 return NULL;
600         }
601
602         return c->cpinfos[pos];
603 }
604
605
606 /* innerclass_getconstant ******************************************************
607
608    Like class_getconstant, but if cptags is ZERO, null is returned.
609         
610 *******************************************************************************/
611
612 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
613 {
614         /* invalid position in constantpool */
615
616         if (pos >= c->cpcount) {
617                 exceptions_throw_classformaterror(c, "Illegal constant pool index");
618                 return NULL;
619         }
620
621         /* constantpool entry of type 0 */      
622
623         if (c->cptags[pos] == 0)
624                 return NULL;
625
626         /* check type of constantpool entry */
627
628         if (c->cptags[pos] != ctype) {
629                 exceptions_throw_classformaterror(c, "Illegal constant pool index");
630                 return NULL;
631         }
632                 
633         return c->cpinfos[pos];
634 }
635
636
637 /* class_free ******************************************************************
638
639    Frees all resources used by the class.
640
641 *******************************************************************************/
642
643 void class_free(classinfo *c)
644 {
645         s4 i;
646         vftbl_t *v;
647                 
648         class_freecpool(c);
649
650         if (c->interfaces)
651                 MFREE(c->interfaces, classinfo*, c->interfacescount);
652
653         if (c->fields) {
654                 for (i = 0; i < c->fieldscount; i++)
655                         field_free(&(c->fields[i]));
656 #if defined(ENABLE_CACAO_GC)
657                 MFREE(c->fields, fieldinfo, c->fieldscount);
658 #endif
659         }
660         
661         if (c->methods) {
662                 for (i = 0; i < c->methodscount; i++)
663                         method_free(&(c->methods[i]));
664                 MFREE(c->methods, methodinfo, c->methodscount);
665         }
666
667         if ((v = c->vftbl) != NULL) {
668                 if (v->arraydesc)
669                         mem_free(v->arraydesc,sizeof(arraydescriptor));
670                 
671                 for (i = 0; i < v->interfacetablelength; i++) {
672                         MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
673                 }
674                 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
675
676                 i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
677                     sizeof(methodptr*) * (v->interfacetablelength -
678                                          (v->interfacetablelength > 0));
679                 v = (vftbl_t*) (((methodptr*) v) -
680                                                 (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
681                 mem_free(v, i);
682         }
683
684         if (c->innerclass)
685                 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
686
687         /*      if (c->classvftbl)
688                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
689         
690 /*      GCFREE(c); */
691 }
692
693
694 /* get_array_class *************************************************************
695
696    Returns the array class with the given name for the given
697    classloader, or NULL if an exception occurred.
698
699    Note: This function does eager loading. 
700
701 *******************************************************************************/
702
703 static classinfo *get_array_class(utf *name,java_objectheader *initloader,
704                                                                                         java_objectheader *defloader,bool link)
705 {
706         classinfo *c;
707         
708         /* lookup this class in the classcache */
709         c = classcache_lookup(initloader,name);
710         if (!c)
711                 c = classcache_lookup_defined(defloader,name);
712
713         if (!c) {
714                 /* we have to create it */
715                 c = class_create_classinfo(name);
716                 c = load_newly_created_array(c,initloader);
717                 if (c == NULL)
718                         return NULL;
719         }
720
721         assert(c);
722         assert(c->state & CLASS_LOADED);
723         assert(c->classloader == defloader);
724
725         if (link && !(c->state & CLASS_LINKED))
726                 if (!link_class(c))
727                         return NULL;
728
729         assert(!link || (c->state & CLASS_LINKED));
730
731         return c;
732 }
733
734
735 /* class_array_of **************************************************************
736
737    Returns an array class with the given component class. The array
738    class is dynamically created if neccessary.
739
740 *******************************************************************************/
741
742 classinfo *class_array_of(classinfo *component, bool link)
743 {
744     s4 namelen;
745     char *namebuf;
746         s4 dumpsize;
747         classinfo *c;
748
749         dumpsize = dump_size();
750
751     /* Assemble the array class name */
752     namelen = component->name->blength;
753     
754     if (component->name->text[0] == '[') {
755         /* the component is itself an array */
756         namebuf = DMNEW(char, namelen + 1);
757         namebuf[0] = '[';
758         MCOPY(namebuf + 1, component->name->text, char, namelen);
759         namelen++;
760
761     } else {
762         /* the component is a non-array class */
763         namebuf = DMNEW(char, namelen + 3);
764         namebuf[0] = '[';
765         namebuf[1] = 'L';
766         MCOPY(namebuf + 2, component->name->text, char, namelen);
767         namebuf[2 + namelen] = ';';
768         namelen += 3;
769     }
770
771         c = get_array_class(utf_new(namebuf, namelen),
772                                                 component->classloader,
773                                                 component->classloader,
774                                                 link);
775
776         dump_release(dumpsize);
777
778         return c;
779 }
780
781
782 /* class_multiarray_of *********************************************************
783
784    Returns an array class with the given dimension and element class.
785    The array class is dynamically created if neccessary.
786
787 *******************************************************************************/
788
789 classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
790 {
791     s4 namelen;
792     char *namebuf;
793         s4 dumpsize;
794         classinfo *c;
795
796         dumpsize = dump_size();
797
798         if (dim < 1) {
799                 log_text("Invalid array dimension requested");
800                 assert(0);
801         }
802
803     /* Assemble the array class name */
804     namelen = element->name->blength;
805     
806     if (element->name->text[0] == '[') {
807         /* the element is itself an array */
808         namebuf = DMNEW(char, namelen + dim);
809         memcpy(namebuf + dim, element->name->text, namelen);
810         namelen += dim;
811     }
812     else {
813         /* the element is a non-array class */
814         namebuf = DMNEW(char, namelen + 2 + dim);
815         namebuf[dim] = 'L';
816         memcpy(namebuf + dim + 1, element->name->text, namelen);
817         namelen += (2 + dim);
818         namebuf[namelen - 1] = ';';
819     }
820         memset(namebuf, '[', dim);
821
822         c = get_array_class(utf_new(namebuf, namelen),
823                                                 element->classloader,
824                                                 element->classloader,
825                                                 link);
826
827         dump_release(dumpsize);
828
829         return c;
830 }
831
832
833 /* class_lookup_classref *******************************************************
834
835    Looks up the constant_classref for a given classname in the classref
836    tables of a class.
837
838    IN:
839        cls..............the class containing the reference
840            name.............the name of the class refered to
841
842     RETURN VALUE:
843            a pointer to a constant_classref, or 
844            NULL if the reference was not found
845    
846 *******************************************************************************/
847
848 constant_classref *class_lookup_classref(classinfo *cls, utf *name)
849 {
850         constant_classref *ref;
851         extra_classref *xref;
852         int count;
853
854         assert(cls);
855         assert(name);
856         assert(!cls->classrefcount || cls->classrefs);
857         
858         /* first search the main classref table */
859         count = cls->classrefcount;
860         ref = cls->classrefs;
861         for (; count; --count, ++ref)
862                 if (ref->name == name)
863                         return ref;
864
865         /* next try the list of extra classrefs */
866         for (xref = cls->extclassrefs; xref; xref = xref->next) {
867                 if (xref->classref.name == name)
868                         return &(xref->classref);
869         }
870
871         /* not found */
872         return NULL;
873 }
874
875
876 /* class_get_classref **********************************************************
877
878    Returns the constant_classref for a given classname.
879
880    IN:
881        cls..............the class containing the reference
882            name.............the name of the class refered to
883
884    RETURN VALUE:
885        a pointer to a constant_classref (never NULL)
886
887    NOTE:
888        The given name is not checked for validity!
889    
890 *******************************************************************************/
891
892 constant_classref *class_get_classref(classinfo *cls, utf *name)
893 {
894         constant_classref *ref;
895         extra_classref *xref;
896
897         assert(cls);
898         assert(name);
899
900         ref = class_lookup_classref(cls,name);
901         if (ref)
902                 return ref;
903
904         xref = NEW(extra_classref);
905         CLASSREF_INIT(xref->classref,cls,name);
906
907         xref->next = cls->extclassrefs;
908         cls->extclassrefs = xref;
909
910         return &(xref->classref);
911 }
912
913
914 /* class_get_self_classref *****************************************************
915
916    Returns the constant_classref to the class itself.
917
918    IN:
919        cls..............the class containing the reference
920
921    RETURN VALUE:
922        a pointer to a constant_classref (never NULL)
923
924 *******************************************************************************/
925
926 constant_classref *class_get_self_classref(classinfo *cls)
927 {
928         /* XXX this should be done in a faster way. Maybe always make */
929         /* the classref of index 0 a self reference.                  */
930         return class_get_classref(cls,cls->name);
931 }
932
933 /* class_get_classref_multiarray_of ********************************************
934
935    Returns an array type reference with the given dimension and element class
936    reference.
937
938    IN:
939        dim..............the requested dimension
940                             dim must be in [1;255]. This is NOT checked!
941            ref..............the component class reference
942
943    RETURN VALUE:
944        a pointer to the class reference for the array type
945
946    NOTE:
947        The referer of `ref` is used as the referer for the new classref.
948
949 *******************************************************************************/
950
951 constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
952 {
953     s4 namelen;
954     char *namebuf;
955         s4 dumpsize;
956         constant_classref *cr;
957
958         assert(ref);
959         assert(dim >= 1 && dim <= 255);
960
961         dumpsize = dump_size();
962
963     /* Assemble the array class name */
964     namelen = ref->name->blength;
965     
966     if (ref->name->text[0] == '[') {
967         /* the element is itself an array */
968         namebuf = DMNEW(char, namelen + dim);
969         memcpy(namebuf + dim, ref->name->text, namelen);
970         namelen += dim;
971     }
972     else {
973         /* the element is a non-array class */
974         namebuf = DMNEW(char, namelen + 2 + dim);
975         namebuf[dim] = 'L';
976         memcpy(namebuf + dim + 1, ref->name->text, namelen);
977         namelen += (2 + dim);
978         namebuf[namelen - 1] = ';';
979     }
980         memset(namebuf, '[', dim);
981
982     cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
983
984         dump_release(dumpsize);
985
986         return cr;
987 }
988
989
990 /* class_get_classref_component_of *********************************************
991
992    Returns the component classref of a given array type reference
993
994    IN:
995        ref..............the array type reference
996
997    RETURN VALUE:
998        a reference to the component class, or
999            NULL if `ref` is not an object array type reference
1000
1001    NOTE:
1002        The referer of `ref` is used as the referer for the new classref.
1003
1004 *******************************************************************************/
1005
1006 constant_classref *class_get_classref_component_of(constant_classref *ref)
1007 {
1008         s4 namelen;
1009         char *name;
1010         
1011         assert(ref);
1012
1013         name = ref->name->text;
1014         if (*name++ != '[')
1015                 return NULL;
1016         
1017         namelen = ref->name->blength - 1;
1018         if (*name == 'L') {
1019                 name++;
1020                 namelen -= 2;
1021         }
1022         else if (*name != '[') {
1023                 return NULL;
1024         }
1025
1026     return class_get_classref(ref->referer, utf_new(name, namelen));
1027 }
1028
1029
1030 /* class_findmethod ************************************************************
1031         
1032    Searches a 'classinfo' structure for a method having the given name
1033    and descriptor. If descriptor is NULL, it is ignored.
1034
1035 *******************************************************************************/
1036
1037 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
1038 {
1039         methodinfo *m;
1040         s4          i;
1041
1042         for (i = 0; i < c->methodscount; i++) {
1043                 m = &(c->methods[i]);
1044
1045                 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
1046                         return m;
1047         }
1048
1049         return NULL;
1050 }
1051
1052
1053 /* class_resolvemethod *********************************************************
1054         
1055    Searches a class and it's super classes for a method.
1056
1057    Superinterfaces are *not* searched.
1058
1059 *******************************************************************************/
1060
1061 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
1062 {
1063         methodinfo *m;
1064
1065         while (c) {
1066                 m = class_findmethod(c, name, desc);
1067
1068                 if (m)
1069                         return m;
1070
1071                 /* JVM Specification bug: 
1072
1073                    It is important NOT to resolve special <init> and <clinit>
1074                    methods to super classes or interfaces; yet, this is not
1075                    explicited in the specification.  Section 5.4.3.3 should be
1076                    updated appropriately.  */
1077
1078                 if (name == utf_init || name == utf_clinit)
1079                         return NULL;
1080
1081                 c = c->super.cls;
1082         }
1083
1084         return NULL;
1085 }
1086
1087
1088 /* class_resolveinterfacemethod_intern *****************************************
1089
1090    Internally used helper function. Do not use this directly.
1091
1092 *******************************************************************************/
1093
1094 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
1095                                                                                                            utf *name, utf *desc)
1096 {
1097         methodinfo *m;
1098         s4          i;
1099
1100         /* try to find the method in the class */
1101
1102         m = class_findmethod(c, name, desc);
1103
1104         if (m != NULL)
1105                 return m;
1106
1107         /* no method found? try the superinterfaces */
1108
1109         for (i = 0; i < c->interfacescount; i++) {
1110                 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
1111                                                                                                         name, desc);
1112
1113                 if (m != NULL)
1114                         return m;
1115         }
1116
1117         /* no method found */
1118
1119         return NULL;
1120 }
1121
1122
1123 /* class_resolveclassmethod ****************************************************
1124         
1125    Resolves a reference from REFERER to a method with NAME and DESC in
1126    class C.
1127
1128    If the method cannot be resolved the return value is NULL. If
1129    EXCEPT is true *exceptionptr is set, too.
1130
1131 *******************************************************************************/
1132
1133 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
1134                                                                          classinfo *referer, bool throwexception)
1135 {
1136         classinfo  *cls;
1137         methodinfo *m;
1138         s4          i;
1139
1140 /*      if (c->flags & ACC_INTERFACE) { */
1141 /*              if (throwexception) */
1142 /*                      *exceptionptr = */
1143 /*                              new_exception(string_java_lang_IncompatibleClassChangeError); */
1144 /*              return NULL; */
1145 /*      } */
1146
1147         /* try class c and its superclasses */
1148
1149         cls = c;
1150
1151         m = class_resolvemethod(cls, name, desc);
1152
1153         if (m != NULL)
1154                 goto found;
1155
1156         /* try the superinterfaces */
1157
1158         for (i = 0; i < c->interfacescount; i++) {
1159                 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
1160                                                                                                 name, desc);
1161
1162                 if (m != NULL)
1163                         goto found;
1164         }
1165         
1166         if (throwexception)
1167                 exceptions_throw_nosuchmethoderror(c, name, desc);
1168
1169         return NULL;
1170
1171  found:
1172         if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
1173                 if (throwexception)
1174                         exceptions_throw_abstractmethoderror();
1175
1176                 return NULL;
1177         }
1178
1179         /* XXX check access rights */
1180
1181         return m;
1182 }
1183
1184
1185 /* class_resolveinterfacemethod ************************************************
1186
1187    Resolves a reference from REFERER to a method with NAME and DESC in
1188    interface C.
1189
1190    If the method cannot be resolved the return value is NULL. If
1191    EXCEPT is true *exceptionptr is set, too.
1192
1193 *******************************************************************************/
1194
1195 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
1196                                                                                  classinfo *referer, bool throwexception)
1197 {
1198         methodinfo *mi;
1199
1200         if (!(c->flags & ACC_INTERFACE)) {
1201                 if (throwexception)
1202                         exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
1203
1204                 return NULL;
1205         }
1206
1207         mi = class_resolveinterfacemethod_intern(c, name, desc);
1208
1209         if (mi != NULL)
1210                 return mi;
1211
1212         /* try class java.lang.Object */
1213
1214         mi = class_findmethod(class_java_lang_Object, name, desc);
1215
1216         if (mi != NULL)
1217                 return mi;
1218
1219         if (throwexception)
1220                 exceptions_throw_nosuchmethoderror(c, name, desc);
1221
1222         return NULL;
1223 }
1224
1225
1226 /* class_findfield *************************************************************
1227         
1228    Searches for field with specified name and type in a classinfo
1229    structure. If no such field is found NULL is returned.
1230
1231 *******************************************************************************/
1232
1233 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
1234 {
1235         s4 i;
1236
1237         for (i = 0; i < c->fieldscount; i++)
1238                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1239                         return &(c->fields[i]);
1240
1241         if (c->super.cls)
1242                 return class_findfield(c->super.cls, name, desc);
1243
1244         return NULL;
1245 }
1246
1247
1248 /* class_findfield_approx ******************************************************
1249         
1250    Searches in 'classinfo'-structure for a field with the specified
1251    name.
1252
1253 *******************************************************************************/
1254  
1255 fieldinfo *class_findfield_by_name(classinfo *c, utf *name)
1256 {
1257         s4 i;
1258
1259         /* get field index */
1260
1261         i = class_findfield_index_by_name(c, name);
1262
1263         /* field was not found, return */
1264
1265         if (i == -1)
1266                 return NULL;
1267
1268         /* return field address */
1269
1270         return &(c->fields[i]);
1271 }
1272
1273
1274 s4 class_findfield_index_by_name(classinfo *c, utf *name)
1275 {
1276         s4 i;
1277
1278         for (i = 0; i < c->fieldscount; i++) {
1279                 /* compare field names */
1280
1281                 if ((c->fields[i].name == name))
1282                         return i;
1283         }
1284
1285         /* field was not found, raise exception */      
1286
1287         exceptions_throw_nosuchfielderror(c, name);
1288
1289         return -1;
1290 }
1291
1292
1293 /****************** Function: class_resolvefield_int ***************************
1294
1295     This is an internally used helper function. Do not use this directly.
1296
1297         Tries to resolve a field having the given name and type.
1298     If the field cannot be resolved, NULL is returned.
1299
1300 *******************************************************************************/
1301
1302 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
1303 {
1304         fieldinfo *fi;
1305         s4         i;
1306
1307         /* search for field in class c */
1308
1309         for (i = 0; i < c->fieldscount; i++) { 
1310                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
1311                         return &(c->fields[i]);
1312                 }
1313     }
1314
1315         /* try superinterfaces recursively */
1316
1317         for (i = 0; i < c->interfacescount; i++) {
1318                 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
1319                 if (fi)
1320                         return fi;
1321         }
1322
1323         /* try superclass */
1324
1325         if (c->super.cls)
1326                 return class_resolvefield_int(c->super.cls, name, desc);
1327
1328         /* not found */
1329
1330         return NULL;
1331 }
1332
1333
1334 /********************* Function: class_resolvefield ***************************
1335         
1336         Resolves a reference from REFERER to a field with NAME and DESC in class C.
1337
1338     If the field cannot be resolved the return value is NULL. If EXCEPT is
1339     true *exceptionptr is set, too.
1340
1341 *******************************************************************************/
1342
1343 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
1344                                                           classinfo *referer, bool throwexception)
1345 {
1346         fieldinfo *fi;
1347
1348         fi = class_resolvefield_int(c, name, desc);
1349
1350         if (!fi) {
1351                 if (throwexception)
1352                         exceptions_throw_nosuchfielderror(c, name);
1353
1354                 return NULL;
1355         }
1356
1357         /* XXX check access rights */
1358
1359         return fi;
1360 }
1361
1362
1363 /* class_issubclass ************************************************************
1364
1365    Checks if sub is a descendant of super.
1366         
1367 *******************************************************************************/
1368
1369 bool class_issubclass(classinfo *sub, classinfo *super)
1370 {
1371         for (;;) {
1372                 if (!sub)
1373                         return false;
1374
1375                 if (sub == super)
1376                         return true;
1377
1378                 sub = sub->super.cls;
1379         }
1380 }
1381
1382
1383 /* class_isanysubclass *********************************************************
1384
1385    Checks a subclass relation between two classes. Implemented
1386    interfaces are interpreted as super classes.
1387
1388    Return value: 1 ... sub is subclass of super
1389                  0 ... otherwise
1390
1391 *******************************************************************************/
1392
1393 bool class_isanysubclass(classinfo *sub, classinfo *super)
1394 {
1395         castinfo classvalues;
1396         u4       diffval;
1397         bool     result;
1398
1399         /* This is the trivial case. */
1400
1401         if (sub == super)
1402                 return true;
1403
1404         /* Primitive classes are only subclasses of themselves. */
1405
1406         if ((sub->flags & ACC_CLASS_PRIMITIVE) ||
1407                 (super->flags & ACC_CLASS_PRIMITIVE))
1408                 return false;
1409
1410         /* Check for interfaces. */
1411
1412         if (super->flags & ACC_INTERFACE) {
1413                 result = (sub->vftbl->interfacetablelength > super->index) &&
1414                         (sub->vftbl->interfacetable[-super->index] != NULL);
1415         }
1416         else {
1417                 /* java.lang.Object is the only super class of any
1418                    interface. */
1419
1420                 if (sub->flags & ACC_INTERFACE)
1421                         return (super == class_java_lang_Object);
1422
1423                 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
1424
1425                 diffval = classvalues.sub_baseval - classvalues.super_baseval;
1426                 result  = diffval <= (u4) classvalues.super_diffval;
1427         }
1428
1429         return result;
1430 }
1431
1432
1433 /* class_printflags ************************************************************
1434
1435    Prints flags of a class.
1436
1437 *******************************************************************************/
1438
1439 #if !defined(NDEBUG)
1440 void class_printflags(classinfo *c)
1441 {
1442         if (c == NULL) {
1443                 printf("NULL");
1444                 return;
1445         }
1446
1447         if (c->flags & ACC_PUBLIC)       printf(" PUBLIC");
1448         if (c->flags & ACC_PRIVATE)      printf(" PRIVATE");
1449         if (c->flags & ACC_PROTECTED)    printf(" PROTECTED");
1450         if (c->flags & ACC_STATIC)       printf(" STATIC");
1451         if (c->flags & ACC_FINAL)        printf(" FINAL");
1452         if (c->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
1453         if (c->flags & ACC_VOLATILE)     printf(" VOLATILE");
1454         if (c->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
1455         if (c->flags & ACC_NATIVE)       printf(" NATIVE");
1456         if (c->flags & ACC_INTERFACE)    printf(" INTERFACE");
1457         if (c->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
1458 }
1459 #endif
1460
1461
1462 /* class_print *****************************************************************
1463
1464    Prints classname plus flags.
1465
1466 *******************************************************************************/
1467
1468 #if !defined(NDEBUG)
1469 void class_print(classinfo *c)
1470 {
1471         if (c == NULL) {
1472                 printf("NULL");
1473                 return;
1474         }
1475
1476         utf_display_printable_ascii(c->name);
1477         class_printflags(c);
1478 }
1479 #endif
1480
1481
1482 /* class_classref_print ********************************************************
1483
1484    Prints classname plus referer class.
1485
1486 *******************************************************************************/
1487
1488 #if !defined(NDEBUG)
1489 void class_classref_print(constant_classref *cr)
1490 {
1491         if (cr == NULL) {
1492                 printf("NULL");
1493                 return;
1494         }
1495
1496         utf_display_printable_ascii(cr->name);
1497         printf("(ref.by ");
1498         if (cr->referer)
1499                 class_print(cr->referer);
1500         else
1501                 printf("NULL");
1502         printf(")");
1503 }
1504 #endif
1505
1506
1507 /* class_println ***************************************************************
1508
1509    Prints classname plus flags and new line.
1510
1511 *******************************************************************************/
1512
1513 #if !defined(NDEBUG)
1514 void class_println(classinfo *c)
1515 {
1516         class_print(c);
1517         printf("\n");
1518 }
1519 #endif
1520
1521
1522 /* class_classref_println ******************************************************
1523
1524    Prints classname plus referer class and new line.
1525
1526 *******************************************************************************/
1527
1528 #if !defined(NDEBUG)
1529 void class_classref_println(constant_classref *cr)
1530 {
1531         class_classref_print(cr);
1532         printf("\n");
1533 }
1534 #endif
1535
1536
1537 /* class_classref_or_classinfo_print *******************************************
1538
1539    Prints classname plus referer class.
1540
1541 *******************************************************************************/
1542
1543 #if !defined(NDEBUG)
1544 void class_classref_or_classinfo_print(classref_or_classinfo c)
1545 {
1546         if (c.any == NULL) {
1547                 printf("(classref_or_classinfo) NULL");
1548                 return;
1549         }
1550         if (IS_CLASSREF(c))
1551                 class_classref_print(c.ref);
1552         else
1553                 class_print(c.cls);
1554 }
1555 #endif
1556
1557
1558 /* class_classref_or_classinfo_println *****************************************
1559
1560    Prints classname plus referer class and a newline.
1561
1562 *******************************************************************************/
1563
1564 void class_classref_or_classinfo_println(classref_or_classinfo c)
1565 {
1566         class_classref_or_classinfo_println(c);
1567         printf("\n");
1568 }
1569
1570
1571 /* class_showconstantpool ******************************************************
1572
1573    Dump the constant pool of the given class to stdout.
1574
1575 *******************************************************************************/
1576
1577 #if !defined(NDEBUG)
1578 void class_showconstantpool (classinfo *c) 
1579 {
1580         u4 i;
1581         voidptr e;
1582
1583         printf ("---- dump of constant pool ----\n");
1584
1585         for (i=0; i<c->cpcount; i++) {
1586                 printf ("#%d:  ", (int) i);
1587                 
1588                 e = c -> cpinfos [i];
1589                 if (e) {
1590                         
1591                         switch (c -> cptags [i]) {
1592                         case CONSTANT_Class:
1593                                 printf ("Classreference -> ");
1594                                 utf_display_printable_ascii ( ((constant_classref*)e) -> name );
1595                                 break;
1596                         case CONSTANT_Fieldref:
1597                                 printf ("Fieldref -> ");
1598                                 field_fieldref_print((constant_FMIref *) e);
1599                                 break;
1600                         case CONSTANT_Methodref:
1601                                 printf ("Methodref -> ");
1602                                 method_methodref_print((constant_FMIref *) e);
1603                                 break;
1604                         case CONSTANT_InterfaceMethodref:
1605                                 printf ("InterfaceMethod -> ");
1606                                 method_methodref_print((constant_FMIref *) e);
1607                                 break;
1608                         case CONSTANT_String:
1609                                 printf ("String -> ");
1610                                 utf_display_printable_ascii (e);
1611                                 break;
1612                         case CONSTANT_Integer:
1613                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
1614                                 break;
1615                         case CONSTANT_Float:
1616                                 printf ("Float -> %f", ((constant_float*)e) -> value);
1617                                 break;
1618                         case CONSTANT_Double:
1619                                 printf ("Double -> %f", ((constant_double*)e) -> value);
1620                                 break;
1621                         case CONSTANT_Long:
1622                                 {
1623                                         u8 v = ((constant_long*)e) -> value;
1624 #if U8_AVAILABLE
1625                                         printf ("Long -> %ld", (long int) v);
1626 #else
1627                                         printf ("Long -> HI: %ld, LO: %ld\n", 
1628                                                         (long int) v.high, (long int) v.low);
1629 #endif 
1630                                 }
1631                                 break;
1632                         case CONSTANT_NameAndType:
1633                                 {
1634                                         constant_nameandtype *cnt = e;
1635                                         printf ("NameAndType: ");
1636                                         utf_display_printable_ascii (cnt->name);
1637                                         printf (" ");
1638                                         utf_display_printable_ascii (cnt->descriptor);
1639                                 }
1640                                 break;
1641                         case CONSTANT_Utf8:
1642                                 printf ("Utf8 -> ");
1643                                 utf_display_printable_ascii (e);
1644                                 break;
1645                         default: 
1646                                 log_text("Invalid type of ConstantPool-Entry");
1647                                 assert(0);
1648                         }
1649                 }
1650
1651                 printf ("\n");
1652         }
1653 }
1654 #endif /* !defined(NDEBUG) */
1655
1656
1657 /* class_showmethods ***********************************************************
1658
1659    Dump info about the fields and methods of the given class to stdout.
1660
1661 *******************************************************************************/
1662
1663 #if !defined(NDEBUG)
1664 void class_showmethods (classinfo *c)
1665 {
1666         s4 i;
1667         
1668         printf("--------- Fields and Methods ----------------\n");
1669         printf("Flags: ");
1670         class_printflags(c);
1671         printf("\n");
1672
1673         printf("This: ");
1674         utf_display_printable_ascii(c->name);
1675         printf("\n");
1676
1677         if (c->super.cls) {
1678                 printf("Super: ");
1679                 utf_display_printable_ascii(c->super.cls->name);
1680                 printf ("\n");
1681         }
1682
1683         printf("Index: %d\n", c->index);
1684         
1685         printf("Interfaces:\n");        
1686         for (i = 0; i < c->interfacescount; i++) {
1687                 printf("   ");
1688                 utf_display_printable_ascii(c->interfaces[i].cls->name);
1689                 printf (" (%d)\n", c->interfaces[i].cls->index);
1690         }
1691
1692         printf("Fields:\n");
1693         for (i = 0; i < c->fieldscount; i++)
1694                 field_println(&(c->fields[i]));
1695
1696         printf("Methods:\n");
1697         for (i = 0; i < c->methodscount; i++) {
1698                 methodinfo *m = &(c->methods[i]);
1699
1700                 if (!(m->flags & ACC_STATIC))
1701                         printf("vftblindex: %d   ", m->vftblindex);
1702
1703                 method_println(m);
1704         }
1705
1706         printf ("Virtual function table:\n");
1707         for (i = 0; i < c->vftbl->vftbllength; i++)
1708                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]));
1709 }
1710 #endif /* !defined(NDEBUG) */
1711
1712
1713 /*
1714  * These are local overrides for various environment variables in Emacs.
1715  * Please do not remove this and leave it at the end of the file, where
1716  * Emacs will automagically detect them.
1717  * ---------------------------------------------------------------------
1718  * Local variables:
1719  * mode: c
1720  * indent-tabs-mode: t
1721  * c-basic-offset: 4
1722  * tab-width: 4
1723  * End:
1724  * vim:noexpandtab:sw=4:ts=4:
1725  */