OSDN Git Service

2004-07-09 Michael Koch <konqueror@gmx.de>
[pf3gnuchains/gcc-fork.git] / libjava / defineclass.cc
1 // defineclass.cc - defining a class from .class format.
2
3 /* Copyright (C) 1999, 2000, 2001, 2002, 2003  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 /* 
12    Author: Kresten Krab Thorup <krab@gnu.org> 
13
14    Written using the online versions of Java Language Specification (1st
15    ed.) and The Java Virtual Machine Specification (2nd ed.). 
16
17    Future work may include reading (and handling) attributes which are
18    currently being ignored ("InnerClasses", "LineNumber", etc...).  
19 */
20
21 #include <config.h>
22
23 #include <java-interp.h>
24
25 #include <stdlib.h>
26 #include <java-cpool.h>
27 #include <gcj/cni.h>
28
29 #include <java/lang/Class.h>
30 #include <java/lang/Float.h>
31 #include <java/lang/Double.h>
32 #include <java/lang/Character.h>
33 #include <java/lang/LinkageError.h>
34 #include <java/lang/InternalError.h>
35 #include <java/lang/ClassFormatError.h>
36 #include <java/lang/NoClassDefFoundError.h>
37 #include <java/lang/ClassCircularityError.h>
38 #include <java/lang/IncompatibleClassChangeError.h>
39 #include <java/lang/reflect/Modifier.h>
40
41 using namespace gcj;
42
43 #ifdef INTERPRETER
44
45 // these go in some separate functions, to avoid having _Jv_InitClass
46 // inserted all over the place.
47 static void throw_internal_error (char *msg)
48         __attribute__ ((__noreturn__));
49 static void throw_no_class_def_found_error (jstring msg)
50         __attribute__ ((__noreturn__));
51 static void throw_no_class_def_found_error (char *msg)
52         __attribute__ ((__noreturn__));
53 static void throw_class_format_error (jstring msg)
54         __attribute__ ((__noreturn__));
55 static void throw_incompatible_class_change_error (jstring msg)
56         __attribute__ ((__noreturn__));
57 static void throw_class_circularity_error (jstring msg)
58         __attribute__ ((__noreturn__));
59
60 /**
61  * We define class reading using a class.  It is practical, since then
62  * the entire class-reader can be a friend of class Class (it needs to
63  * write all it's different structures); but also because this makes it
64  * easy to make class definition reentrant, and thus two threads can be
65  * defining classes at the same time.   This class (_Jv_ClassReader) is
66  * never exposed outside this file, so we don't have to worry about
67  * public or private members here.
68  */
69
70 struct _Jv_ClassReader {
71
72   // do verification?  Currently, there is no option to disable this.
73   // This flag just controls the verificaiton done by the class loader;
74   // i.e., checking the integrity of the constant pool; and it is
75   // allways on.  You always want this as far as I can see, but it also
76   // controls weither identifiers and type descriptors/signatures are
77   // verified as legal.  This could be somewhat more expensive since it
78   // will call Character.isJavaIdentifier{Start,Part} for each character
79   // in any identifier (field name or method name) it comes by.  Thus,
80   // it might be useful to turn off this verification for classes that
81   // come from a trusted source.  However, for GCJ, trusted classes are
82   // most likely to be linked in.
83
84   bool verify;
85
86   // input data.
87   unsigned char     *bytes;
88   int                len;
89
90   // current input position
91   int                pos;
92
93   // the constant pool data
94   int pool_count;
95   unsigned char     *tags;
96   unsigned int      *offsets;
97
98   // the class to define (see java-interp.h)
99   jclass           def;
100   
101   // the classes associated interpreter data.
102   _Jv_InterpClass  *def_interp;
103
104   /* check that the given number of input bytes are available */
105   inline void check (int num)
106   {
107     if (pos + num > len)
108       throw_class_format_error ("Premature end of data");
109   }
110
111   /* skip a given number of bytes in input */
112   inline void skip (int num)
113   {
114     check (num);
115     pos += num;
116   }
117   
118   /* read an unsignend 1-byte unit */
119   inline static jint get1u (unsigned char* bytes)
120   {
121     return bytes[0];
122   }
123   
124   /* read an unsigned 1-byte unit */
125   inline jint read1u ()
126   {
127     skip (1);
128     return get1u (bytes+pos-1);
129   }
130   
131   /* read an unsigned 2-byte unit */
132   inline static jint get2u (unsigned char *bytes)
133   {
134     return (((jint)bytes[0]) << 8) | ((jint)bytes[1]);
135   }
136   
137   /* read an unsigned 2-byte unit */
138   inline jint read2u ()
139   {
140     skip (2);  
141     return get2u (bytes+pos-2);
142   }
143   
144   /* read a 4-byte unit */
145   static jint get4 (unsigned char *bytes)
146   {
147     return (((jint)bytes[0]) << 24)
148          | (((jint)bytes[1]) << 16)
149          | (((jint)bytes[2]) << 8)
150          | (((jint)bytes[3]) << 0);
151   }
152
153   /* read a 4-byte unit, (we don't do that quite so often) */
154   inline jint read4 ()
155   {
156     skip (4);  
157     return get4 (bytes+pos-4);
158   }
159
160   /* read a 8-byte unit */
161   static jlong get8 (unsigned char* bytes)
162   {
163     return (((jlong)bytes[0]) << 56)
164          | (((jlong)bytes[1]) << 48)
165          | (((jlong)bytes[2]) << 40)
166          | (((jlong)bytes[3]) << 32) 
167          | (((jlong)bytes[4]) << 24)
168          | (((jlong)bytes[5]) << 16)
169          | (((jlong)bytes[6]) << 8)
170          | (((jlong)bytes[7]) << 0);
171   }
172
173   /* read a 8-byte unit */
174   inline jlong read8 ()
175   {
176     skip (8);  
177     return get8 (bytes+pos-8);
178   }
179
180   inline void check_tag (int index, char expected_tag)
181   {
182     if (index < 0
183         || index > pool_count
184         || tags[index] != expected_tag)
185       throw_class_format_error ("erroneous constant pool tag");
186   }
187
188   inline void verify_identifier (_Jv_Utf8Const* name)
189   {
190     if (! _Jv_VerifyIdentifier (name))
191       throw_class_format_error ("erroneous identifier");
192   }
193
194   inline void verify_classname (unsigned char* ptr, _Jv_ushort length)
195   {
196     if (! _Jv_VerifyClassName (ptr, length))
197       throw_class_format_error ("erroneous class name");
198   }
199
200   inline void verify_classname (_Jv_Utf8Const *name)
201   {
202     if (! _Jv_VerifyClassName (name))
203       throw_class_format_error ("erroneous class name");
204   }
205
206   inline void verify_field_signature (_Jv_Utf8Const *sig)
207   {
208     if (! _Jv_VerifyFieldSignature (sig))
209       throw_class_format_error ("erroneous type descriptor");
210   }
211
212   inline void verify_method_signature (_Jv_Utf8Const *sig)
213   {
214     if (! _Jv_VerifyMethodSignature (sig))
215       throw_class_format_error ("erroneous type descriptor");
216   }
217
218   _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length)
219   {
220     if (klass == 0 || length < 0 || offset+length > data->length)
221       throw_internal_error ("arguments to _Jv_DefineClass");
222
223     verify = true;
224     bytes  = (unsigned char*) (elements (data)+offset);
225     len    = length;
226     pos    = 0;
227     def    = klass;
228     def_interp = (_Jv_InterpClass *) def->aux_info;
229   }
230
231   /** and here goes the parser members defined out-of-line */
232   void parse ();
233   void read_constpool ();
234   void prepare_pool_entry (int index, unsigned char tag);
235   void read_fields ();
236   void read_methods ();
237   void read_one_class_attribute ();
238   void read_one_method_attribute (int method);
239   void read_one_code_attribute (int method);
240   void read_one_field_attribute (int field);
241   void throw_class_format_error (char *msg);
242
243   /** check an utf8 entry, without creating a Utf8Const object */
244   bool is_attribute_name (int index, char *name);
245
246   /** here goes the class-loader members defined out-of-line */
247   void handleConstantPool ();
248   void handleClassBegin (int, int, int);
249   void handleInterfacesBegin (int);
250   void handleInterface (int, int);
251   void handleFieldsBegin (int);
252   void handleField (int, int, int, int);
253   void handleFieldsEnd ();
254   void handleConstantValueAttribute (int,int);
255   void handleMethodsBegin (int);
256   void handleMethod (int, int, int, int);
257   void handleMethodsEnd ();
258   void handleCodeAttribute (int, int, int, int, int, int);
259   void handleExceptionTableEntry (int, int, int, int, int, int);
260
261   void checkExtends (jclass sub, jclass super);
262   void checkImplements (jclass sub, jclass super);
263
264   /*
265    * FIXME: we should keep a hash table of utf8-strings, since many will
266    * be the same.  It's a little tricky, however, because the hash table
267    * needs to interact gracefully with the garbage collector.  Much
268    * memory is to be saved by this, however!  perhaps the improvement
269    * could be implemented in prims.cc (_Jv_makeUtf8Const), since it
270    * computes the hash value anyway.
271    */
272 };
273
274 void
275 _Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length)
276 {
277   _Jv_ClassReader reader (klass, data, offset, length);
278   reader.parse();
279
280   /* that's it! */
281 }
282
283 \f
284 /** This section defines the parsing/scanning of the class data */
285
286 void
287 _Jv_ClassReader::parse ()
288 {
289   int magic = read4 ();
290
291   /* FIXME: Decide which range of version numbers to allow */
292
293   /* int minor_version = */ read2u ();
294   /* int major_verson  = */ read2u ();
295
296   if (magic != (int) 0xCAFEBABE)
297     throw_class_format_error ("bad magic number");
298
299   pool_count = read2u ();
300
301   read_constpool ();
302
303   int access_flags = read2u ();
304   int this_class = read2u ();
305   int super_class = read2u ();
306
307   check_tag (this_class, JV_CONSTANT_Class);
308   if (super_class != 0) 
309     check_tag (super_class, JV_CONSTANT_Class);
310
311   handleClassBegin (access_flags, this_class, super_class);
312
313   int interfaces_count = read2u (); 
314         
315   handleInterfacesBegin (interfaces_count);
316
317   for (int i = 0; i < interfaces_count; i++)
318     {
319       int iface = read2u ();
320       check_tag (iface, JV_CONSTANT_Class);
321       handleInterface (i, iface);
322     }
323   
324   read_fields ();
325   read_methods ();
326   
327   int attributes_count = read2u ();
328   
329   for (int i = 0; i < attributes_count; i++)
330     {
331       read_one_class_attribute ();
332     }
333
334   if (pos != len)
335     throw_class_format_error ("unused data before end of file");
336
337   // tell everyone we're done.
338   def->state = JV_STATE_LOADED;
339   def->notifyAll ();
340
341 }
342
343 void _Jv_ClassReader::read_constpool ()
344 {
345   tags    = (unsigned char*) _Jv_AllocBytes (pool_count);
346   offsets = (unsigned int *) _Jv_AllocBytes (sizeof (int)
347                                                     * pool_count) ;
348
349   /** first, we scan the constant pool, collecting tags and offsets */
350   tags[0]   = JV_CONSTANT_Undefined;
351   offsets[0] = pos;
352   for (int c = 1; c < pool_count; c++)
353     {
354       tags[c]    = read1u ();
355       offsets[c] = pos;
356
357       switch (tags[c])
358         {
359         case JV_CONSTANT_String:
360         case JV_CONSTANT_Class:
361           skip (2);
362           break;
363
364         case JV_CONSTANT_Fieldref:
365         case JV_CONSTANT_Methodref:
366         case JV_CONSTANT_InterfaceMethodref:
367         case JV_CONSTANT_NameAndType:
368         case JV_CONSTANT_Integer:
369         case JV_CONSTANT_Float:
370           skip (4);
371           break;
372
373         case JV_CONSTANT_Double:
374         case JV_CONSTANT_Long:
375           skip (8);
376           tags[++c] = JV_CONSTANT_Undefined;
377           break;
378             
379         case JV_CONSTANT_Utf8:
380           {                 
381             int len = read2u ();
382             skip (len);
383           }
384           break;
385
386         case JV_CONSTANT_Unicode:
387           throw_class_format_error ("unicode not supported");
388           break;
389
390         default:
391           throw_class_format_error ("erroneous constant pool tag");
392         }
393     }
394
395   handleConstantPool ();
396 }
397
398
399 void _Jv_ClassReader::read_fields ()
400 {
401   int fields_count = read2u ();
402   handleFieldsBegin (fields_count);
403
404   for (int i = 0; i < fields_count; i++)
405     {
406       int access_flags     = read2u ();
407       int name_index       = read2u ();
408       int descriptor_index = read2u ();
409       int attributes_count = read2u ();
410
411       check_tag (name_index, JV_CONSTANT_Utf8);
412       prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
413
414       check_tag (descriptor_index, JV_CONSTANT_Utf8);
415       prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
416
417       handleField (i, access_flags, name_index, descriptor_index);
418
419       for (int j = 0; j < attributes_count; j++)
420         {
421           read_one_field_attribute (i);
422         }
423     }
424
425   handleFieldsEnd ();
426 }
427
428 bool
429 _Jv_ClassReader::is_attribute_name (int index, char *name)
430 {
431   check_tag (index, JV_CONSTANT_Utf8);
432   int len = get2u (bytes+offsets[index]);
433   if (len != (int) strlen (name))
434     return false;
435   else
436     return !memcmp (bytes+offsets[index]+2, name, len);
437 }
438
439 void _Jv_ClassReader::read_one_field_attribute (int field_index)
440 {
441   int name = read2u ();
442   int length = read4 ();
443
444   if (is_attribute_name (name, "ConstantValue"))
445     {
446       int cv = read2u ();
447
448       if (cv < pool_count 
449           && cv > 0
450           && (tags[cv] == JV_CONSTANT_Integer
451               || tags[cv] == JV_CONSTANT_Float
452               || tags[cv] == JV_CONSTANT_Long
453               || tags[cv] == JV_CONSTANT_Double
454               || tags[cv] == JV_CONSTANT_String))
455           {
456             handleConstantValueAttribute (field_index, cv);
457           }
458         else
459           {
460             throw_class_format_error ("erroneous ConstantValue attribute");
461           }
462
463         if (length != 2) 
464           throw_class_format_error ("erroneous ConstantValue attribute");
465       }
466
467     else
468       {
469         skip (length);
470       }
471 }
472
473 void _Jv_ClassReader::read_methods ()
474 {
475   int methods_count = read2u ();
476   
477   handleMethodsBegin (methods_count);
478   
479   for (int i = 0; i < methods_count; i++)
480     {
481       int access_flags     = read2u ();
482       int name_index       = read2u ();
483       int descriptor_index = read2u ();
484       int attributes_count = read2u ();
485       
486       check_tag (name_index, JV_CONSTANT_Utf8);
487       prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
488
489       check_tag (name_index, JV_CONSTANT_Utf8);
490       prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
491
492       handleMethod (i, access_flags, name_index,
493                     descriptor_index);
494
495       for (int j = 0; j < attributes_count; j++)
496         {
497           read_one_method_attribute (i);
498         }
499     }
500   
501   handleMethodsEnd ();
502 }
503
504 void _Jv_ClassReader::read_one_method_attribute (int method_index) 
505 {
506   int name = read2u ();
507   int length = read4 ();
508
509   if (is_attribute_name (name, "Exceptions"))
510     {
511       _Jv_Method *method = reinterpret_cast<_Jv_Method *>
512         (&def->methods[method_index]);
513       if (method->throws != NULL)
514         throw_class_format_error ("only one Exceptions attribute allowed per method");
515
516       int num_exceptions = read2u ();
517       // We use malloc here because the GC won't scan the method
518       // objects.  FIXME this means a memory leak if we GC a class.
519       // (Currently we never do.)
520       _Jv_Utf8Const **exceptions =
521         (_Jv_Utf8Const **) _Jv_Malloc ((num_exceptions + 1) * sizeof (_Jv_Utf8Const *));
522
523       int out = 0;
524       _Jv_word *pool_data = def->constants.data;
525       for (int i = 0; i < num_exceptions; ++i)
526         {
527           try
528             {
529               int ndx = read2u ();
530               // JLS 2nd Ed. 4.7.5 requires that the tag not be 0.
531               if (ndx != 0)
532                 {
533                   check_tag (ndx, JV_CONSTANT_Class);
534                   exceptions[out++] = pool_data[ndx].utf8; 
535                 }
536             }
537           catch (java::lang::Throwable *exc)
538             {
539               _Jv_Free (exceptions);
540               throw exc;
541             }
542         }
543       exceptions[out] = NULL;
544       method->throws = exceptions;
545     }
546
547   else if (is_attribute_name (name, "Code"))
548     {
549       int start_off = pos;
550       int max_stack = read2u ();
551       int max_locals = read2u ();
552       int code_length = read4 ();
553
554       int code_start = pos;
555       skip (code_length);
556       int exception_table_length = read2u ();
557
558       handleCodeAttribute (method_index, 
559                            max_stack, max_locals,
560                            code_start, code_length,
561                            exception_table_length);
562       
563
564       for (int i = 0; i < exception_table_length; i++)
565         {
566           int start_pc   = read2u ();
567           int end_pc     = read2u ();
568           int handler_pc = read2u ();
569           int catch_type = read2u ();
570
571           if (start_pc > end_pc
572               || start_pc < 0
573               // END_PC can be equal to CODE_LENGTH.
574               // See JVM Spec 4.7.4.
575               || end_pc > code_length
576               || handler_pc >= code_length)
577             throw_class_format_error ("erroneous exception handler info");
578
579           if (! (tags[catch_type] == JV_CONSTANT_Class
580                  || tags[catch_type] == 0))
581             {
582               throw_class_format_error ("erroneous exception handler info");
583             }
584
585           handleExceptionTableEntry (method_index,
586                                      i,
587                                      start_pc,
588                                      end_pc,
589                                      handler_pc, 
590                                      catch_type);
591
592         }
593
594       int attributes_count = read2u ();
595
596       for (int i = 0; i < attributes_count; i++)
597         {
598           read_one_code_attribute (method_index);
599         }
600
601       if ((pos - start_off) != length)
602         throw_class_format_error ("code attribute too short");
603     }
604
605   else
606     {
607       /* ignore unknown attributes */
608       skip (length);
609     }
610 }
611
612 void _Jv_ClassReader::read_one_code_attribute (int /*method*/) 
613 {
614   /* ignore for now, ... later we may want to pick up
615      line number information, for debugging purposes;
616      in fact, the whole debugger issue is open!  */
617
618   /* int name = */ read2u ();
619   int length = read4 ();
620   skip (length);
621
622 }
623
624 void _Jv_ClassReader::read_one_class_attribute () 
625 {
626   /* we also ignore the class attributes, ...
627      some day we'll add inner-classes support. */
628
629   /* int name = */ read2u ();
630   int length = read4 ();
631   skip (length);
632 }
633
634
635
636 \f
637 /* this section defines the semantic actions of the parser */
638
639 void _Jv_ClassReader::handleConstantPool ()
640 {
641   /** now, we actually define the class' constant pool */
642
643   // the pool is scanned explicitly by the collector
644   jbyte *pool_tags = (jbyte*) _Jv_AllocBytes (pool_count);
645   _Jv_word *pool_data
646     = (_Jv_word*) _Jv_AllocBytes (pool_count * sizeof (_Jv_word));
647   
648   def->constants.tags = pool_tags;
649   def->constants.data = pool_data;
650   def->constants.size = pool_count;
651
652   // Here we make a pass to collect the strings!   We do this, because
653   // internally in the GCJ runtime, classes are encoded with .'s not /'s. 
654   // Therefore, we first collect the strings, and then translate the rest
655   // of the utf8-entries (thus not representing strings) from /-notation
656   // to .-notation.
657   for (int i = 1; i < pool_count; i++)
658     {
659       if (tags[i] == JV_CONSTANT_String)
660         {
661           unsigned char* str_data = bytes + offsets [i];
662           int utf_index = get2u (str_data);
663           check_tag (utf_index, JV_CONSTANT_Utf8);
664           unsigned char *utf_data = bytes + offsets[utf_index];
665           int len = get2u (utf_data);
666           pool_data[i].utf8 = _Jv_makeUtf8Const ((char*)(utf_data+2), len);
667           pool_tags[i] = JV_CONSTANT_String;
668         }
669       else
670         {
671           pool_tags[i] = JV_CONSTANT_Undefined;
672         }
673     }
674
675   // and now, we scan everything else but strings & utf8-entries.  This
676   // leaves out those utf8-entries which are not used; which will be left
677   // with a tag of JV_CONSTANT_Undefined in the class definition.
678   for (int index = 1; index < pool_count; index++)
679     {
680       switch (tags[index])
681         {
682         case JV_CONSTANT_Undefined:
683         case JV_CONSTANT_String:
684         case JV_CONSTANT_Utf8:
685           continue;
686           
687         default:
688           prepare_pool_entry (index, tags[index]);
689         }
690     }  
691   
692 }
693
694 /* this is a recursive procedure, which will prepare pool entries as needed.
695    Which is how we avoid initializing those entries which go unused. */
696 void
697 _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
698 {
699   /* these two, pool_data and pool_tags, point into the class
700      structure we are currently defining */
701
702   unsigned char *pool_tags = (unsigned char*) def->constants.tags;
703   _Jv_word      *pool_data = def->constants.data;
704
705   /* this entry was already prepared */
706   if (pool_tags[index] == this_tag)
707     return;
708
709   /* this_data points to the constant-pool information for the current
710      constant-pool entry */
711
712   unsigned char *this_data = bytes + offsets[index];
713
714   switch (this_tag)
715     {
716     case JV_CONSTANT_Utf8: 
717       {
718         // If we came here, it is because some other tag needs this
719         // utf8-entry for type information!  Thus, we translate /'s to .'s in
720         // order to accomondate gcj's internal representation.
721
722         int len = get2u (this_data);
723         char *buffer = (char*) __builtin_alloca (len);
724         char *s = ((char*) this_data)+2;
725
726         /* FIXME: avoid using a buffer here */
727         for (int i = 0; i < len; i++)
728           {
729             if (s[i] == '/')
730               buffer[i] = '.';
731             else
732               buffer[i] = (char) s[i];
733           }
734         
735         pool_data[index].utf8 = _Jv_makeUtf8Const (buffer, len);
736         pool_tags[index] = JV_CONSTANT_Utf8;
737       }
738       break;
739             
740     case JV_CONSTANT_Class:      
741       {
742         int utf_index = get2u (this_data);
743         check_tag (utf_index, JV_CONSTANT_Utf8);
744         prepare_pool_entry (utf_index, JV_CONSTANT_Utf8);
745
746         if (verify)
747           verify_classname (pool_data[utf_index].utf8);
748                 
749         pool_data[index].utf8 = pool_data[utf_index].utf8;
750         pool_tags[index] = JV_CONSTANT_Class;
751       }
752       break;
753             
754     case JV_CONSTANT_String:
755       // already handled before... 
756       break;
757             
758     case JV_CONSTANT_Fieldref:
759     case JV_CONSTANT_Methodref:
760     case JV_CONSTANT_InterfaceMethodref:
761       {
762         int class_index = get2u (this_data);
763         int nat_index = get2u (this_data+2);
764
765         check_tag (class_index, JV_CONSTANT_Class);
766         prepare_pool_entry (class_index, JV_CONSTANT_Class);        
767
768         check_tag (nat_index, JV_CONSTANT_NameAndType);
769         prepare_pool_entry (nat_index, JV_CONSTANT_NameAndType);
770
771         // here, verify the signature and identifier name
772         if (verify)
773         {
774           _Jv_ushort name_index, type_index;
775           _Jv_loadIndexes (&pool_data[nat_index],
776                            name_index, type_index);
777
778           if (this_tag == JV_CONSTANT_Fieldref)
779             verify_field_signature (pool_data[type_index].utf8);
780           else
781             verify_method_signature (pool_data[type_index].utf8);
782
783           _Jv_Utf8Const* name = pool_data[name_index].utf8;
784
785           if (this_tag != JV_CONSTANT_Fieldref
786               && (   _Jv_equalUtf8Consts (name, clinit_name)
787                   || _Jv_equalUtf8Consts (name, init_name)))
788             /* ignore */;
789           else
790             verify_identifier (pool_data[name_index].utf8);
791         }
792             
793         _Jv_storeIndexes (&pool_data[index], class_index, nat_index);
794         pool_tags[index] = this_tag;
795       }
796       break;
797             
798     case JV_CONSTANT_NameAndType:
799       {
800         _Jv_ushort name_index = get2u (this_data);
801         _Jv_ushort type_index = get2u (this_data+2);
802
803         check_tag (name_index, JV_CONSTANT_Utf8);
804         prepare_pool_entry (name_index, JV_CONSTANT_Utf8);          
805
806         check_tag (type_index, JV_CONSTANT_Utf8);
807         prepare_pool_entry (type_index, JV_CONSTANT_Utf8);
808
809         _Jv_storeIndexes (&pool_data[index], name_index, type_index);
810         pool_tags[index] = JV_CONSTANT_NameAndType;
811       }
812       break;
813             
814     case JV_CONSTANT_Float:
815       {
816         jfloat f = java::lang::Float::intBitsToFloat ((jint) get4 (this_data));
817         _Jv_storeFloat (&pool_data[index], f);
818         pool_tags[index] = JV_CONSTANT_Float;
819       }
820       break;
821             
822     case JV_CONSTANT_Integer:
823       {
824         int i = get4 (this_data);
825         _Jv_storeInt (&pool_data[index], i);
826         pool_tags[index] = JV_CONSTANT_Integer;
827       }
828       break;
829             
830     case JV_CONSTANT_Double:
831       {
832         jdouble d
833           = java::lang::Double::longBitsToDouble ((jlong) get8 (this_data));
834         _Jv_storeDouble (&pool_data[index], d);
835         pool_tags[index] = JV_CONSTANT_Double;
836       }
837       break;
838             
839     case JV_CONSTANT_Long:
840       {
841         jlong i = get8 (this_data);
842         _Jv_storeLong (&pool_data[index], i);
843         pool_tags[index] = JV_CONSTANT_Long;
844       }
845       break;
846             
847     default:
848       throw_class_format_error ("erroneous constant pool tag");
849     }
850 }
851
852
853 void
854 _Jv_ClassReader::handleClassBegin
855   (int access_flags, int this_class, int super_class)
856 {
857   using namespace java::lang::reflect;
858
859   unsigned char *pool_tags = (unsigned char*) def->constants.tags;
860   _Jv_word      *pool_data = def->constants.data;
861
862   check_tag (this_class, JV_CONSTANT_Class);
863   _Jv_Utf8Const *loadedName = pool_data[this_class].utf8;
864
865   // was ClassLoader.defineClass called with an expected class name?
866   if (def->name == 0)
867     {
868       jclass orig = _Jv_FindClassInCache (loadedName, def->loader);
869
870       if (orig == 0)
871         {
872           def->name = loadedName;
873         }
874       else
875         {
876           jstring msg = JvNewStringUTF ("anonymous "
877                                         "class data denotes "
878                                         "existing class ");
879           msg = msg->concat (orig->getName ());
880
881           throw_no_class_def_found_error (msg);
882         }
883     }
884
885   // assert that the loaded class has the expected name, 5.3.5
886   else if (! _Jv_equalUtf8Consts (loadedName, def->name))
887     {
888       jstring msg = JvNewStringUTF ("loaded class ");
889       msg = msg->concat (def->getName ());
890       msg = msg->concat (_Jv_NewStringUTF (" was in fact named "));
891       jstring klass_name = _Jv_NewStringUTF (loadedName->data);
892       msg = msg->concat (klass_name);
893
894       throw_no_class_def_found_error (msg);
895     }
896
897   def->accflags = access_flags | java::lang::reflect::Modifier::INTERPRETED;
898   pool_data[this_class].clazz = def;
899   pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
900
901   if (super_class == 0 && ! (access_flags & Modifier::INTERFACE))
902     {
903       // FIXME: Consider this carefully!  
904       if (! _Jv_equalUtf8Consts (def->name, java::lang::Object::class$.name))
905         throw_no_class_def_found_error ("loading java.lang.Object");
906     }
907
908   // In the pre-loading state, it can be looked up in the
909   // cache only by this thread!  This allows the super-class
910   // to include references to this class.
911
912   def->state = JV_STATE_PRELOADING;
913
914   {
915     JvSynchronize sync (&java::lang::Class::class$);
916     _Jv_RegisterClass (def);
917   }
918
919   if (super_class != 0)
920     {
921       // Load the superclass.
922       check_tag (super_class, JV_CONSTANT_Class);
923       _Jv_Utf8Const* super_name = pool_data[super_class].utf8; 
924
925       // Load the superclass using our defining loader.
926       jclass the_super = _Jv_FindClass (super_name,
927                                         def->loader);
928
929       // This will establish that we are allowed to be a subclass,
930       // and check for class circularity error.
931       checkExtends (def, the_super);
932
933       // Note: for an interface we will find Object as the
934       // superclass.  We still check it above to ensure class file
935       // validity, but we simply assign `null' to the actual field in
936       // this case.
937       def->superclass = (((access_flags & Modifier::INTERFACE))
938                          ? NULL : the_super);
939       pool_data[super_class].clazz = the_super;
940       pool_tags[super_class] = JV_CONSTANT_ResolvedClass;
941     }
942
943   // Now we've come past the circularity problem, we can 
944   // now say that we're loading.
945
946   def->state = JV_STATE_LOADING;
947   def->notifyAll ();
948 }
949
950 ///// implements the checks described in sect. 5.3.5.3
951 void
952 _Jv_ClassReader::checkExtends (jclass sub, jclass super)
953 {
954   using namespace java::lang::reflect;
955
956   // having an interface or a final class as a superclass is no good
957   if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
958     {
959       throw_incompatible_class_change_error (sub->getName ());
960     }
961
962   // if the super class is not public, we need to check some more
963   if ((super->accflags & Modifier::PUBLIC) == 0)
964     {
965       // With package scope, the classes must have the same
966       // class loader.
967       if (   sub->loader != super->loader
968           || !_Jv_ClassNameSamePackage (sub->name, super->name))
969         {
970           throw_incompatible_class_change_error (sub->getName ());
971         }
972     } 
973
974   for (; super != 0; super = super->superclass)
975     {
976       if (super == sub)
977         throw_class_circularity_error (sub->getName ());
978     }
979 }
980
981
982
983 void _Jv_ClassReader::handleInterfacesBegin (int count)
984 {
985   def->interfaces = (jclass*) _Jv_AllocBytes (count*sizeof (jclass));
986   def->interface_count = count;
987 }
988
989 void _Jv_ClassReader::handleInterface (int if_number, int offset)
990 {
991   _Jv_word       * pool_data = def->constants.data;
992   unsigned char  * pool_tags = (unsigned char*) def->constants.tags;
993
994   jclass the_interface;
995
996   if (pool_tags[offset] == JV_CONSTANT_Class)
997     {
998       _Jv_Utf8Const* name = pool_data[offset].utf8;
999       the_interface =  _Jv_FindClass (name, def->loader);
1000     }
1001   else if (pool_tags[offset] == JV_CONSTANT_ResolvedClass)
1002     {
1003       the_interface = pool_data[offset].clazz;
1004     }
1005   else
1006     {
1007       throw_no_class_def_found_error ("erroneous constant pool tag");
1008     }
1009
1010   // checks the validity of the_interface, and that we are in fact
1011   // allowed to implement that interface.
1012   checkImplements (def, the_interface);
1013   
1014   pool_data[offset].clazz = the_interface;
1015   pool_tags[offset] = JV_CONSTANT_ResolvedClass;
1016   
1017   def->interfaces[if_number] = the_interface;
1018 }
1019
1020 void
1021 _Jv_ClassReader::checkImplements (jclass sub, jclass super)
1022 {
1023   using namespace java::lang::reflect;
1024
1025   // well, it *must* be an interface
1026   if ((super->accflags & Modifier::INTERFACE) == 0)
1027     {
1028       throw_incompatible_class_change_error (sub->getName ());
1029     }
1030
1031   // if it has package scope, it must also be defined by the 
1032   // same loader.
1033   if ((super->accflags & Modifier::PUBLIC) == 0)
1034     {
1035       if (    sub->loader != super->loader
1036           || !_Jv_ClassNameSamePackage (sub->name, super->name))
1037         {
1038           throw_incompatible_class_change_error (sub->getName ());
1039         }
1040     } 
1041
1042   // FIXME: add interface circularity check here
1043   if (sub == super)
1044     {
1045       throw_class_circularity_error (sub->getName ());
1046     }           
1047 }
1048
1049 void _Jv_ClassReader::handleFieldsBegin (int count)
1050 {
1051   def->fields = (_Jv_Field*) 
1052     _Jv_AllocBytes (count * sizeof (_Jv_Field));
1053   def->field_count = count;
1054   def_interp->field_initializers = (_Jv_ushort*)
1055     _Jv_AllocBytes (count * sizeof (_Jv_ushort));
1056   for (int i = 0; i < count; i++)
1057     def_interp->field_initializers[i] = (_Jv_ushort) 0;
1058 }
1059
1060 void _Jv_ClassReader::handleField (int field_no,
1061                                    int flags,
1062                                    int name,
1063                                    int desc)
1064 {
1065   using namespace java::lang::reflect;
1066
1067   _Jv_word *pool_data = def->constants.data;
1068
1069   _Jv_Field *field = &def->fields[field_no];
1070   _Jv_Utf8Const *field_name = pool_data[name].utf8;
1071
1072 #ifndef COMPACT_FIELDS
1073   field->name      = field_name;
1074 #else
1075   field->nameIndex = name;
1076 #endif
1077
1078   // Ignore flags we don't know about.  
1079   field->flags = flags & Modifier::ALL_FLAGS;
1080
1081   _Jv_Utf8Const* sig = pool_data[desc].utf8;
1082
1083   if (verify)
1084     {
1085       verify_identifier (field_name);
1086
1087       for (int i = 0; i < field_no; ++i)
1088         {
1089           if (_Jv_equalUtf8Consts (field_name, def->fields[i].name)
1090               && _Jv_equalUtf8Consts (sig,
1091                                       // We know the other fields are
1092                                       // unresolved.
1093                                       (_Jv_Utf8Const *) def->fields[i].type))
1094             throw_class_format_error ("duplicate field name");
1095         }
1096
1097       if (field->flags & (Modifier::SYNCHRONIZED
1098                           | Modifier::NATIVE
1099                           | Modifier::INTERFACE
1100                           | Modifier::ABSTRACT))
1101         throw_class_format_error ("erroneous field access flags");
1102       
1103       if (1 < ( ((field->flags & Modifier::PUBLIC) ? 1 : 0)
1104                 +((field->flags & Modifier::PRIVATE) ? 1 : 0)
1105                 +((field->flags & Modifier::PROTECTED) ? 1 : 0)))
1106         throw_class_format_error ("erroneous field access flags");
1107     }
1108
1109   if (verify)
1110     verify_field_signature (sig);
1111
1112   // field->type is really a jclass, but while it is still
1113   // unresolved we keep an _Jv_Utf8Const* instead.
1114   field->type       = (jclass) sig;
1115   field->flags     |= _Jv_FIELD_UNRESOLVED_FLAG;
1116   field->u.boffset  = 0;
1117 }
1118
1119
1120 void _Jv_ClassReader::handleConstantValueAttribute (int field_index, 
1121                                                     int value)
1122 {
1123   using namespace java::lang::reflect;
1124
1125   _Jv_Field *field = &def->fields[field_index];
1126
1127   if ((field->flags & (Modifier::STATIC
1128                        | Modifier::FINAL
1129                        | Modifier::PRIVATE)) == 0)
1130     {
1131       // Ignore, as per vmspec #4.7.2
1132       return;
1133     }
1134
1135   // do not allow multiple constant fields!
1136   if (field->flags & _Jv_FIELD_CONSTANT_VALUE)
1137     throw_class_format_error ("field has multiple ConstantValue attributes");
1138
1139   field->flags |= _Jv_FIELD_CONSTANT_VALUE;
1140   def_interp->field_initializers[field_index] = value;
1141
1142   /* type check the initializer */
1143   
1144   if (value <= 0 || value >= pool_count)
1145     throw_class_format_error ("erroneous ConstantValue attribute");
1146
1147   /* FIXME: do the rest */
1148 }
1149
1150 void _Jv_ClassReader::handleFieldsEnd ()
1151 {
1152   using namespace java::lang::reflect;
1153
1154   // We need to reorganize the fields so that the static ones are first,
1155   // to conform to GCJ class layout.
1156
1157   int low            = 0;
1158   int high           = def->field_count-1;
1159   _Jv_Field  *fields = def->fields;
1160   _Jv_ushort *inits  = def_interp->field_initializers;
1161
1162   // this is kind of a raw version of quicksort.
1163   while (low < high)
1164     {
1165       // go forward on low, while it's a static
1166       while (low < high && (fields[low].flags & Modifier::STATIC) != 0)
1167         low++;
1168       
1169       // go backwards on high, while it's a non-static
1170       while (low < high && (fields[high].flags & Modifier::STATIC) == 0)
1171         high--;
1172
1173       if (low==high)
1174         break;
1175
1176       _Jv_Field  tmp  = fields[low];
1177       _Jv_ushort itmp = inits[low];
1178           
1179       fields[low] = fields[high];
1180       inits[low]  = inits[high];
1181           
1182       fields[high] = tmp;
1183       inits[high]  = itmp;
1184           
1185       high -= 1;
1186       low  += 1;
1187     }
1188   
1189   if ((fields[low].flags & Modifier::STATIC) != 0) 
1190     low += 1;
1191
1192   def->static_field_count = low;
1193 }
1194
1195
1196
1197 void
1198 _Jv_ClassReader::handleMethodsBegin (int count)
1199 {
1200   def->methods = (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method) * count);
1201
1202   def_interp->interpreted_methods
1203     = (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *)
1204                                           * count);
1205
1206   for (int i = 0; i < count; i++)
1207     {
1208       def_interp->interpreted_methods[i] = 0;
1209       def->methods[i].index = (_Jv_ushort) -1;
1210     }
1211
1212   def->method_count = count;
1213 }
1214
1215
1216 void _Jv_ClassReader::handleMethod 
1217     (int mth_index, int accflags, int name, int desc)
1218
1219   using namespace java::lang::reflect;
1220
1221   _Jv_word *pool_data = def->constants.data;
1222   _Jv_Method *method = &def->methods[mth_index];
1223
1224   check_tag (name, JV_CONSTANT_Utf8);
1225   prepare_pool_entry (name, JV_CONSTANT_Utf8);
1226   method->name = pool_data[name].utf8;
1227
1228   check_tag (desc, JV_CONSTANT_Utf8);
1229   prepare_pool_entry (desc, JV_CONSTANT_Utf8);
1230   method->signature = pool_data[desc].utf8;
1231
1232   // ignore unknown flags
1233   method->accflags = accflags & Modifier::ALL_FLAGS;
1234
1235   // intialize...
1236   method->ncode = 0;
1237   method->throws = NULL;
1238   
1239   if (verify)
1240     {
1241       if (_Jv_equalUtf8Consts (method->name, clinit_name)
1242           || _Jv_equalUtf8Consts (method->name, init_name))
1243         /* ignore */;
1244       else
1245         verify_identifier (method->name);
1246
1247       verify_method_signature (method->signature);
1248
1249       for (int i = 0; i < mth_index; ++i)
1250         {
1251           if (_Jv_equalUtf8Consts (method->name, def->methods[i].name)
1252               && _Jv_equalUtf8Consts (method->signature,
1253                                       def->methods[i].signature))
1254             throw_class_format_error ("duplicate method");
1255         }
1256
1257       if (method->accflags & (Modifier::VOLATILE
1258                               | Modifier::TRANSIENT
1259                               | Modifier::INTERFACE))
1260         throw_class_format_error ("erroneous method access flags");
1261       
1262       if (1 < ( ((method->accflags & Modifier::PUBLIC) ? 1 : 0)
1263                 +((method->accflags & Modifier::PRIVATE) ? 1 : 0)
1264                 +((method->accflags & Modifier::PROTECTED) ? 1 : 0)))
1265         throw_class_format_error ("erroneous method access flags");
1266     }
1267 }
1268
1269 void _Jv_ClassReader::handleCodeAttribute
1270   (int method_index, int max_stack, int max_locals, 
1271    int code_start, int code_length, int exc_table_length)
1272 {
1273   int size = _Jv_InterpMethod::size (exc_table_length, code_length);
1274   _Jv_InterpMethod *method = 
1275     (_Jv_InterpMethod*) (_Jv_AllocBytes (size));
1276
1277   method->deferred       = NULL;
1278   method->max_stack      = max_stack;
1279   method->max_locals     = max_locals;
1280   method->code_length    = code_length;
1281   method->exc_count      = exc_table_length;
1282   method->defining_class = def;
1283   method->self           = &def->methods[method_index];
1284   method->prepared       = NULL;
1285
1286   // grab the byte code!
1287   memcpy ((void*) method->bytecode (),
1288           (void*) (bytes+code_start),
1289           code_length);
1290
1291   def_interp->interpreted_methods[method_index] = method;
1292
1293   if ((method->self->accflags & java::lang::reflect::Modifier::STATIC))
1294     {
1295       // Precompute the ncode field for a static method.  This lets us
1296       // call a static method of an interpreted class from precompiled
1297       // code without first resolving the class (that will happen
1298       // during class initialization instead).
1299       method->self->ncode = method->ncode ();
1300     }
1301 }
1302
1303 void _Jv_ClassReader::handleExceptionTableEntry
1304   (int method_index, int exc_index, 
1305    int start_pc, int end_pc, int handler_pc, int catch_type)
1306 {
1307   _Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
1308     (def_interp->interpreted_methods[method_index]);
1309   _Jv_InterpException *exc = method->exceptions ();
1310
1311   exc[exc_index].start_pc.i     = start_pc;
1312   exc[exc_index].end_pc.i       = end_pc;
1313   exc[exc_index].handler_pc.i   = handler_pc;
1314   exc[exc_index].handler_type.i = catch_type;
1315 }
1316
1317 void _Jv_ClassReader::handleMethodsEnd ()
1318 {
1319   using namespace java::lang::reflect;
1320
1321   for (int i = 0; i < def->method_count; i++)
1322     {
1323       _Jv_Method *method = &def->methods[i];
1324       if ((method->accflags & Modifier::NATIVE) != 0)
1325         {
1326           if (def_interp->interpreted_methods[i] != 0)
1327             throw_class_format_error ("code provided for native method");
1328           else
1329             {
1330               _Jv_JNIMethod *m = (_Jv_JNIMethod *)
1331                 _Jv_AllocBytes (sizeof (_Jv_JNIMethod));
1332               m->defining_class = def;
1333               m->self = method;
1334               m->function = NULL;
1335               def_interp->interpreted_methods[i] = m;
1336               m->deferred = NULL;
1337
1338               if ((method->accflags & Modifier::STATIC))
1339                 {
1340                   // Precompute the ncode field for a static method.
1341                   // This lets us call a static method of an
1342                   // interpreted class from precompiled code without
1343                   // first resolving the class (that will happen
1344                   // during class initialization instead).
1345                   method->ncode = m->ncode ();
1346                 }
1347             }
1348         }
1349       else if ((method->accflags & Modifier::ABSTRACT) != 0)
1350         {
1351           if (def_interp->interpreted_methods[i] != 0)
1352             throw_class_format_error ("code provided for abstract method");
1353         }
1354       else
1355         {
1356           if (def_interp->interpreted_methods[i] == 0)
1357             throw_class_format_error ("method with no code");
1358         }
1359     }
1360 }
1361
1362 void _Jv_ClassReader::throw_class_format_error (char *msg)
1363 {
1364   jstring str;
1365   if (def->name != NULL)
1366     {
1367       jsize mlen = strlen (msg);
1368       unsigned char* data = (unsigned char*) def->name->data;
1369       int ulen = def->name->length;
1370       unsigned char* limit = data + ulen;
1371       jsize nlen = _Jv_strLengthUtf8 ((char *) data, ulen);
1372       jsize len = nlen + mlen + 3;
1373       str = JvAllocString(len);
1374       jchar *chrs = JvGetStringChars(str);
1375       while (data < limit)
1376         *chrs++ = UTF8_GET(data, limit);
1377       *chrs++ = ' ';
1378       *chrs++ = '(';
1379       for (;;)
1380         {
1381           char c = *msg++;
1382           if (c == 0)
1383             break;
1384           *chrs++ = c & 0xFFFF;
1385         }
1386       *chrs++ = ')';
1387     }
1388   else
1389     str = JvNewStringLatin1 (msg);
1390   ::throw_class_format_error (str);
1391 }
1392 \f
1393 /** Here we define the exceptions that can be thrown */
1394
1395 static void
1396 throw_no_class_def_found_error (jstring msg)
1397 {
1398   throw (msg
1399          ? new java::lang::NoClassDefFoundError (msg)
1400          : new java::lang::NoClassDefFoundError);
1401 }
1402
1403 static void
1404 throw_no_class_def_found_error (char *msg)
1405 {
1406   throw_no_class_def_found_error (JvNewStringLatin1 (msg));
1407 }
1408
1409 static void
1410 throw_class_format_error (jstring msg)
1411 {
1412   throw (msg
1413          ? new java::lang::ClassFormatError (msg)
1414          : new java::lang::ClassFormatError);
1415 }
1416
1417 static void
1418 throw_internal_error (char *msg)
1419 {
1420   throw new java::lang::InternalError (JvNewStringLatin1 (msg));
1421 }
1422
1423 static void
1424 throw_incompatible_class_change_error (jstring msg)
1425 {
1426   throw new java::lang::IncompatibleClassChangeError (msg);
1427 }
1428
1429 static void
1430 throw_class_circularity_error (jstring msg)
1431 {
1432   throw new java::lang::ClassCircularityError (msg);
1433 }
1434
1435 #endif /* INTERPRETER */
1436
1437 \f
1438
1439 /** This section takes care of verifying integrity of identifiers,
1440     signatures, field ddescriptors, and class names */
1441
1442 #define UTF8_PEEK(PTR, LIMIT) \
1443   ({ unsigned char* xxkeep = (PTR); \
1444      int xxch = UTF8_GET(PTR,LIMIT); \
1445      PTR = xxkeep; xxch; })
1446
1447 /* Verify one element of a type descriptor or signature.  */
1448 static unsigned char*
1449 _Jv_VerifyOne (unsigned char* ptr, unsigned char* limit, bool void_ok)
1450 {
1451   if (ptr >= limit)
1452     return 0;
1453
1454   int ch = UTF8_GET (ptr, limit);
1455
1456   switch (ch)
1457     {
1458     case 'V':
1459       if (! void_ok)
1460         return 0;
1461
1462     case 'S': case 'B': case 'I': case 'J':
1463     case 'Z': case 'C': case 'F': case 'D': 
1464       break;
1465
1466     case 'L':
1467       {
1468         unsigned char *start = ptr, *end;
1469         do
1470           {
1471             if (ptr > limit)
1472               return 0;
1473
1474             end = ptr;
1475
1476             if ((ch = UTF8_GET (ptr, limit)) == -1)
1477               return 0;
1478
1479           }
1480         while (ch != ';');
1481         if (! _Jv_VerifyClassName (start, (unsigned short) (end-start)))
1482           return 0;
1483       }
1484       break;
1485
1486     case '[':
1487       return _Jv_VerifyOne (ptr, limit, false);
1488       break;
1489
1490     default:
1491       return 0;
1492     }
1493
1494   return ptr;
1495 }
1496
1497 /* Verification and loading procedures.  */
1498 bool
1499 _Jv_VerifyFieldSignature (_Jv_Utf8Const*sig)
1500 {
1501   unsigned char* ptr = (unsigned char*) sig->data;
1502   unsigned char* limit = ptr + sig->length;
1503
1504   ptr = _Jv_VerifyOne (ptr, limit, false);
1505
1506   return ptr == limit;
1507 }
1508
1509 bool
1510 _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig)
1511 {
1512   unsigned char* ptr = (unsigned char*) sig->data;
1513   unsigned char* limit = ptr + sig->length;
1514
1515   if (ptr == limit || UTF8_GET(ptr,limit) != '(')
1516     return false;
1517
1518   while (ptr && UTF8_PEEK (ptr, limit) != ')')
1519     ptr = _Jv_VerifyOne (ptr, limit, false);
1520
1521   if (UTF8_GET (ptr, limit) != ')')
1522     return false;
1523
1524   // get the return type
1525   ptr = _Jv_VerifyOne (ptr, limit, true);
1526
1527   return ptr == limit;
1528 }
1529
1530 /* We try to avoid calling the Character methods all the time, in
1531    fact, they will only be called for non-standard things. */
1532 static __inline__ int 
1533 is_identifier_start (int c)
1534 {
1535   unsigned int ch = (unsigned)c;
1536
1537   if ((ch - 0x41U) < 29U)               /* A ... Z */
1538     return 1;
1539   if ((ch - 0x61U) < 29U)               /* a ... z */
1540     return 1;
1541   if (ch == 0x5FU)                      /* _ */
1542     return 1;
1543
1544   return java::lang::Character::isJavaIdentifierStart ((jchar) ch);
1545 }
1546
1547 static __inline__ int 
1548 is_identifier_part (int c)
1549 {
1550   unsigned int ch = (unsigned)c;
1551
1552   if ((ch - 0x41U) < 29U)               /* A ... Z */
1553     return 1;
1554   if ((ch - 0x61U) < 29U)               /* a ... z */
1555     return 1;
1556   if ((ch - 0x30) < 10U)                /* 0 .. 9 */
1557     return 1;
1558   if (ch == 0x5FU || ch == 0x24U)       /* _ $ */
1559     return 1;
1560
1561   return java::lang::Character::isJavaIdentifierStart ((jchar) ch);
1562 }
1563
1564 bool
1565 _Jv_VerifyIdentifier (_Jv_Utf8Const* name)
1566 {
1567   unsigned char *ptr   = (unsigned char*) name->data;
1568   unsigned char *limit = ptr + name->length;
1569   int ch;
1570
1571   if ((ch = UTF8_GET (ptr, limit))==-1
1572       || ! is_identifier_start (ch))
1573     return false;
1574
1575   while (ptr != limit)
1576     {
1577       if ((ch = UTF8_GET (ptr, limit))==-1
1578           || ! is_identifier_part (ch))
1579         return false;
1580     }
1581   return true;
1582 }
1583
1584 bool
1585 _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length)
1586 {
1587   unsigned char *limit = ptr+length;
1588   int ch;
1589
1590   if ('[' == UTF8_PEEK (ptr, limit))
1591     {
1592       unsigned char *end = _Jv_VerifyOne (++ptr, limit, false);
1593       // _Jv_VerifyOne must leave us looking at the terminating nul
1594       // byte.
1595       if (! end || *end)
1596         return false;
1597       else
1598         return true;
1599     }
1600
1601  next_level:
1602   for (;;) {
1603     if ((ch = UTF8_GET (ptr, limit))==-1)
1604       return false;
1605     if (! is_identifier_start (ch))
1606       return false;
1607     for (;;) {
1608       if (ptr == limit)
1609         return true;
1610       else if ((ch = UTF8_GET (ptr, limit))==-1)
1611         return false;
1612       else if (ch == '.')
1613         goto next_level;
1614       else if (! is_identifier_part (ch))
1615         return false;
1616     }
1617   }
1618 }
1619
1620 bool
1621 _Jv_VerifyClassName (_Jv_Utf8Const *name)
1622 {
1623   return _Jv_VerifyClassName ((unsigned char*)&name->data[0],
1624                               (_Jv_ushort) name->length);
1625 }
1626
1627 /* Returns true, if NAME1 and NAME2 represent classes in the same
1628    package.  */
1629 bool
1630 _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2)
1631 {
1632   unsigned char* ptr1 = (unsigned char*) name1->data;
1633   unsigned char* limit1 = ptr1 + name1->length;
1634
1635   unsigned char* last1 = ptr1;
1636
1637   // scan name1, and find the last occurrence of '.'
1638   while (ptr1 < limit1) {
1639     int ch1 = UTF8_GET (ptr1, limit1);
1640
1641     if (ch1 == '.')
1642       last1 = ptr1;
1643
1644     else if (ch1 == -1)
1645       return false;
1646   }
1647
1648   // Now the length of NAME1's package name is LEN.
1649   int len = last1 - (unsigned char*) name1->data;
1650
1651   // If this is longer than NAME2, then we're off.
1652   if (len > name2->length)
1653     return false;
1654
1655   // Then compare the first len bytes for equality.
1656   if (memcmp ((void*) name1->data, (void*) name2->data, len) == 0)
1657     {
1658       // Check that there are no .'s after position LEN in NAME2.
1659
1660       unsigned char* ptr2 = (unsigned char*) name2->data + len;
1661       unsigned char* limit2 =
1662         (unsigned char*) name2->data + name2->length;
1663
1664       while (ptr2 < limit2)
1665         {
1666           int ch2 = UTF8_GET (ptr2, limit2);
1667           if (ch2 == -1 || ch2 == '.')
1668             return false;
1669         }
1670       return true;
1671     }
1672   return false;
1673 }