source: vendor/gcc/3.2.2/libjava/defineclass.cc

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

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