OSDN Git Service

2004-08-03 David Daney <ddaney@avtrex.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 <java-cpool.h>
27 #include <gcj/cni.h>
28
29 #include <java/lang/Class.h>
30 #include <java/lang/Float.h>
31 #include <java/lang/Double.h>
32 #include <java/lang/Character.h>
33 #include <java/lang/LinkageError.h>
34 #include <java/lang/InternalError.h>
35 #include <java/lang/ClassFormatError.h>
36 #include <java/lang/NoClassDefFoundError.h>
37 #include <java/lang/ClassCircularityError.h>
38 #include <java/lang/IncompatibleClassChangeError.h>
39 #include <java/lang/reflect/Modifier.h>
40
41 using namespace gcj;
42
43 #ifdef INTERPRETER
44
45 // these go in some separate functions, to avoid having _Jv_InitClass
46 // inserted all over the place.
47 static void throw_internal_error (char *msg)
48         __attribute__ ((__noreturn__));
49 static void throw_no_class_def_found_error (jstring msg)
50         __attribute__ ((__noreturn__));
51 static void throw_no_class_def_found_error (char *msg)
52         __attribute__ ((__noreturn__));
53 static void throw_class_format_error (jstring msg)
54         __attribute__ ((__noreturn__));
55 static void throw_incompatible_class_change_error (jstring msg)
56         __attribute__ ((__noreturn__));
57 static void throw_class_circularity_error (jstring msg)
58         __attribute__ ((__noreturn__));
59
60 /**
61  * We define class reading using a class.  It is practical, since then
62  * the entire class-reader can be a friend of class Class (it needs to
63  * write all it's different structures); but also because this makes it
64  * easy to make class definition reentrant, and thus two threads can be
65  * defining classes at the same time.   This class (_Jv_ClassReader) is
66  * never exposed outside this file, so we don't have to worry about
67  * public or private members here.
68  */
69
70 struct _Jv_ClassReader {
71
72   // do verification?  Currently, there is no option to disable this.
73   // This flag just controls the verificaiton done by the class loader;
74   // i.e., checking the integrity of the constant pool; and it is
75   // allways on.  You always want this as far as I can see, but it also
76   // controls weither identifiers and type descriptors/signatures are
77   // verified as legal.  This could be somewhat more expensive since it
78   // will call Character.isJavaIdentifier{Start,Part} for each character
79   // in any identifier (field name or method name) it comes by.  Thus,
80   // it might be useful to turn off this verification for classes that
81   // come from a trusted source.  However, for GCJ, trusted classes are
82   // most likely to be linked in.
83
84   bool verify;
85
86   // input data.
87   unsigned char     *bytes;
88   int                len;
89
90   // current input position
91   int                pos;
92
93   // the constant pool data
94   int pool_count;
95   unsigned char     *tags;
96   unsigned int      *offsets;
97
98   // the class to define (see java-interp.h)
99   jclass           def;
100   
101   // the classes associated interpreter data.
102   _Jv_InterpClass  *def_interp;
103
104   /* check that the given number of input bytes are available */
105   inline void check (int num)
106   {
107     if (pos + num > len)
108       throw_class_format_error ("Premature end of data");
109   }
110
111   /* skip a given number of bytes in input */
112   inline void skip (int num)
113   {
114     check (num);
115     pos += num;
116   }
117   
118   /* read an unsignend 1-byte unit */
119   inline static jint get1u (unsigned char* bytes)
120   {
121     return bytes[0];
122   }
123   
124   /* read an unsigned 1-byte unit */
125   inline jint read1u ()
126   {
127     skip (1);
128     return get1u (bytes+pos-1);
129   }
130   
131   /* read an unsigned 2-byte unit */
132   inline static jint get2u (unsigned char *bytes)
133   {
134     return (((jint)bytes[0]) << 8) | ((jint)bytes[1]);
135   }
136   
137   /* read an unsigned 2-byte unit */
138   inline jint read2u ()
139   {
140     skip (2);  
141     return get2u (bytes+pos-2);
142   }
143   
144   /* read a 4-byte unit */
145   static jint get4 (unsigned char *bytes)
146   {
147     return (((jint)bytes[0]) << 24)
148          | (((jint)bytes[1]) << 16)
149          | (((jint)bytes[2]) << 8)
150          | (((jint)bytes[3]) << 0);
151   }
152
153   /* read a 4-byte unit, (we don't do that quite so often) */
154   inline jint read4 ()
155   {
156     skip (4);  
157     return get4 (bytes+pos-4);
158   }
159
160   /* read a 8-byte unit */
161   static jlong get8 (unsigned char* bytes)
162   {
163     return (((jlong)bytes[0]) << 56)
164          | (((jlong)bytes[1]) << 48)
165          | (((jlong)bytes[2]) << 40)
166          | (((jlong)bytes[3]) << 32) 
167          | (((jlong)bytes[4]) << 24)
168          | (((jlong)bytes[5]) << 16)
169          | (((jlong)bytes[6]) << 8)
170          | (((jlong)bytes[7]) << 0);
171   }
172
173   /* read a 8-byte unit */
174   inline jlong read8 ()
175   {
176     skip (8);  
177     return get8 (bytes+pos-8);
178   }
179
180   inline void check_tag (int index, char expected_tag)
181   {
182     if (index < 0
183         || index > pool_count
184         || tags[index] != expected_tag)
185       throw_class_format_error ("erroneous constant pool tag");
186   }
187
188   inline void verify_identifier (_Jv_Utf8Const* name)
189   {
190     if (! _Jv_VerifyIdentifier (name))
191       throw_class_format_error ("erroneous identifier");
192   }
193
194   inline void verify_classname (unsigned char* ptr, _Jv_ushort length)
195   {
196     if (! _Jv_VerifyClassName (ptr, length))
197       throw_class_format_error ("erroneous class name");
198   }
199
200   inline void verify_classname (_Jv_Utf8Const *name)
201   {
202     if (! _Jv_VerifyClassName (name))
203       throw_class_format_error ("erroneous class name");
204   }
205
206   inline void verify_field_signature (_Jv_Utf8Const *sig)
207   {
208     if (! _Jv_VerifyFieldSignature (sig))
209       throw_class_format_error ("erroneous type descriptor");
210   }
211
212   inline void verify_method_signature (_Jv_Utf8Const *sig)
213   {
214     if (! _Jv_VerifyMethodSignature (sig))
215       throw_class_format_error ("erroneous type descriptor");
216   }
217
218   _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length)
219   {
220     if (klass == 0 || length < 0 || offset+length > data->length)
221       throw_internal_error ("arguments to _Jv_DefineClass");
222
223     verify = true;
224     bytes  = (unsigned char*) (elements (data)+offset);
225     len    = length;
226     pos    = 0;
227     def    = klass;
228     def_interp = (_Jv_InterpClass *) def->aux_info;
229   }
230
231   /** and here goes the parser members defined out-of-line */
232   void parse ();
233   void read_constpool ();
234   void prepare_pool_entry (int index, unsigned char tag);
235   void read_fields ();
236   void read_methods ();
237   void read_one_class_attribute ();
238   void read_one_method_attribute (int method);
239   void read_one_code_attribute (int method);
240   void read_one_field_attribute (int field);
241   void throw_class_format_error (char *msg);
242
243   /** check an utf8 entry, without creating a Utf8Const object */
244   bool is_attribute_name (int index, char *name);
245
246   /** here goes the class-loader members defined out-of-line */
247   void handleConstantPool ();
248   void handleClassBegin (int, int, int);
249   void handleInterfacesBegin (int);
250   void handleInterface (int, int);
251   void handleFieldsBegin (int);
252   void handleField (int, int, int, int);
253   void handleFieldsEnd ();
254   void handleConstantValueAttribute (int,int);
255   void handleMethodsBegin (int);
256   void handleMethod (int, int, int, int);
257   void handleMethodsEnd ();
258   void handleCodeAttribute (int, int, int, int, int, int);
259   void handleExceptionTableEntry (int, int, int, int, int, int);
260
261   void checkExtends (jclass sub, jclass super);
262   void checkImplements (jclass sub, jclass super);
263
264   /*
265    * FIXME: we should keep a hash table of utf8-strings, since many will
266    * be the same.  It's a little tricky, however, because the hash table
267    * needs to interact gracefully with the garbage collector.  Much
268    * memory is to be saved by this, however!  perhaps the improvement
269    * could be implemented in prims.cc (_Jv_makeUtf8Const), since it
270    * computes the hash value anyway.
271    */
272 };
273
274 void
275 _Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length)
276 {
277   _Jv_ClassReader reader (klass, data, offset, length);
278   reader.parse();
279
280   /* that's it! */
281 }
282
283 \f
284 /** This section defines the parsing/scanning of the class data */
285
286 void
287 _Jv_ClassReader::parse ()
288 {
289   int magic = read4 ();
290
291   /* FIXME: Decide which range of version numbers to allow */
292
293   /* int minor_version = */ read2u ();
294   /* int major_verson  = */ read2u ();
295
296   if (magic != (int) 0xCAFEBABE)
297     throw_class_format_error ("bad magic number");
298
299   pool_count = read2u ();
300
301   read_constpool ();
302
303   int access_flags = read2u ();
304   int this_class = read2u ();
305   int super_class = read2u ();
306
307   check_tag (this_class, JV_CONSTANT_Class);
308   if (super_class != 0) 
309     check_tag (super_class, JV_CONSTANT_Class);
310
311   handleClassBegin (access_flags, this_class, super_class);
312
313   int interfaces_count = read2u (); 
314         
315   handleInterfacesBegin (interfaces_count);
316
317   for (int i = 0; i < interfaces_count; i++)
318     {
319       int iface = read2u ();
320       check_tag (iface, JV_CONSTANT_Class);
321       handleInterface (i, iface);
322     }
323   
324   read_fields ();
325   read_methods ();
326   
327   int attributes_count = read2u ();
328   
329   for (int i = 0; i < attributes_count; i++)
330     {
331       read_one_class_attribute ();
332     }
333
334   if (pos != len)
335     throw_class_format_error ("unused data before end of file");
336
337   // tell everyone we're done.
338   def->state = JV_STATE_LOADED;
339   if (gcj::verbose_class_flag)
340     fprintf (stderr, "[Loaded (bytecode) %s]\n", def->name->chars());
341   def->notifyAll ();
342
343 }
344
345 void _Jv_ClassReader::read_constpool ()
346 {
347   tags    = (unsigned char*) _Jv_AllocBytes (pool_count);
348   offsets = (unsigned int *) _Jv_AllocBytes (sizeof (int)
349                                                     * pool_count) ;
350
351   /** first, we scan the constant pool, collecting tags and offsets */
352   tags[0]   = JV_CONSTANT_Undefined;
353   offsets[0] = pos;
354   for (int c = 1; c < pool_count; c++)
355     {
356       tags[c]    = read1u ();
357       offsets[c] = pos;
358
359       switch (tags[c])
360         {
361         case JV_CONSTANT_String:
362         case JV_CONSTANT_Class:
363           skip (2);
364           break;
365
366         case JV_CONSTANT_Fieldref:
367         case JV_CONSTANT_Methodref:
368         case JV_CONSTANT_InterfaceMethodref:
369         case JV_CONSTANT_NameAndType:
370         case JV_CONSTANT_Integer:
371         case JV_CONSTANT_Float:
372           skip (4);
373           break;
374
375         case JV_CONSTANT_Double:
376         case JV_CONSTANT_Long:
377           skip (8);
378           tags[++c] = JV_CONSTANT_Undefined;
379           break;
380             
381         case JV_CONSTANT_Utf8:
382           {                 
383             int len = read2u ();
384             skip (len);
385           }
386           break;
387
388         case JV_CONSTANT_Unicode:
389           throw_class_format_error ("unicode not supported");
390           break;
391
392         default:
393           throw_class_format_error ("erroneous constant pool tag");
394         }
395     }
396
397   handleConstantPool ();
398 }
399
400
401 void _Jv_ClassReader::read_fields ()
402 {
403   int fields_count = read2u ();
404   handleFieldsBegin (fields_count);
405
406   for (int i = 0; i < fields_count; i++)
407     {
408       int access_flags     = read2u ();
409       int name_index       = read2u ();
410       int descriptor_index = read2u ();
411       int attributes_count = read2u ();
412
413       check_tag (name_index, JV_CONSTANT_Utf8);
414       prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
415
416       check_tag (descriptor_index, JV_CONSTANT_Utf8);
417       prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
418
419       handleField (i, access_flags, name_index, descriptor_index);
420
421       for (int j = 0; j < attributes_count; j++)
422         {
423           read_one_field_attribute (i);
424         }
425     }
426
427   handleFieldsEnd ();
428 }
429
430 bool
431 _Jv_ClassReader::is_attribute_name (int index, char *name)
432 {
433   check_tag (index, JV_CONSTANT_Utf8);
434   int len = get2u (bytes+offsets[index]);
435   if (len != (int) strlen (name))
436     return false;
437   else
438     return !memcmp (bytes+offsets[index]+2, name, len);
439 }
440
441 void _Jv_ClassReader::read_one_field_attribute (int field_index)
442 {
443   int name = read2u ();
444   int length = read4 ();
445
446   if (is_attribute_name (name, "ConstantValue"))
447     {
448       int cv = read2u ();
449
450       if (cv < pool_count 
451           && cv > 0
452           && (tags[cv] == JV_CONSTANT_Integer
453               || tags[cv] == JV_CONSTANT_Float
454               || tags[cv] == JV_CONSTANT_Long
455               || tags[cv] == JV_CONSTANT_Double
456               || tags[cv] == JV_CONSTANT_String))
457           {
458             handleConstantValueAttribute (field_index, cv);
459           }
460         else
461           {
462             throw_class_format_error ("erroneous ConstantValue attribute");
463           }
464
465         if (length != 2) 
466           throw_class_format_error ("erroneous ConstantValue attribute");
467       }
468
469     else
470       {
471         skip (length);
472       }
473 }
474
475 void _Jv_ClassReader::read_methods ()
476 {
477   int methods_count = read2u ();
478   
479   handleMethodsBegin (methods_count);
480   
481   for (int i = 0; i < methods_count; i++)
482     {
483       int access_flags     = read2u ();
484       int name_index       = read2u ();
485       int descriptor_index = read2u ();
486       int attributes_count = read2u ();
487       
488       check_tag (name_index, JV_CONSTANT_Utf8);
489       prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
490
491       check_tag (name_index, JV_CONSTANT_Utf8);
492       prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
493
494       handleMethod (i, access_flags, name_index,
495                     descriptor_index);
496
497       for (int j = 0; j < attributes_count; j++)
498         {
499           read_one_method_attribute (i);
500         }
501     }
502   
503   handleMethodsEnd ();
504 }
505
506 void _Jv_ClassReader::read_one_method_attribute (int method_index) 
507 {
508   int name = read2u ();
509   int length = read4 ();
510
511   if (is_attribute_name (name, "Exceptions"))
512     {
513       _Jv_Method *method = reinterpret_cast<_Jv_Method *>
514         (&def->methods[method_index]);
515       if (method->throws != NULL)
516         throw_class_format_error ("only one Exceptions attribute allowed per method");
517
518       int num_exceptions = read2u ();
519       // We use malloc here because the GC won't scan the method
520       // objects.  FIXME this means a memory leak if we GC a class.
521       // (Currently we never do.)
522       _Jv_Utf8Const **exceptions =
523         (_Jv_Utf8Const **) _Jv_Malloc ((num_exceptions + 1) * sizeof (_Jv_Utf8Const *));
524
525       int out = 0;
526       _Jv_word *pool_data = def->constants.data;
527       for (int i = 0; i < num_exceptions; ++i)
528         {
529           try
530             {
531               int ndx = read2u ();
532               // JLS 2nd Ed. 4.7.5 requires that the tag not be 0.
533               if (ndx != 0)
534                 {
535                   check_tag (ndx, JV_CONSTANT_Class);
536                   exceptions[out++] = pool_data[ndx].utf8; 
537                 }
538             }
539           catch (java::lang::Throwable *exc)
540             {
541               _Jv_Free (exceptions);
542               throw exc;
543             }
544         }
545       exceptions[out] = NULL;
546       method->throws = exceptions;
547     }
548
549   else if (is_attribute_name (name, "Code"))
550     {
551       int start_off = pos;
552       int max_stack = read2u ();
553       int max_locals = read2u ();
554       int code_length = read4 ();
555
556       int code_start = pos;
557       skip (code_length);
558       int exception_table_length = read2u ();
559
560       handleCodeAttribute (method_index, 
561                            max_stack, max_locals,
562                            code_start, code_length,
563                            exception_table_length);
564       
565
566       for (int i = 0; i < exception_table_length; i++)
567         {
568           int start_pc   = read2u ();
569           int end_pc     = read2u ();
570           int handler_pc = read2u ();
571           int catch_type = read2u ();
572
573           if (start_pc > end_pc
574               || start_pc < 0
575               // END_PC can be equal to CODE_LENGTH.
576               // See JVM Spec 4.7.4.
577               || end_pc > code_length
578               || handler_pc >= code_length)
579             throw_class_format_error ("erroneous exception handler info");
580
581           if (! (tags[catch_type] == JV_CONSTANT_Class
582                  || tags[catch_type] == 0))
583             {
584               throw_class_format_error ("erroneous exception handler info");
585             }
586
587           handleExceptionTableEntry (method_index,
588                                      i,
589                                      start_pc,
590                                      end_pc,
591                                      handler_pc, 
592                                      catch_type);
593
594         }
595
596       int attributes_count = read2u ();
597
598       for (int i = 0; i < attributes_count; i++)
599         {
600           read_one_code_attribute (method_index);
601         }
602
603       if ((pos - start_off) != length)
604         throw_class_format_error ("code attribute too short");
605     }
606
607   else
608     {
609       /* ignore unknown attributes */
610       skip (length);
611     }
612 }
613
614 void _Jv_ClassReader::read_one_code_attribute (int /*method*/) 
615 {
616   /* ignore for now, ... later we may want to pick up
617      line number information, for debugging purposes;
618      in fact, the whole debugger issue is open!  */
619
620   /* int name = */ read2u ();
621   int length = read4 ();
622   skip (length);
623
624 }
625
626 void _Jv_ClassReader::read_one_class_attribute () 
627 {
628   /* we also ignore the class attributes, ...
629      some day we'll add inner-classes support. */
630
631   /* int name = */ read2u ();
632   int length = read4 ();
633   skip (length);
634 }
635
636
637
638 \f
639 /* this section defines the semantic actions of the parser */
640
641 void _Jv_ClassReader::handleConstantPool ()
642 {
643   /** now, we actually define the class' constant pool */
644
645   // the pool is scanned explicitly by the collector
646   jbyte *pool_tags = (jbyte*) _Jv_AllocBytes (pool_count);
647   _Jv_word *pool_data
648     = (_Jv_word*) _Jv_AllocBytes (pool_count * sizeof (_Jv_word));
649   
650   def->constants.tags = pool_tags;
651   def->constants.data = pool_data;
652   def->constants.size = pool_count;
653
654   // Here we make a pass to collect the strings!   We do this, because
655   // internally in the GCJ runtime, classes are encoded with .'s not /'s. 
656   // Therefore, we first collect the strings, and then translate the rest
657   // of the utf8-entries (thus not representing strings) from /-notation
658   // to .-notation.
659   for (int i = 1; i < pool_count; i++)
660     {
661       if (tags[i] == JV_CONSTANT_String)
662         {
663           unsigned char* str_data = bytes + offsets [i];
664           int utf_index = get2u (str_data);
665           check_tag (utf_index, JV_CONSTANT_Utf8);
666           unsigned char *utf_data = bytes + offsets[utf_index];
667           int len = get2u (utf_data);
668           pool_data[i].utf8 = _Jv_makeUtf8Const ((char*)(utf_data+2), len);
669           pool_tags[i] = JV_CONSTANT_String;
670         }
671       else
672         {
673           pool_tags[i] = JV_CONSTANT_Undefined;
674         }
675     }
676
677   // and now, we scan everything else but strings & utf8-entries.  This
678   // leaves out those utf8-entries which are not used; which will be left
679   // with a tag of JV_CONSTANT_Undefined in the class definition.
680   for (int index = 1; index < pool_count; index++)
681     {
682       switch (tags[index])
683         {
684         case JV_CONSTANT_Undefined:
685         case JV_CONSTANT_String:
686         case JV_CONSTANT_Utf8:
687           continue;
688           
689         default:
690           prepare_pool_entry (index, tags[index]);
691         }
692     }  
693   
694 }
695
696 /* this is a recursive procedure, which will prepare pool entries as needed.
697    Which is how we avoid initializing those entries which go unused. */
698 void
699 _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
700 {
701   /* these two, pool_data and pool_tags, point into the class
702      structure we are currently defining */
703
704   unsigned char *pool_tags = (unsigned char*) def->constants.tags;
705   _Jv_word      *pool_data = def->constants.data;
706
707   /* this entry was already prepared */
708   if (pool_tags[index] == this_tag)
709     return;
710
711   /* this_data points to the constant-pool information for the current
712      constant-pool entry */
713
714   unsigned char *this_data = bytes + offsets[index];
715
716   switch (this_tag)
717     {
718     case JV_CONSTANT_Utf8: 
719       {
720         // If we came here, it is because some other tag needs this
721         // utf8-entry for type information!  Thus, we translate /'s to .'s in
722         // order to accomondate gcj's internal representation.
723
724         int len = get2u (this_data);
725         char *buffer = (char*) __builtin_alloca (len);
726         char *s = ((char*) this_data)+2;
727
728         /* FIXME: avoid using a buffer here */
729         for (int i = 0; i < len; i++)
730           {
731             if (s[i] == '/')
732               buffer[i] = '.';
733             else
734               buffer[i] = (char) s[i];
735           }
736         
737         pool_data[index].utf8 = _Jv_makeUtf8Const (buffer, len);
738         pool_tags[index] = JV_CONSTANT_Utf8;
739       }
740       break;
741             
742     case JV_CONSTANT_Class:      
743       {
744         int utf_index = get2u (this_data);
745         check_tag (utf_index, JV_CONSTANT_Utf8);
746         prepare_pool_entry (utf_index, JV_CONSTANT_Utf8);
747
748         if (verify)
749           verify_classname (pool_data[utf_index].utf8);
750                 
751         pool_data[index].utf8 = pool_data[utf_index].utf8;
752         pool_tags[index] = JV_CONSTANT_Class;
753       }
754       break;
755             
756     case JV_CONSTANT_String:
757       // already handled before... 
758       break;
759             
760     case JV_CONSTANT_Fieldref:
761     case JV_CONSTANT_Methodref:
762     case JV_CONSTANT_InterfaceMethodref:
763       {
764         int class_index = get2u (this_data);
765         int nat_index = get2u (this_data+2);
766
767         check_tag (class_index, JV_CONSTANT_Class);
768         prepare_pool_entry (class_index, JV_CONSTANT_Class);        
769
770         check_tag (nat_index, JV_CONSTANT_NameAndType);
771         prepare_pool_entry (nat_index, JV_CONSTANT_NameAndType);
772
773         // here, verify the signature and identifier name
774         if (verify)
775         {
776           _Jv_ushort name_index, type_index;
777           _Jv_loadIndexes (&pool_data[nat_index],
778                            name_index, type_index);
779
780           if (this_tag == JV_CONSTANT_Fieldref)
781             verify_field_signature (pool_data[type_index].utf8);
782           else
783             verify_method_signature (pool_data[type_index].utf8);
784
785           _Jv_Utf8Const* name = pool_data[name_index].utf8;
786
787           if (this_tag != JV_CONSTANT_Fieldref
788               && (   _Jv_equalUtf8Consts (name, clinit_name)
789                   || _Jv_equalUtf8Consts (name, init_name)))
790             /* ignore */;
791           else
792             verify_identifier (pool_data[name_index].utf8);
793         }
794             
795         _Jv_storeIndexes (&pool_data[index], class_index, nat_index);
796         pool_tags[index] = this_tag;
797       }
798       break;
799             
800     case JV_CONSTANT_NameAndType:
801       {
802         _Jv_ushort name_index = get2u (this_data);
803         _Jv_ushort type_index = get2u (this_data+2);
804
805         check_tag (name_index, JV_CONSTANT_Utf8);
806         prepare_pool_entry (name_index, JV_CONSTANT_Utf8);          
807
808         check_tag (type_index, JV_CONSTANT_Utf8);
809         prepare_pool_entry (type_index, JV_CONSTANT_Utf8);
810
811         _Jv_storeIndexes (&pool_data[index], name_index, type_index);
812         pool_tags[index] = JV_CONSTANT_NameAndType;
813       }
814       break;
815             
816     case JV_CONSTANT_Float:
817       {
818         jfloat f = java::lang::Float::intBitsToFloat ((jint) get4 (this_data));
819         _Jv_storeFloat (&pool_data[index], f);
820         pool_tags[index] = JV_CONSTANT_Float;
821       }
822       break;
823             
824     case JV_CONSTANT_Integer:
825       {
826         int i = get4 (this_data);
827         _Jv_storeInt (&pool_data[index], i);
828         pool_tags[index] = JV_CONSTANT_Integer;
829       }
830       break;
831             
832     case JV_CONSTANT_Double:
833       {
834         jdouble d
835           = java::lang::Double::longBitsToDouble ((jlong) get8 (this_data));
836         _Jv_storeDouble (&pool_data[index], d);
837         pool_tags[index] = JV_CONSTANT_Double;
838       }
839       break;
840             
841     case JV_CONSTANT_Long:
842       {
843         jlong i = get8 (this_data);
844         _Jv_storeLong (&pool_data[index], i);
845         pool_tags[index] = JV_CONSTANT_Long;
846       }
847       break;
848             
849     default:
850       throw_class_format_error ("erroneous constant pool tag");
851     }
852 }
853
854
855 void
856 _Jv_ClassReader::handleClassBegin
857   (int access_flags, int this_class, int super_class)
858 {
859   using namespace java::lang::reflect;
860
861   unsigned char *pool_tags = (unsigned char*) def->constants.tags;
862   _Jv_word      *pool_data = def->constants.data;
863
864   check_tag (this_class, JV_CONSTANT_Class);
865   _Jv_Utf8Const *loadedName = pool_data[this_class].utf8;
866
867   // was ClassLoader.defineClass called with an expected class name?
868   if (def->name == 0)
869     {
870       jclass orig = _Jv_FindClassInCache (loadedName, def->loader);
871
872       if (orig == 0)
873         {
874           def->name = loadedName;
875         }
876       else
877         {
878           jstring msg = JvNewStringUTF ("anonymous "
879                                         "class data denotes "
880                                         "existing class ");
881           msg = msg->concat (orig->getName ());
882
883           throw_no_class_def_found_error (msg);
884         }
885     }
886
887   // assert that the loaded class has the expected name, 5.3.5
888   else if (! _Jv_equalUtf8Consts (loadedName, def->name))
889     {
890       jstring msg = JvNewStringUTF ("loaded class ");
891       msg = msg->concat (def->getName ());
892       msg = msg->concat (_Jv_NewStringUTF (" was in fact named "));
893       jstring klass_name = loadedName->toString();
894       msg = msg->concat (klass_name);
895
896       throw_no_class_def_found_error (msg);
897     }
898
899   def->accflags = access_flags | java::lang::reflect::Modifier::INTERPRETED;
900   pool_data[this_class].clazz = def;
901   pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
902
903   if (super_class == 0 && ! (access_flags & Modifier::INTERFACE))
904     {
905       // FIXME: Consider this carefully!  
906       if (! _Jv_equalUtf8Consts (def->name, java::lang::Object::class$.name))
907         throw_no_class_def_found_error ("loading java.lang.Object");
908     }
909
910   // In the pre-loading state, it can be looked up in the
911   // cache only by this thread!  This allows the super-class
912   // to include references to this class.
913
914   def->state = JV_STATE_PRELOADING;
915
916   {
917     JvSynchronize sync (&java::lang::Class::class$);
918     _Jv_RegisterClass (def);
919   }
920
921   if (super_class != 0)
922     {
923       // Load the superclass.
924       check_tag (super_class, JV_CONSTANT_Class);
925       _Jv_Utf8Const* super_name = pool_data[super_class].utf8; 
926
927       // Load the superclass using our defining loader.
928       jclass the_super = _Jv_FindClass (super_name,
929                                         def->loader);
930
931       // This will establish that we are allowed to be a subclass,
932       // and check for class circularity error.
933       checkExtends (def, the_super);
934
935       // Note: for an interface we will find Object as the
936       // superclass.  We still check it above to ensure class file
937       // validity, but we simply assign `null' to the actual field in
938       // this case.
939       def->superclass = (((access_flags & Modifier::INTERFACE))
940                          ? NULL : the_super);
941       pool_data[super_class].clazz = the_super;
942       pool_tags[super_class] = JV_CONSTANT_ResolvedClass;
943     }
944
945   // Now we've come past the circularity problem, we can 
946   // now say that we're loading.
947
948   def->state = JV_STATE_LOADING;
949   def->notifyAll ();
950 }
951
952 ///// implements the checks described in sect. 5.3.5.3
953 void
954 _Jv_ClassReader::checkExtends (jclass sub, jclass super)
955 {
956   using namespace java::lang::reflect;
957
958   // having an interface or a final class as a superclass is no good
959   if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
960     {
961       throw_incompatible_class_change_error (sub->getName ());
962     }
963
964   // if the super class is not public, we need to check some more
965   if ((super->accflags & Modifier::PUBLIC) == 0)
966     {
967       // With package scope, the classes must have the same
968       // class loader.
969       if (   sub->loader != super->loader
970           || !_Jv_ClassNameSamePackage (sub->name, super->name))
971         {
972           throw_incompatible_class_change_error (sub->getName ());
973         }
974     } 
975
976   for (; super != 0; super = super->superclass)
977     {
978       if (super == sub)
979         throw_class_circularity_error (sub->getName ());
980     }
981 }
982
983
984
985 void _Jv_ClassReader::handleInterfacesBegin (int count)
986 {
987   def->interfaces = (jclass*) _Jv_AllocBytes (count*sizeof (jclass));
988   def->interface_count = count;
989 }
990
991 void _Jv_ClassReader::handleInterface (int if_number, int offset)
992 {
993   _Jv_word       * pool_data = def->constants.data;
994   unsigned char  * pool_tags = (unsigned char*) def->constants.tags;
995
996   jclass the_interface;
997
998   if (pool_tags[offset] == JV_CONSTANT_Class)
999     {
1000       _Jv_Utf8Const* name = pool_data[offset].utf8;
1001       the_interface =  _Jv_FindClass (name, def->loader);
1002     }
1003   else if (pool_tags[offset] == JV_CONSTANT_ResolvedClass)
1004     {
1005       the_interface = pool_data[offset].clazz;
1006     }
1007   else
1008     {
1009       throw_no_class_def_found_error ("erroneous constant pool tag");
1010     }
1011
1012   // checks the validity of the_interface, and that we are in fact
1013   // allowed to implement that interface.
1014   checkImplements (def, the_interface);
1015   
1016   pool_data[offset].clazz = the_interface;
1017   pool_tags[offset] = JV_CONSTANT_ResolvedClass;
1018   
1019   def->interfaces[if_number] = the_interface;
1020 }
1021
1022 void
1023 _Jv_ClassReader::checkImplements (jclass sub, jclass super)
1024 {
1025   using namespace java::lang::reflect;
1026
1027   // well, it *must* be an interface
1028   if ((super->accflags & Modifier::INTERFACE) == 0)
1029     {
1030       throw_incompatible_class_change_error (sub->getName ());
1031     }
1032
1033   // if it has package scope, it must also be defined by the 
1034   // same loader.
1035   if ((super->accflags & Modifier::PUBLIC) == 0)
1036     {
1037       if (    sub->loader != super->loader
1038           || !_Jv_ClassNameSamePackage (sub->name, super->name))
1039         {
1040           throw_incompatible_class_change_error (sub->getName ());
1041         }
1042     } 
1043
1044   // FIXME: add interface circularity check here
1045   if (sub == super)
1046     {
1047       throw_class_circularity_error (sub->getName ());
1048     }           
1049 }
1050
1051 void _Jv_ClassReader::handleFieldsBegin (int count)
1052 {
1053   def->fields = (_Jv_Field*) 
1054     _Jv_AllocBytes (count * sizeof (_Jv_Field));
1055   def->field_count = count;
1056   def_interp->field_initializers = (_Jv_ushort*)
1057     _Jv_AllocBytes (count * sizeof (_Jv_ushort));
1058   for (int i = 0; i < count; i++)
1059     def_interp->field_initializers[i] = (_Jv_ushort) 0;
1060 }
1061
1062 void _Jv_ClassReader::handleField (int field_no,
1063                                    int flags,
1064                                    int name,
1065                                    int desc)
1066 {
1067   using namespace java::lang::reflect;
1068
1069   _Jv_word *pool_data = def->constants.data;
1070
1071   _Jv_Field *field = &def->fields[field_no];
1072   _Jv_Utf8Const *field_name = pool_data[name].utf8;
1073
1074 #ifndef COMPACT_FIELDS
1075   field->name      = field_name;
1076 #else
1077   field->nameIndex = name;
1078 #endif
1079
1080   // Ignore flags we don't know about.  
1081   field->flags = flags & Modifier::ALL_FLAGS;
1082
1083   _Jv_Utf8Const* sig = pool_data[desc].utf8;
1084
1085   if (verify)
1086     {
1087       verify_identifier (field_name);
1088
1089       for (int i = 0; i < field_no; ++i)
1090         {
1091           if (_Jv_equalUtf8Consts (field_name, def->fields[i].name)
1092               && _Jv_equalUtf8Consts (sig,
1093                                       // We know the other fields are
1094                                       // unresolved.
1095                                       (_Jv_Utf8Const *) def->fields[i].type))
1096             throw_class_format_error ("duplicate field name");
1097         }
1098
1099       if (field->flags & (Modifier::SYNCHRONIZED
1100                           | Modifier::NATIVE
1101                           | Modifier::INTERFACE
1102                           | Modifier::ABSTRACT))
1103         throw_class_format_error ("erroneous field access flags");
1104       
1105       if (1 < ( ((field->flags & Modifier::PUBLIC) ? 1 : 0)
1106                 +((field->flags & Modifier::PRIVATE) ? 1 : 0)
1107                 +((field->flags & Modifier::PROTECTED) ? 1 : 0)))
1108         throw_class_format_error ("erroneous field access flags");
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       if (method->accflags & (Modifier::VOLATILE
1260                               | Modifier::TRANSIENT
1261                               | Modifier::INTERFACE))
1262         throw_class_format_error ("erroneous method access flags");
1263       
1264       if (1 < ( ((method->accflags & Modifier::PUBLIC) ? 1 : 0)
1265                 +((method->accflags & Modifier::PRIVATE) ? 1 : 0)
1266                 +((method->accflags & Modifier::PROTECTED) ? 1 : 0)))
1267         throw_class_format_error ("erroneous method access flags");
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 }