source: trunk/third/gcc/libjava/defineclass.cc @ 18474

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