OSDN Git Service

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