OSDN Git Service

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