* M_LSUB, M_LSUB_IMM32, M_AND, M_IAND, M_IAND_IMM, M_IXOR, M_BLE, M_BA:
[cacao.git] / src / vm / resolve.c
1 /* src/vm/resolve.c - resolving classes/interfaces/fields/methods
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: Edwin Steiner
28
29    Changes: Christan Thalinger
30
31    $Id: resolve.c 3460 2005-10-20 09:34:16Z edwin $
32
33 */
34
35
36 #include <assert.h>
37
38 #include "mm/memory.h"
39 #include "vm/resolve.h"
40 #include "vm/access.h"
41 #include "vm/classcache.h"
42 #include "vm/descriptor.h"
43 #include "vm/exceptions.h"
44 #include "vm/linker.h"
45 #include "vm/loader.h"
46 #include "vm/stringlocal.h"
47 #include "vm/jit/jit.h"
48 #include "vm/jit/verify/typeinfo.h"
49
50
51 /******************************************************************************/
52 /* DEBUG HELPERS                                                              */
53 /******************************************************************************/
54
55 /*#define RESOLVE_VERBOSE*/
56
57 /******************************************************************************/
58 /* CLASS RESOLUTION                                                           */
59 /******************************************************************************/
60
61 /* resolve_class_from_name *****************************************************
62  
63    Resolve a symbolic class reference
64   
65    IN:
66        referer..........the class containing the reference
67        refmethod........the method from which resolution was triggered
68                         (may be NULL if not applicable)
69        classname........class name to resolve
70        mode.............mode of resolution:
71                             resolveLazy...only resolve if it does not
72                                           require loading classes
73                             resolveEager..load classes if necessary
74            checkaccess......if true, access rights to the class are checked
75            link.............if true, guarantee that the returned class, if any,
76                             has been linked
77   
78    OUT:
79        *result..........set to result of resolution, or to NULL if
80                         the reference has not been resolved
81                         In the case of an exception, *result is
82                         guaranteed to be set to NULL.
83   
84    RETURN VALUE:
85        true.............everything ok 
86                         (*result may still be NULL for resolveLazy)
87        false............an exception has been thrown
88
89    NOTE:
90        The returned class is *not* guaranteed to be linked!
91            (It is guaranteed to be loaded, though.)
92    
93 *******************************************************************************/
94
95 bool resolve_class_from_name(classinfo *referer,
96                                                          methodinfo *refmethod,
97                                                          utf *classname,
98                                                          resolve_mode_t mode,
99                                                          bool checkaccess,
100                                                          bool link,
101                                                          classinfo **result)
102 {
103         classinfo *cls = NULL;
104         char *utf_ptr;
105         int len;
106         
107         assert(result);
108         assert(referer);
109         assert(classname);
110         assert(mode == resolveLazy || mode == resolveEager);
111         
112         *result = NULL;
113
114 #ifdef RESOLVE_VERBOSE
115         fprintf(stderr,"resolve_class_from_name(");
116         utf_fprint(stderr,referer->name);
117         fprintf(stderr,",%p,",referer->classloader);
118         utf_fprint(stderr,classname);
119         fprintf(stderr,",%d,%d)\n",(int)checkaccess,(int)link);
120 #endif
121
122         /* lookup if this class has already been loaded */
123
124         cls = classcache_lookup(referer->classloader, classname);
125
126 #ifdef RESOLVE_VERBOSE
127         fprintf(stderr,"    lookup result: %p\n",(void*)cls);
128 #endif
129
130         if (!cls) {
131                 /* resolve array types */
132
133                 if (classname->text[0] == '[') {
134                         utf_ptr = classname->text + 1;
135                         len = classname->blength - 1;
136
137                         /* classname is an array type name */
138
139                         switch (*utf_ptr) {
140                                 case 'L':
141                                         utf_ptr++;
142                                         len -= 2;
143                                         /* FALLTHROUGH */
144                                 case '[':
145                                         /* the component type is a reference type */
146                                         /* resolve the component type */
147                                         if (!resolve_class_from_name(referer,refmethod,
148                                                                            utf_new(utf_ptr,len),
149                                                                            mode,checkaccess,link,&cls))
150                                                 return false; /* exception */
151                                         if (!cls) {
152                                                 assert(mode == resolveLazy);
153                                                 return true; /* be lazy */
154                                         }
155                                         /* create the array class */
156                                         cls = class_array_of(cls,false);
157                                         if (!cls)
158                                                 return false; /* exception */
159                         }
160                 }
161                 else {
162                         /* the class has not been loaded, yet */
163                         if (mode == resolveLazy)
164                                 return true; /* be lazy */
165                 }
166
167 #ifdef RESOLVE_VERBOSE
168                 fprintf(stderr,"    loading...\n");
169 #endif
170
171                 /* load the class */
172                 if (!cls) {
173                         if (!(cls = load_class_from_classloader(classname,
174                                                                                                         referer->classloader)))
175                                 return false; /* exception */
176                 }
177         }
178
179         /* the class is now loaded */
180         assert(cls);
181         assert(cls->loaded);
182
183 #ifdef RESOLVE_VERBOSE
184         fprintf(stderr,"    checking access rights...\n");
185 #endif
186         
187         /* check access rights of referer to refered class */
188         if (checkaccess && !access_is_accessible_class(referer,cls)) {
189                 int msglen;
190                 char *message;
191
192                 msglen = utf_strlen(cls->name) + utf_strlen(referer->name) + 100;
193                 message = MNEW(char,msglen);
194                 strcpy(message,"class is not accessible (");
195                 utf_sprint_classname(message+strlen(message),cls->name);
196                 strcat(message," from ");
197                 utf_sprint_classname(message+strlen(message),referer->name);
198                 strcat(message,")");
199                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
200                 MFREE(message,char,msglen);
201                 return false; /* exception */
202         }
203
204         /* link the class if necessary */
205         if (link) {
206                 if (!cls->linked)
207                         if (!link_class(cls))
208                                 return false; /* exception */
209                 assert(cls->linked);
210         }
211
212         /* resolution succeeds */
213 #ifdef RESOLVE_VERBOSE
214         fprintf(stderr,"    success.\n");
215 #endif
216         *result = cls;
217         return true;
218 }
219
220 /* resolve_classref ************************************************************
221  
222    Resolve a symbolic class reference
223   
224    IN:
225        refmethod........the method from which resolution was triggered
226                         (may be NULL if not applicable)
227        ref..............class reference
228        mode.............mode of resolution:
229                             resolveLazy...only resolve if it does not
230                                           require loading classes
231                             resolveEager..load classes if necessary
232            checkaccess......if true, access rights to the class are checked
233            link.............if true, guarantee that the returned class, if any,
234                             has been linked
235   
236    OUT:
237        *result..........set to result of resolution, or to NULL if
238                         the reference has not been resolved
239                         In the case of an exception, *result is
240                         guaranteed to be set to NULL.
241   
242    RETURN VALUE:
243        true.............everything ok 
244                         (*result may still be NULL for resolveLazy)
245        false............an exception has been thrown
246    
247 *******************************************************************************/
248
249 bool resolve_classref(methodinfo *refmethod,
250                                           constant_classref *ref,
251                                           resolve_mode_t mode,
252                                           bool checkaccess,
253                                           bool link,
254                                           classinfo **result)
255 {
256         return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,checkaccess,link,result);
257 }
258
259 /* resolve_classref_or_classinfo ***********************************************
260  
261    Resolve a symbolic class reference if necessary
262   
263    IN:
264        refmethod........the method from which resolution was triggered
265                         (may be NULL if not applicable)
266        cls..............class reference or classinfo
267        mode.............mode of resolution:
268                             resolveLazy...only resolve if it does not
269                                           require loading classes
270                             resolveEager..load classes if necessary
271            checkaccess......if true, access rights to the class are checked
272            link.............if true, guarantee that the returned class, if any,
273                             has been linked
274   
275    OUT:
276        *result..........set to result of resolution, or to NULL if
277                         the reference has not been resolved
278                         In the case of an exception, *result is
279                         guaranteed to be set to NULL.
280   
281    RETURN VALUE:
282        true.............everything ok 
283                         (*result may still be NULL for resolveLazy)
284        false............an exception has been thrown
285    
286 *******************************************************************************/
287
288 bool resolve_classref_or_classinfo(methodinfo *refmethod,
289                                                                    classref_or_classinfo cls,
290                                                                    resolve_mode_t mode,
291                                                                    bool checkaccess,
292                                                                    bool link,
293                                                                    classinfo **result)
294 {
295         classinfo         *c;
296         
297         assert(cls.any);
298         assert(mode == resolveEager || mode == resolveLazy);
299         assert(result);
300
301 #ifdef RESOLVE_VERBOSE
302         fprintf(stderr,"resolve_classref_or_classinfo(");
303         utf_fprint(stderr,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
304         fprintf(stderr,",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
305 #endif
306
307         *result = NULL;
308
309         if (IS_CLASSREF(cls)) {
310                 /* we must resolve this reference */
311
312                 if (!resolve_class_from_name(cls.ref->referer, refmethod, cls.ref->name,
313                                                                          mode, checkaccess, link, &c))
314                         goto return_exception;
315
316         } else {
317                 /* cls has already been resolved */
318                 c = cls.cls;
319                 assert(c->loaded);
320         }
321         assert(c || (mode == resolveLazy));
322
323         if (!c)
324                 return true; /* be lazy */
325         
326         assert(c);
327         assert(c->loaded);
328
329         if (link) {
330                 if (!c->linked)
331                         if (!link_class(c))
332                                 goto return_exception;
333
334                 assert(c->linked);
335         }
336
337         /* succeeded */
338         *result = c;
339         return true;
340
341  return_exception:
342         *result = NULL;
343         return false;
344 }
345
346
347 /* resolve_class_from_typedesc *************************************************
348  
349    Return a classinfo * for the given type descriptor
350   
351    IN:
352        d................type descriptor
353            checkaccess......if true, access rights to the class are checked
354            link.............if true, guarantee that the returned class, if any,
355                             has been linked
356    OUT:
357        *result..........set to result of resolution, or to NULL if
358                         the reference has not been resolved
359                         In the case of an exception, *result is
360                         guaranteed to be set to NULL.
361   
362    RETURN VALUE:
363        true.............everything ok 
364        false............an exception has been thrown
365
366    NOTE:
367        This function always resolved eagerly.
368    
369 *******************************************************************************/
370
371 bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
372 {
373         classinfo *cls;
374         
375         assert(d);
376         assert(result);
377
378         *result = NULL;
379
380 #ifdef RESOLVE_VERBOSE
381         fprintf(stderr,"resolve_class_from_typedesc(");
382         descriptor_debug_print_typedesc(stderr,d);
383         fprintf(stderr,",%i,%i)\n",(int)checkaccess,(int)link);
384 #endif
385
386         if (d->classref) {
387                 /* a reference type */
388                 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
389                                                                                    resolveEager,checkaccess,link,&cls))
390                         return false; /* exception */
391         }
392         else {
393                 /* a primitive type */
394                 cls = primitivetype_table[d->decltype].class_primitive;
395                 assert(cls->loaded);
396                 if (!cls->linked)
397                         if (!link_class(cls))
398                                 return false; /* exception */
399         }
400         assert(cls);
401         assert(cls->loaded);
402         assert(!link || cls->linked);
403
404 #ifdef RESOLVE_VERBOSE
405         fprintf(stderr,"    result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
406 #endif
407
408         *result = cls;
409         return true;
410 }
411
412 /******************************************************************************/
413 /* SUBTYPE SET CHECKS                                                         */
414 /******************************************************************************/
415
416 /* resolve_and_check_subtype_set ***********************************************
417  
418    Resolve the references in the given set and test subtype relationships
419   
420    IN:
421        referer..........the class containing the references
422        refmethod........the method triggering the resolution
423        ref..............a set of class/interface references
424                         (may be empty)
425        type.............the type to test against the set
426        reversed.........if true, test if type is a subtype of
427                         the set members, instead of the other
428                         way round
429        mode.............mode of resolution:
430                             resolveLazy...only resolve if it does not
431                                           require loading classes
432                             resolveEager..load classes if necessary
433        error............which type of exception to throw if
434                         the test fails. May be:
435                             resolveLinkageError, or
436                             resolveIllegalAccessError
437                                                 IMPORTANT: If error==resolveIllegalAccessError,
438                                                 then array types in the set are skipped.
439
440    OUT:
441        *checked.........set to true if all checks were performed,
442                             otherwise set to false
443                             (This is guaranteed to be true if mode was
444                                                 resolveEager and no exception occured.)
445                                                 If checked == NULL, this parameter is not used.
446   
447    RETURN VALUE:
448        true.............the check succeeded
449        false............the check failed. An exception has been
450                         thrown.
451    
452    NOTE:
453        The references in the set are resolved first, so any
454        exception which may occurr during resolution may
455        be thrown by this function.
456    
457 *******************************************************************************/
458
459 bool resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
460                                                                    unresolved_subtype_set *ref,
461                                                                    classref_or_classinfo typeref,
462                                                                    bool reversed,
463                                                                    resolve_mode_t mode,
464                                                                    resolve_err_t error,
465                                                                    bool *checked)
466 {
467         classref_or_classinfo *setp;
468         classinfo *result;
469         classinfo *type;
470         typeinfo resultti;
471         typeinfo typeti;
472         char *message;
473         int msglen;
474         typecheck_result r;
475
476         assert(referer);
477         assert(ref);
478         assert(typeref.any);
479         assert(mode == resolveLazy || mode == resolveEager);
480         assert(error == resolveLinkageError || error == resolveIllegalAccessError);
481
482 #ifdef RESOLVE_VERBOSE
483         fprintf(stderr,"resolve_and_check_subtype_set\n");
484         unresolved_subtype_set_debug_dump(ref,stderr);
485         if (IS_CLASSREF(typeref)) {
486                 fprintf(stderr,"    ref: ");utf_fprint(stderr,typeref.ref->name);
487         }
488         else {
489                 fprintf(stderr,"    cls: ");utf_fprint(stderr,typeref.cls->name);
490         }
491         fprintf(stderr,"\n");
492 #endif
493
494         setp = ref->subtyperefs;
495
496         /* an empty set of tests always succeeds */
497         if (!setp || !setp->any) {
498                 if (checked)
499                         *checked = true;
500                 return true;
501         }
502
503         if (checked)
504                 *checked = false;
505
506         /* first resolve the type if necessary */
507         if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&type))
508                 return false; /* exception */
509         if (!type)
510                 return true; /* be lazy */
511
512         assert(type);
513         assert(type->loaded);
514         assert(type->linked);
515         TYPEINFO_INIT_CLASSINFO(typeti,type);
516
517         for (; setp->any; ++setp) {
518                 /* first resolve the set member if necessary */
519                 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,false,true,&result)) {
520                         /* the type could not be resolved. therefore we are sure that  */
521                         /* no instances of this type will ever exist -> skip this test */
522                         /* XXX this assumes that class loading has invariant results (as in JVM spec) */
523                         *exceptionptr = NULL;
524                         continue;
525                 }
526                 if (!result)
527                         return true; /* be lazy */
528
529                 assert(result);
530                 assert(result->loaded);
531                 assert(result->linked);
532
533
534                 /* do not check access to protected members of arrays */
535                 if (error == resolveIllegalAccessError && result->name->text[0] == '[') {
536                         continue;
537                 }
538
539 #ifdef RESOLVE_VERBOSE
540                 fprintf(stderr,"performing subclass test:\n");
541                 fprintf(stderr,"    ");utf_fprint(stderr,result->name);fputc('\n',stderr);
542                 fprintf(stderr,"  must be a %s of\n",(reversed) ? "superclass" : "subclass");
543                 fprintf(stderr,"    ");utf_fprint(stderr,type->name);fputc('\n',stderr);
544 #endif
545
546                 /* now check the subtype relationship */
547                 TYPEINFO_INIT_CLASSINFO(resultti,result);
548                 if (reversed) {
549                         /* we must test against `true` because `MAYBE` is also != 0 */
550                         r = typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result));
551                         if (r == typecheck_FAIL)
552                                 return false;
553                         if (r != typecheck_TRUE) {
554 #ifdef RESOLVE_VERBOSE
555                                 fprintf(stderr,"reversed subclass test failed\n");
556 #endif
557                                 goto throw_error;
558                         }
559                 }
560                 else {
561                         /* we must test against `true` because `MAYBE` is also != 0 */
562                         r = typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type));
563                         if (r == typecheck_FAIL)
564                                 return false;
565                         if (r != typecheck_TRUE) {
566 #ifdef RESOLVE_VERBOSE
567                                 fprintf(stderr,"subclass test failed\n");
568 #endif
569                                 goto throw_error;
570                         }
571                 }
572         }
573         
574         /* check succeeds */
575         if (checked)
576                 *checked = true;
577         return true;
578
579 throw_error:
580         msglen = utf_strlen(result->name) + utf_strlen(type->name) + 200;
581         message = MNEW(char,msglen);
582         strcpy(message,(error == resolveIllegalAccessError) ?
583                         "illegal access to protected member ("
584                         : "subtype constraint violated (");
585         utf_sprint_classname(message+strlen(message),result->name);
586         strcat(message," is not a subclass of ");
587         utf_sprint_classname(message+strlen(message),type->name);
588         strcat(message,")");
589         if (error == resolveIllegalAccessError)
590                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
591         else
592                 *exceptionptr = new_exception_message(string_java_lang_LinkageError,message);
593         MFREE(message,char,msglen);
594         return false; /* exception */
595 }
596
597 /******************************************************************************/
598 /* CLASS RESOLUTION                                                           */
599 /******************************************************************************/
600
601 /* resolve_class ***************************************************************
602  
603    Resolve an unresolved class reference. The class is also linked.
604   
605    IN:
606        ref..............struct containing the reference
607        mode.............mode of resolution:
608                             resolveLazy...only resolve if it does not
609                                           require loading classes
610                             resolveEager..load classes if necessary
611            checkaccess......if true, access rights to the class are checked
612    
613    OUT:
614        *result..........set to the result of resolution, or to NULL if
615                         the reference has not been resolved
616                         In the case of an exception, *result is
617                         guaranteed to be set to NULL.
618   
619    RETURN VALUE:
620        true.............everything ok 
621                         (*result may still be NULL for resolveLazy)
622        false............an exception has been thrown
623    
624 *******************************************************************************/
625
626 bool resolve_class(unresolved_class *ref,
627                                    resolve_mode_t mode,
628                                    bool checkaccess,
629                                    classinfo **result)
630 {
631         classinfo *cls;
632         bool checked;
633         
634         assert(ref);
635         assert(result);
636         assert(mode == resolveLazy || mode == resolveEager);
637
638         *result = NULL;
639
640 #ifdef RESOLVE_VERBOSE
641         unresolved_class_debug_dump(ref,stderr);
642 #endif
643
644         /* first we must resolve the class */
645         if (!resolve_classref(ref->referermethod,
646                                               ref->classref,mode,checkaccess,true,&cls))
647         {
648                 /* the class reference could not be resolved */
649                 return false; /* exception */
650         }
651         if (!cls)
652                 return true; /* be lazy */
653
654         assert(cls);
655         assert(cls->loaded && cls->linked);
656
657         /* now we check the subtype constraints */
658         if (!resolve_and_check_subtype_set(ref->classref->referer,ref->referermethod,
659                                                                            &(ref->subtypeconstraints),
660                                                                            CLASSREF_OR_CLASSINFO(cls),
661                                                                            false,
662                                                                            mode,
663                                                                            resolveLinkageError,&checked))
664         {
665                 return false; /* exception */
666         }
667         if (!checked)
668                 return true; /* be lazy */
669
670         /* succeed */
671         *result = cls;
672         return true;
673 }
674
675 /* resolve_classref_eager ******************************************************
676  
677    Resolve an unresolved class reference eagerly. The class is also linked and
678    access rights to the class are checked.
679   
680    IN:
681        ref..............constant_classref to the class
682    
683    RETURN VALUE:
684        classinfo * to the class, or
685            NULL if an exception has been thrown
686    
687 *******************************************************************************/
688
689 classinfo * resolve_classref_eager(constant_classref *ref)
690 {
691         classinfo *c;
692
693         if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
694                 return NULL;
695
696         return c;
697 }
698
699 /* resolve_classref_eager_nonabstract ******************************************
700  
701    Resolve an unresolved class reference eagerly. The class is also linked and
702    access rights to the class are checked. A check is performed that the class
703    is not abstract.
704   
705    IN:
706        ref..............constant_classref to the class
707    
708    RETURN VALUE:
709        classinfo * to the class, or
710            NULL if an exception has been thrown
711    
712 *******************************************************************************/
713
714 classinfo * resolve_classref_eager_nonabstract(constant_classref *ref)
715 {
716         classinfo *c;
717
718         if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
719                 return NULL;
720
721         /* ensure that the class is not abstract */
722
723         if (c->flags & ACC_ABSTRACT) {
724                 *exceptionptr = new_verifyerror(NULL,"creating instance of abstract class");
725                 return NULL;
726         }
727
728         return c;
729 }
730
731 /* resolve_class_eager *********************************************************
732  
733    Resolve an unresolved class reference eagerly. The class is also linked and
734    access rights to the class are checked.
735   
736    IN:
737        ref..............struct containing the reference
738    
739    RETURN VALUE:
740        classinfo * to the class, or
741            NULL if an exception has been thrown
742    
743 *******************************************************************************/
744
745 classinfo * resolve_class_eager(unresolved_class *ref)
746 {
747         classinfo *c;
748
749         if (!resolve_class(ref,resolveEager,true,&c))
750                 return NULL;
751
752         return c;
753 }
754
755 /******************************************************************************/
756 /* FIELD RESOLUTION                                                           */
757 /******************************************************************************/
758
759 /* resolve_field ***************************************************************
760  
761    Resolve an unresolved field reference
762   
763    IN:
764        ref..............struct containing the reference
765        mode.............mode of resolution:
766                             resolveLazy...only resolve if it does not
767                                           require loading classes
768                             resolveEager..load classes if necessary
769   
770    OUT:
771        *result..........set to the result of resolution, or to NULL if
772                         the reference has not been resolved
773                         In the case of an exception, *result is
774                         guaranteed to be set to NULL.
775   
776    RETURN VALUE:
777        true.............everything ok 
778                         (*result may still be NULL for resolveLazy)
779        false............an exception has been thrown
780    
781 *******************************************************************************/
782
783 bool resolve_field(unresolved_field *ref,
784                                    resolve_mode_t mode,
785                                    fieldinfo **result)
786 {
787         classinfo *referer;
788         classinfo *container;
789         classinfo *declarer;
790         constant_classref *fieldtyperef;
791         fieldinfo *fi;
792         bool checked;
793         
794         assert(ref);
795         assert(result);
796         assert(mode == resolveLazy || mode == resolveEager);
797
798         *result = NULL;
799
800 #ifdef RESOLVE_VERBOSE
801         unresolved_field_debug_dump(ref,stderr);
802 #endif
803
804         /* the class containing the reference */
805
806         referer = ref->fieldref->classref->referer;
807         assert(referer);
808
809         /* first we must resolve the class containg the field */
810         if (!resolve_class_from_name(referer,ref->referermethod,
811                                            ref->fieldref->classref->name,mode,true,true,&container))
812         {
813                 /* the class reference could not be resolved */
814                 return false; /* exception */
815         }
816         if (!container)
817                 return true; /* be lazy */
818
819         assert(container);
820         assert(container->loaded && container->linked);
821
822         /* now we must find the declaration of the field in `container`
823          * or one of its superclasses */
824
825 #ifdef RESOLVE_VERBOSE
826                 fprintf(stderr,"    resolving field in class...\n");
827 #endif
828
829         fi = class_resolvefield(container,
830                                                         ref->fieldref->name,ref->fieldref->descriptor,
831                                                         referer,true);
832         if (!fi) {
833                 if (mode == resolveLazy) {
834                         /* The field does not exist. But since we were called lazily, */
835                         /* this error must not be reported now. (It will be reported   */
836                         /* if eager resolving of this field is ever tried.)           */
837
838                         *exceptionptr = NULL;
839                         return true; /* be lazy */
840                 }
841                 
842                 return false; /* exception */
843         }
844
845         /* { the field reference has been resolved } */
846         declarer = fi->class;
847         assert(declarer);
848         assert(declarer->loaded && declarer->linked);
849
850 #ifdef RESOLVE_VERBOSE
851                 fprintf(stderr,"    checking static...\n");
852 #endif
853
854         /* check static */
855
856         if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
857                 /* a static field is accessed via an instance, or vice versa */
858                 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
859                                 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
860                                                          : "instance field accessed without instance");
861                 return false; /* exception */
862         }
863
864         /* for non-static accesses we have to check the constraints on the */
865         /* instance type */
866
867         if (!(ref->flags & RESOLVE_STATIC)) {
868 #ifdef RESOLVE_VERBOSE
869                 fprintf(stderr,"    checking instance types...\n");
870 #endif
871
872                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
873                                                                                    &(ref->instancetypes),
874                                                                                    CLASSREF_OR_CLASSINFO(container),
875                                                                                    false, mode, resolveLinkageError,
876                                                                                    &checked))
877                 {
878                         return false; /* exception */
879                 }
880
881                 if (!checked)
882                         return true; /* be lazy */
883         }
884
885 #ifdef RESOLVE_VERBOSE
886         fprintf(stderr,"    checking instance types...done\n");
887 #endif
888
889         fieldtyperef = ref->fieldref->parseddesc.fd->classref;
890
891         /* for PUT* instructions we have to check the constraints on the value type */
892         if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
893 #ifdef RESOLVE_VERBOSE
894                 fprintf(stderr,"    checking value constraints...\n");
895 #endif
896                 assert(fieldtyperef);
897                 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
898                         /* check subtype constraints */
899                         if (!resolve_and_check_subtype_set(referer, ref->referermethod,
900                                                                                            &(ref->valueconstraints),
901                                                                                            CLASSREF_OR_CLASSINFO(fieldtyperef),
902                                                                                            false, mode, resolveLinkageError,
903                                                                                            &checked))
904                         {
905                                 return false; /* exception */
906                         }
907                         if (!checked)
908                                 return true; /* be lazy */
909                 }
910         }
911                                                                            
912         /* check access rights */
913 #ifdef RESOLVE_VERBOSE
914         fprintf(stderr,"    checking access rights...\n");
915 #endif
916         if (!access_is_accessible_member(referer,declarer,fi->flags)) {
917                 int msglen;
918                 char *message;
919
920                 msglen = utf_strlen(declarer->name) + utf_strlen(fi->name) + utf_strlen(referer->name) + 100;
921                 message = MNEW(char,msglen);
922                 strcpy(message,"field is not accessible (");
923                 utf_sprint_classname(message+strlen(message),declarer->name);
924                 strcat(message,".");
925                 utf_sprint(message+strlen(message),fi->name);
926                 strcat(message," from ");
927                 utf_sprint_classname(message+strlen(message),referer->name);
928                 strcat(message,")");
929                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
930                 MFREE(message,char,msglen);
931                 return false; /* exception */
932         }
933 #ifdef RESOLVE_VERBOSE
934         fprintf(stderr,"    checking access rights...done\n");
935         fprintf(stderr,"        declarer = ");
936         utf_fprint_classname(stderr,declarer->name); fputc('\n',stderr);
937         fprintf(stderr,"        referer = ");
938         utf_fprint_classname(stderr,referer->name); fputc('\n',stderr);
939 #endif
940
941         /* check protected access */
942         if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
943 #ifdef RESOLVE_VERBOSE
944                 fprintf(stderr,"    checking protectec access...\n");
945 #endif
946                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
947                                                                                    &(ref->instancetypes),
948                                                                                    CLASSREF_OR_CLASSINFO(referer),
949                                                                                    false, mode,
950                                                                                    resolveIllegalAccessError, &checked))
951                 {
952                         return false; /* exception */
953                 }
954
955                 if (!checked)
956                         return true; /* be lazy */
957         }
958
959         /* impose loading constraint on field type */
960
961         if (fi->type == TYPE_ADR) {
962 #ifdef RESOLVE_VERBOSE
963                 fprintf(stderr,"    adding constraint...\n");
964 #endif
965                 assert(fieldtyperef);
966                 if (!classcache_add_constraint(declarer->classloader,
967                                                                            referer->classloader,
968                                                                            fieldtyperef->name))
969                         return false;
970         }
971
972         /* succeed */
973 #ifdef RESOLVE_VERBOSE
974         fprintf(stderr,"    success.\n");
975 #endif
976         *result = fi;
977
978         return true;
979 }
980
981 /* resolve_field_eager *********************************************************
982  
983    Resolve an unresolved field reference eagerly.
984   
985    IN:
986        ref..............struct containing the reference
987    
988    RETURN VALUE:
989        fieldinfo * to the field, or
990            NULL if an exception has been thrown
991    
992 *******************************************************************************/
993
994 fieldinfo * resolve_field_eager(unresolved_field *ref)
995 {
996         fieldinfo *fi;
997
998         if (!resolve_field(ref,resolveEager,&fi))
999                 return NULL;
1000
1001         return fi;
1002 }
1003
1004 /******************************************************************************/
1005 /* METHOD RESOLUTION                                                          */
1006 /******************************************************************************/
1007
1008 /* resolve_method **************************************************************
1009  
1010    Resolve an unresolved method reference
1011   
1012    IN:
1013        ref..............struct containing the reference
1014        mode.............mode of resolution:
1015                             resolveLazy...only resolve if it does not
1016                                           require loading classes
1017                             resolveEager..load classes if necessary
1018   
1019    OUT:
1020        *result..........set to the result of resolution, or to NULL if
1021                         the reference has not been resolved
1022                         In the case of an exception, *result is
1023                         guaranteed to be set to NULL.
1024   
1025    RETURN VALUE:
1026        true.............everything ok 
1027                         (*result may still be NULL for resolveLazy)
1028        false............an exception has been thrown
1029    
1030 *******************************************************************************/
1031
1032 bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
1033 {
1034         classinfo *referer;
1035         classinfo *container;
1036         classinfo *declarer;
1037         methodinfo *mi;
1038         typedesc *paramtypes;
1039         int instancecount;
1040         int i;
1041         bool checked;
1042         
1043         assert(ref);
1044         assert(result);
1045         assert(mode == resolveLazy || mode == resolveEager);
1046
1047 #ifdef RESOLVE_VERBOSE
1048         unresolved_method_debug_dump(ref,stderr);
1049 #endif
1050
1051         *result = NULL;
1052
1053         /* the class containing the reference */
1054         referer = ref->methodref->classref->referer;
1055         assert(referer);
1056
1057         /* first we must resolve the class containg the method */
1058         if (!resolve_class_from_name(referer,ref->referermethod,
1059                                            ref->methodref->classref->name,mode,true,true,&container))
1060         {
1061                 /* the class reference could not be resolved */
1062                 return false; /* exception */
1063         }
1064         if (!container)
1065                 return true; /* be lazy */
1066
1067         assert(container);
1068         assert(container->linked);
1069
1070         /* now we must find the declaration of the method in `container`
1071          * or one of its superclasses */
1072
1073         if (container->flags & ACC_INTERFACE) {
1074                 mi = class_resolveinterfacemethod(container,
1075                                                                               ref->methodref->name,
1076                                                                                   ref->methodref->descriptor,
1077                                                                               referer, true);
1078
1079         } else {
1080                 mi = class_resolveclassmethod(container,
1081                                                                           ref->methodref->name,
1082                                                                           ref->methodref->descriptor,
1083                                                                           referer, true);
1084         }
1085
1086         if (!mi) {
1087                 if (mode == resolveLazy) {
1088                         /* The method does not exist. But since we were called lazily, */
1089                         /* this error must not be reported now. (It will be reported   */
1090                         /* if eager resolving of this method is ever tried.)           */
1091
1092                         *exceptionptr = NULL;
1093                         return true; /* be lazy */
1094                 }
1095                 
1096                 return false; /* exception */ /* XXX set exceptionptr? */
1097         }
1098
1099 #ifdef RESOLVE_VERBOSE
1100         fprintf(stderr,"    flags: %02x\n",mi->flags);
1101 #endif
1102         /* { the method reference has been resolved } */
1103
1104         declarer = mi->class;
1105         assert(declarer);
1106         assert(referer->linked);
1107
1108         /* checks for INVOKESPECIAL:                                       */
1109         /* for <init> and methods of the current class we don't need any   */
1110         /* special checks. Otherwise we must verify that the called method */
1111         /* belongs to a super class of the current class                   */
1112         if (((ref->flags & RESOLVE_SPECIAL) != 0) 
1113                 && referer != declarer 
1114                 && mi->name != utf_init) 
1115         {
1116                 /* check that declarer is a super class of the current class   */
1117                 if (!class_issubclass(referer,declarer)) {
1118                         *exceptionptr = new_verifyerror(ref->referermethod,
1119                                         "INVOKESPECIAL calling non-super class method");
1120                         return false;
1121                 }
1122
1123                 /* if the referer has ACC_SUPER set, we must do the special    */
1124                 /* lookup starting with the direct super class of referer      */
1125                 if ((referer->flags & ACC_SUPER) != 0) {
1126                         mi = class_resolvemethod(referer->super.cls,
1127                                                                          ref->methodref->name,
1128                                                                          ref->methodref->descriptor);
1129                         if (!mi) {
1130                                 /* the spec calls for an AbstractMethodError in this case */
1131                                 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
1132                                 return false;
1133                         }
1134                         declarer = mi->class;
1135                 }
1136         }
1137
1138         /* check static */
1139
1140         if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
1141                 /* a static method is accessed via an instance, or vice versa */
1142                 *exceptionptr =
1143                         new_exception_message(string_java_lang_IncompatibleClassChangeError,
1144                                 (mi->flags & ACC_STATIC) ? "static method called via instance"
1145                                                          : "instance method called without instance");
1146                 return false;
1147         }
1148
1149         /* have the method params already been parsed? no, do it. */
1150
1151         if (!mi->parseddesc->params)
1152                 if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
1153                         return false;
1154                 
1155         /* for non-static methods we have to check the constraints on the         */
1156         /* instance type                                                          */
1157
1158         if (!(ref->flags & RESOLVE_STATIC)) {
1159                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
1160                                                                                    &(ref->instancetypes),
1161                                                                                    CLASSREF_OR_CLASSINFO(container),
1162                                                                                    false,
1163                                                                                    mode,
1164                                                                                    resolveLinkageError,&checked))
1165                 {
1166                         return false; /* exception */
1167                 }
1168                 if (!checked)
1169                         return true; /* be lazy */
1170                 instancecount = 1;
1171         }
1172         else {
1173                 instancecount = 0;
1174         }
1175
1176         /* check subtype constraints for TYPE_ADR parameters */
1177
1178         assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
1179         paramtypes = mi->parseddesc->paramtypes;
1180         
1181         for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
1182                 if (paramtypes[i+instancecount].type == TYPE_ADR) {
1183                         if (ref->paramconstraints) {
1184                                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
1185                                                         ref->paramconstraints + i,
1186                                                         CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
1187                                                         false,
1188                                                         mode,
1189                                                         resolveLinkageError,&checked))
1190                                 {
1191                                         return false; /* exception */
1192                                 }
1193                                 if (!checked)
1194                                         return true; /* be lazy */
1195                         }
1196                 }
1197         }
1198
1199         /* check access rights */
1200
1201         if (!access_is_accessible_member(referer,declarer,mi->flags)) {
1202                 int msglen;
1203                 char *message;
1204
1205                 msglen = utf_strlen(declarer->name) + utf_strlen(mi->name) + 
1206                         utf_strlen(mi->descriptor) + utf_strlen(referer->name) + 100;
1207                 message = MNEW(char,msglen);
1208                 strcpy(message,"method is not accessible (");
1209                 utf_sprint_classname(message+strlen(message),declarer->name);
1210                 strcat(message,".");
1211                 utf_sprint(message+strlen(message),mi->name);
1212                 utf_sprint(message+strlen(message),mi->descriptor);
1213                 strcat(message," from ");
1214                 utf_sprint_classname(message+strlen(message),referer->name);
1215                 strcat(message,")");
1216                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
1217                 MFREE(message,char,msglen);
1218                 return false; /* exception */
1219         }
1220
1221         /* check protected access */
1222
1223         if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
1224         {
1225                 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
1226                                                                                    &(ref->instancetypes),
1227                                                                                    CLASSREF_OR_CLASSINFO(referer),
1228                                                                                    false,
1229                                                                                    mode,
1230                                                                                    resolveIllegalAccessError,&checked))
1231                 {
1232                         return false; /* exception */
1233                 }
1234                 if (!checked)
1235                         return true; /* be lazy */
1236         }
1237
1238         /* impose loading constraints on parameters (including instance) */
1239
1240         paramtypes = mi->parseddesc->paramtypes;
1241
1242         for (i = 0; i < mi->parseddesc->paramcount; i++) {
1243                 if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
1244                         utf *name;
1245                         
1246                         if (i < instancecount)
1247                                 name = container->name; /* XXX should this be declarer->name? */
1248                         else
1249                                 name = paramtypes[i].classref->name;
1250                         
1251                         if (!classcache_add_constraint(referer->classloader,
1252                                                                                    declarer->classloader, name))
1253                                 return false; /* exception */
1254                 }
1255         }
1256
1257         /* impose loading constraing onto return type */
1258
1259         if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
1260                 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
1261                                 ref->methodref->parseddesc.md->returntype.classref->name))
1262                         return false; /* exception */
1263         }
1264
1265         /* succeed */
1266         *result = mi;
1267         return true;
1268 }
1269
1270 /* resolve_method_eager ********************************************************
1271  
1272    Resolve an unresolved method reference eagerly.
1273   
1274    IN:
1275        ref..............struct containing the reference
1276    
1277    RETURN VALUE:
1278        methodinfo * to the method, or
1279            NULL if an exception has been thrown
1280    
1281 *******************************************************************************/
1282
1283 methodinfo * resolve_method_eager(unresolved_method *ref)
1284 {
1285         methodinfo *mi;
1286
1287         if (!resolve_method(ref,resolveEager,&mi))
1288                 return NULL;
1289
1290         return mi;
1291 }
1292
1293 /******************************************************************************/
1294 /* CREATING THE DATA STRUCTURES                                               */
1295 /******************************************************************************/
1296
1297 static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
1298                                                                                                  methodinfo *refmethod,
1299                                                                                                  unresolved_subtype_set *stset,
1300                                                                                                  typeinfo *tinfo,
1301                                                                                                  constant_classref *declaredtype)
1302 {
1303         int count;
1304         int i;
1305         
1306         assert(stset);
1307         assert(tinfo);
1308
1309 #ifdef RESOLVE_VERBOSE
1310         fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
1311 #ifdef TYPEINFO_DEBUG
1312         typeinfo_print(stderr,tinfo,4);
1313 #endif
1314         fprintf(stderr,"    declared type:");utf_fprint(stderr,declaredtype->name);
1315         fprintf(stderr,"\n");
1316 #endif
1317
1318         if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
1319                 *exceptionptr = new_verifyerror(refmethod,
1320                                 "Invalid use of returnAddress");
1321                 return false;
1322         }
1323
1324         if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
1325                 *exceptionptr = new_verifyerror(refmethod,
1326                                 "Invalid use of uninitialized object");
1327                 return false;
1328         }
1329
1330         /* the nulltype is always assignable (XXX for reversed?) */
1331         if (TYPEINFO_IS_NULLTYPE(*tinfo))
1332                 goto empty_set;
1333
1334         /* every type is assignable to (BOOTSTRAP)java.lang.Object */
1335         if (declaredtype->name == utf_java_lang_Object
1336                         && referer->classloader == NULL)
1337         {
1338                 goto empty_set;
1339         }
1340
1341         if (tinfo->merged) {
1342                 count = tinfo->merged->count;
1343                 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
1344                 for (i=0; i<count; ++i) {
1345                         classref_or_classinfo c = tinfo->merged->list[i];
1346                         if (tinfo->dimension > 0) {
1347                                 /* a merge of array types */
1348                                 /* the merged list contains the possible _element_ types, */
1349                                 /* so we have to create array types with these elements.  */
1350                                 if (IS_CLASSREF(c)) {
1351                                         c.ref = class_get_classref_multiarray_of(tinfo->dimension,c.ref);
1352                                 }
1353                                 else {
1354                                         c.cls = class_multiarray_of(tinfo->dimension,c.cls,false);
1355                                 }
1356                         }
1357                         stset->subtyperefs[i] = c;
1358                 }
1359                 stset->subtyperefs[count].any = NULL; /* terminate */
1360         }
1361         else {
1362                 if ((IS_CLASSREF(tinfo->typeclass)
1363                                         ? tinfo->typeclass.ref->name 
1364                                         : tinfo->typeclass.cls->name) == declaredtype->name)
1365                 {
1366                         /* the class names are the same */
1367                     /* equality is guaranteed by the loading constraints */
1368                         goto empty_set;
1369                 }
1370                 else {
1371                         stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
1372                         stset->subtyperefs[0] = tinfo->typeclass;
1373                         stset->subtyperefs[1].any = NULL; /* terminate */
1374                 }
1375         }
1376
1377         return true;
1378
1379 empty_set:
1380         UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
1381         return true;
1382 }
1383
1384 /* create_unresolved_class *****************************************************
1385  
1386    Create an unresolved_class struct for the given class reference
1387   
1388    IN:
1389            refmethod........the method triggering the resolution (if any)
1390            classref.........the class reference
1391            valuetype........value type to check against the resolved class
1392                                                 may be NULL, if no typeinfo is available
1393
1394    RETURN VALUE:
1395        a pointer to a new unresolved_class struct, or
1396            NULL if an exception has been thrown
1397
1398 *******************************************************************************/
1399
1400 unresolved_class * create_unresolved_class(methodinfo *refmethod,
1401                                                                                    constant_classref *classref,
1402                                                                                    typeinfo *valuetype)
1403 {
1404         unresolved_class *ref;
1405         
1406 #ifdef RESOLVE_VERBOSE
1407         fprintf(stderr,"create_unresolved_class\n");
1408         fprintf(stderr,"    referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
1409         if (refmethod) {
1410                 fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1411                 fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1412         }
1413         fprintf(stderr,"    name   : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
1414 #endif
1415
1416         ref = NEW(unresolved_class);
1417         ref->classref = classref;
1418         ref->referermethod = refmethod;
1419
1420         if (valuetype) {
1421                 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
1422                                         &(ref->subtypeconstraints),valuetype,classref))
1423                         return NULL;
1424         }
1425         else {
1426                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
1427         }
1428
1429         return ref;
1430 }
1431
1432 /* create_unresolved_field *****************************************************
1433  
1434    Create an unresolved_field struct for the given field access instruction
1435   
1436    IN:
1437        referer..........the class containing the reference
1438            refmethod........the method triggering the resolution (if any)
1439            iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
1440
1441    RETURN VALUE:
1442        a pointer to a new unresolved_field struct, or
1443            NULL if an exception has been thrown
1444
1445 *******************************************************************************/
1446
1447 unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refmethod,
1448                                                                                    instruction *iptr)
1449 {
1450         unresolved_field *ref;
1451         constant_FMIref *fieldref = NULL;
1452
1453 #ifdef RESOLVE_VERBOSE
1454         fprintf(stderr,"create_unresolved_field\n");
1455         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1456         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1457         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1458 #endif
1459
1460         ref = NEW(unresolved_field);
1461         ref->flags = 0;
1462         ref->referermethod = refmethod;
1463         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
1464
1465         switch (iptr[0].opc) {
1466                 case ICMD_PUTFIELD:
1467                         ref->flags |= RESOLVE_PUTFIELD;
1468                         fieldref = (constant_FMIref *) iptr[0].val.a;
1469                         break;
1470
1471                 case ICMD_PUTFIELDCONST:
1472                         ref->flags |= RESOLVE_PUTFIELD;
1473                         fieldref = (constant_FMIref *) iptr[1].val.a;
1474                         break;
1475
1476                 case ICMD_PUTSTATIC:
1477                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
1478                         fieldref = (constant_FMIref *) iptr[0].val.a;
1479                         break;
1480
1481                 case ICMD_PUTSTATICCONST:
1482                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
1483                         fieldref = (constant_FMIref *) iptr[1].val.a;
1484                         break;
1485
1486                 case ICMD_GETFIELD:
1487                         fieldref = (constant_FMIref *) iptr[0].val.a;
1488                         break;
1489                         
1490                 case ICMD_GETSTATIC:
1491                         ref->flags |= RESOLVE_STATIC;
1492                         fieldref = (constant_FMIref *) iptr[0].val.a;
1493                         break;
1494         }
1495         
1496         assert(fieldref);
1497
1498 #ifdef RESOLVE_VERBOSE
1499         fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
1500         fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
1501         fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
1502         fprintf(stderr,"    type   : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
1503         fputc('\n',stderr);
1504         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1505 #endif
1506
1507         ref->fieldref = fieldref;
1508
1509         return ref;
1510 }
1511
1512 /* constrain_unresolved_field **************************************************
1513  
1514    Record subtype constraints for a field access.
1515   
1516    IN:
1517        ref..............the unresolved_field structure of the access
1518        referer..........the class containing the reference
1519            refmethod........the method triggering the resolution (if any)
1520            iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
1521            stack............the input stack of the instruction
1522
1523    RETURN VALUE:
1524        true.............everything ok
1525            false............an exception has been thrown
1526
1527 *******************************************************************************/
1528
1529 bool constrain_unresolved_field(unresolved_field *ref,
1530                                                             classinfo *referer, methodinfo *refmethod,
1531                                                             instruction *iptr,
1532                                                             stackelement *stack)
1533 {
1534         constant_FMIref *fieldref;
1535         stackelement *instanceslot = NULL;
1536         int type;
1537         typeinfo tinfo;
1538         typeinfo *tip = NULL;
1539         typedesc *fd;
1540
1541         assert(ref);
1542
1543         fieldref = ref->fieldref;
1544         assert(fieldref);
1545
1546 #ifdef RESOLVE_VERBOSE
1547         fprintf(stderr,"constrain_unresolved_field\n");
1548         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1549         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1550         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1551         fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
1552         fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
1553         fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
1554         fprintf(stderr,"    type   : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
1555         fputc('\n',stderr);
1556         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1557 #endif
1558
1559         switch (iptr[0].opc) {
1560                 case ICMD_PUTFIELD:
1561                         instanceslot = stack->prev;
1562                         tip = &(stack->typeinfo);
1563                         break;
1564
1565                 case ICMD_PUTFIELDCONST:
1566                         instanceslot = stack;
1567                         break;
1568
1569                 case ICMD_PUTSTATIC:
1570                         tip = &(stack->typeinfo);
1571                         break;
1572
1573                 case ICMD_GETFIELD:
1574                         instanceslot = stack;
1575                         break;
1576         }
1577         
1578         assert(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
1579         fd = fieldref->parseddesc.fd;
1580         assert(fd);
1581
1582         /* record subtype constraints for the instance type, if any */
1583         if (instanceslot) {
1584                 typeinfo *insttip;
1585
1586                 /* The instanceslot must contain a reference to a non-array type */
1587                 if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
1588                         *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on non-reference");
1589                         return false;
1590                 }
1591                 if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
1592                         *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on array");
1593                         return false;
1594                 }
1595                 
1596                 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && 
1597                                 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1598                 {
1599                         /* The instruction writes a field in an uninitialized object. */
1600                         /* This is only allowed when a field of an uninitialized 'this' object is */
1601                         /* written inside an initialization method                                */
1602                         
1603                         classinfo *initclass;
1604                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1605
1606                         if (ins != NULL) {
1607                                 *exceptionptr = new_verifyerror(refmethod,"accessing field of uninitialized object");
1608                                 return false;
1609                         }
1610                         /* XXX check that class of field == refmethod->class */
1611                         initclass = refmethod->class; /* XXX classrefs */
1612                         assert(initclass->loaded && initclass->linked);
1613                         TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
1614                         insttip = &tinfo;
1615                 }
1616                 else {
1617                         insttip = &(instanceslot->typeinfo);
1618                 }
1619                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1620                                         &(ref->instancetypes),insttip,fieldref->classref))
1621                         return false;
1622         }
1623         else {
1624                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1625         }
1626         
1627         /* record subtype constraints for the value type, if any */
1628         type = fd->type;
1629         if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
1630                 if (!tip) {
1631                         /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
1632                         tip = &tinfo;
1633                         if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
1634                                 assert(class_java_lang_String);
1635                                 assert(class_java_lang_String->loaded);
1636                                 assert(class_java_lang_String->linked);
1637                                 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String);
1638                         }
1639                         else
1640                                 TYPEINFO_INIT_NULLTYPE(tinfo);
1641                 }
1642                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1643                                         &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
1644                         return false;
1645         }
1646         else {
1647                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
1648         }
1649
1650         return true;
1651 }
1652
1653 /* create_unresolved_method ****************************************************
1654  
1655    Create an unresolved_method struct for the given method invocation
1656   
1657    IN:
1658        referer..........the class containing the reference
1659            refmethod........the method triggering the resolution (if any)
1660            iptr.............the INVOKE* instruction
1661
1662    RETURN VALUE:
1663        a pointer to a new unresolved_method struct, or
1664            NULL if an exception has been thrown
1665
1666 *******************************************************************************/
1667
1668 unresolved_method * create_unresolved_method(classinfo *referer, methodinfo *refmethod,
1669                                                                                          instruction *iptr)
1670 {
1671         unresolved_method *ref;
1672         constant_FMIref *methodref;
1673         bool staticmethod;
1674
1675         methodref = (constant_FMIref *) iptr[0].val.a;
1676         assert(methodref);
1677         staticmethod = (iptr[0].opc == ICMD_INVOKESTATIC);
1678
1679 #ifdef RESOLVE_VERBOSE
1680         fprintf(stderr,"create_unresolved_method\n");
1681         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1682         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1683         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1684         fprintf(stderr,"    class  : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1685         fprintf(stderr,"    name   : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1686         fprintf(stderr,"    desc   : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1687         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1688 #endif
1689
1690         /* allocate params if necessary */
1691         if (!methodref->parseddesc.md->params)
1692                 if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
1693                                         (staticmethod) ? ACC_STATIC : ACC_NONE))
1694                         return NULL;
1695
1696         /* create the data structure */
1697         ref = NEW(unresolved_method);
1698         ref->flags = ((staticmethod) ? RESOLVE_STATIC : 0)
1699                            | ((iptr[0].opc == ICMD_INVOKESPECIAL) ? RESOLVE_SPECIAL : 0);
1700         ref->referermethod = refmethod;
1701         ref->methodref = methodref;
1702         ref->paramconstraints = NULL;
1703         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1704
1705         return ref;
1706 }
1707
1708 /* constrain_unresolved_method *************************************************
1709  
1710    Record subtype constraints for the arguments of a method call.
1711   
1712    IN:
1713        ref..............the unresolved_method structure of the call
1714        referer..........the class containing the reference
1715            refmethod........the method triggering the resolution (if any)
1716            iptr.............the INVOKE* instruction
1717            stack............the input stack of the instruction
1718
1719    RETURN VALUE:
1720        true.............everything ok
1721            false............an exception has been thrown
1722
1723 *******************************************************************************/
1724
1725 bool constrain_unresolved_method(unresolved_method *ref,
1726                                                                  classinfo *referer, methodinfo *refmethod,
1727                                                                  instruction *iptr,
1728                                                                  stackelement *stack)
1729 {
1730         constant_FMIref *methodref;
1731         stackelement *instanceslot = NULL;
1732         stackelement *param;
1733         methoddesc *md;
1734         typeinfo tinfo;
1735         int i,j;
1736         int type;
1737         int instancecount;
1738
1739         assert(ref);
1740         methodref = ref->methodref;
1741         assert(methodref);
1742         md = methodref->parseddesc.md;
1743         assert(md);
1744         assert(md->params != NULL);
1745
1746 #ifdef RESOLVE_VERBOSE
1747         fprintf(stderr,"constrain_unresolved_method\n");
1748         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1749         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1750         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1751         fprintf(stderr,"    class  : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1752         fprintf(stderr,"    name   : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1753         fprintf(stderr,"    desc   : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1754         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1755 #endif
1756
1757         if ((ref->flags & RESOLVE_STATIC) == 0) {
1758                 /* find the instance slot under all the parameter slots on the stack */
1759                 instanceslot = stack;
1760                 for (i=1; i<md->paramcount; ++i)
1761                         instanceslot = instanceslot->prev;
1762                 instancecount = 1;
1763         }
1764         else {
1765                 instancecount = 0;
1766         }
1767         
1768         assert((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
1769
1770         /* record subtype constraints for the instance type, if any */
1771         if (instanceslot) {
1772                 typeinfo *tip;
1773                 
1774                 assert(instanceslot->type == TYPE_ADR);
1775                 
1776                 if (iptr[0].opc == ICMD_INVOKESPECIAL && 
1777                                 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1778                 {   /* XXX clean up */
1779                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1780                         classref_or_classinfo initclass = (ins) ? CLASSREF_OR_CLASSINFO(ins[-1].val.a)
1781                                                                                  : CLASSREF_OR_CLASSINFO(refmethod->class);
1782                         tip = &tinfo;
1783                         if (!typeinfo_init_class(tip,initclass))
1784                                 return false;
1785                 }
1786                 else {
1787                         tip = &(instanceslot->typeinfo);
1788                 }
1789                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1790                                         &(ref->instancetypes),tip,methodref->classref))
1791                         return false;
1792         }
1793         
1794         /* record subtype constraints for the parameter types, if any */
1795         param = stack;
1796         for (i=md->paramcount-1-instancecount; i>=0; --i, param=param->prev) {
1797                 type = md->paramtypes[i+instancecount].type;
1798
1799                 assert(param);
1800                 assert(type == param->type);
1801
1802                 if (type == TYPE_ADR) {
1803                         if (!ref->paramconstraints) {
1804                                 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1805                                 for (j=md->paramcount-1-instancecount; j>i; --j)
1806                                         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1807                         }
1808                         assert(ref->paramconstraints);
1809                         if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1810                                                 ref->paramconstraints + i,&(param->typeinfo),
1811                                                 md->paramtypes[i+instancecount].classref))
1812                                 return false;
1813                 }
1814                 else {
1815                         if (ref->paramconstraints)
1816                                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1817                 }
1818         }
1819
1820         return true;
1821 }
1822
1823 /******************************************************************************/
1824 /* FREEING MEMORY                                                             */
1825 /******************************************************************************/
1826
1827 inline static void unresolved_subtype_set_free_list(classref_or_classinfo *list)
1828 {
1829         if (list) {
1830                 classref_or_classinfo *p = list;
1831
1832                 /* this is silly. we *only* need to count the elements for MFREE */
1833                 while ((p++)->any)
1834                         ;
1835                 MFREE(list,classref_or_classinfo,(p - list));
1836         }
1837 }
1838
1839 /* unresolved_class_free *******************************************************
1840  
1841    Free the memory used by an unresolved_class
1842   
1843    IN:
1844        ref..............the unresolved_class
1845
1846 *******************************************************************************/
1847
1848 void unresolved_class_free(unresolved_class *ref)
1849 {
1850         assert(ref);
1851
1852         unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
1853         FREE(ref,unresolved_class);
1854 }
1855
1856 /* unresolved_field_free *******************************************************
1857  
1858    Free the memory used by an unresolved_field
1859   
1860    IN:
1861        ref..............the unresolved_field
1862
1863 *******************************************************************************/
1864
1865 void unresolved_field_free(unresolved_field *ref)
1866 {
1867         assert(ref);
1868
1869         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1870         unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1871         FREE(ref,unresolved_field);
1872 }
1873
1874 /* unresolved_method_free ******************************************************
1875  
1876    Free the memory used by an unresolved_method
1877   
1878    IN:
1879        ref..............the unresolved_method
1880
1881 *******************************************************************************/
1882
1883 void unresolved_method_free(unresolved_method *ref)
1884 {
1885         assert(ref);
1886
1887         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1888         if (ref->paramconstraints) {
1889                 int i;
1890                 int count = ref->methodref->parseddesc.md->paramcount;
1891
1892                 for (i=0; i<count; ++i)
1893                         unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1894                 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1895         }
1896         FREE(ref,unresolved_method);
1897 }
1898
1899 #ifndef NDEBUG
1900 /******************************************************************************/
1901 /* DEBUG DUMPS                                                                */
1902 /******************************************************************************/
1903
1904 /* unresolved_subtype_set_debug_dump *******************************************
1905  
1906    Print debug info for unresolved_subtype_set to stream
1907   
1908    IN:
1909        stset............the unresolved_subtype_set
1910            file.............the stream
1911
1912 *******************************************************************************/
1913
1914 void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1915 {
1916         classref_or_classinfo *p;
1917         
1918         if (SUBTYPESET_IS_EMPTY(*stset)) {
1919                 fprintf(file,"        (empty)\n");
1920         }
1921         else {
1922                 p = stset->subtyperefs;
1923                 for (;p->any; ++p) {
1924                         if (IS_CLASSREF(*p)) {
1925                                 fprintf(file,"        ref: ");
1926                                 utf_fprint(file,p->ref->name);
1927                         }
1928                         else {
1929                                 fprintf(file,"        cls: ");
1930                                 utf_fprint(file,p->cls->name);
1931                         }
1932                         fputc('\n',file);
1933                 }
1934         }
1935 }
1936
1937 /* unresolved_class_debug_dump *************************************************
1938  
1939    Print debug info for unresolved_class to stream
1940   
1941    IN:
1942        ref..............the unresolved_class
1943            file.............the stream
1944
1945 *******************************************************************************/
1946
1947 void unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
1948 {
1949         fprintf(file,"unresolved_class(%p):\n",(void *)ref);
1950         if (ref) {
1951                 fprintf(file,"    referer   : ");
1952                 utf_fprint(file,ref->classref->referer->name); fputc('\n',file);
1953                 fprintf(file,"    refmethod : ");
1954                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1955                 fprintf(file,"    refmethodd: ");
1956                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1957                 fprintf(file,"    classname : ");
1958                 utf_fprint(file,ref->classref->name); fputc('\n',file);
1959                 fprintf(file,"    subtypeconstraints:\n");
1960                 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
1961         }
1962 }
1963
1964 /* unresolved_field_debug_dump *************************************************
1965  
1966    Print debug info for unresolved_field to stream
1967   
1968    IN:
1969        ref..............the unresolved_field
1970            file.............the stream
1971
1972 *******************************************************************************/
1973
1974 void unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1975 {
1976         fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1977         if (ref) {
1978                 fprintf(file,"    referer   : ");
1979                 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1980                 fprintf(file,"    refmethod : ");
1981                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1982                 fprintf(file,"    refmethodd: ");
1983                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1984                 fprintf(file,"    classname : ");
1985                 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1986                 fprintf(file,"    name      : ");
1987                 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1988                 fprintf(file,"    descriptor: ");
1989                 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1990                 fprintf(file,"    parseddesc: ");
1991                 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1992                 fprintf(file,"    flags     : %04x\n",ref->flags);
1993                 fprintf(file,"    instancetypes:\n");
1994                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1995                 fprintf(file,"    valueconstraints:\n");
1996                 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1997         }
1998 }
1999
2000 /* unresolved_method_debug_dump ************************************************
2001  
2002    Print debug info for unresolved_method to stream
2003   
2004    IN:
2005        ref..............the unresolved_method
2006            file.............the stream
2007
2008 *******************************************************************************/
2009
2010 void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
2011 {
2012         int i;
2013
2014         fprintf(file,"unresolved_method(%p):\n",(void *)ref);
2015         if (ref) {
2016                 fprintf(file,"    referer   : ");
2017                 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
2018                 fprintf(file,"    refmethod : ");
2019                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
2020                 fprintf(file,"    refmethodd: ");
2021                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
2022                 fprintf(file,"    classname : ");
2023                 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
2024                 fprintf(file,"    name      : ");
2025                 utf_fprint(file,ref->methodref->name); fputc('\n',file);
2026                 fprintf(file,"    descriptor: ");
2027                 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
2028                 fprintf(file,"    parseddesc: ");
2029                 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
2030                 fprintf(file,"    flags     : %04x\n",ref->flags);
2031                 fprintf(file,"    instancetypes:\n");
2032                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
2033                 fprintf(file,"    paramconstraints:\n");
2034                 if (ref->paramconstraints) {
2035                         for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
2036                                 fprintf(file,"      param %d:\n",i);
2037                                 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
2038                         }
2039                 } 
2040                 else {
2041                         fprintf(file,"      (empty)\n");
2042                 }
2043         }
2044 }
2045 #endif
2046
2047 /*
2048  * These are local overrides for various environment variables in Emacs.
2049  * Please do not remove this and leave it at the end of the file, where
2050  * Emacs will automagically detect them.
2051  * ---------------------------------------------------------------------
2052  * Local variables:
2053  * mode: c
2054  * indent-tabs-mode: t
2055  * c-basic-offset: 4
2056  * tab-width: 4
2057  * End:
2058  * vim:noexpandtab:sw=4:ts=4:
2059  */
2060