OSDN Git Service

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