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

Last change on this file was 1391, checked in by bird, 21 years ago

GCC v3.3.3 sources.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 41.2 KB
Line 
1// defineclass.cc - defining a class from .class format.
2
3/* Copyright (C) 1999, 2000, 2001, 2002 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/IncompatibleClassChangeError.h>
39#include <java/lang/reflect/Modifier.h>
40
41using namespace gcj;
42
43#ifdef INTERPRETER
44
45// these go in some separate functions, to avoid having _Jv_InitClass
46// inserted all over the place.
47static void throw_internal_error (char *msg)
48 __attribute__ ((__noreturn__));
49static void throw_no_class_def_found_error (jstring msg)
50 __attribute__ ((__noreturn__));
51static void throw_no_class_def_found_error (char *msg)
52 __attribute__ ((__noreturn__));
53static void throw_class_format_error (jstring msg)
54 __attribute__ ((__noreturn__));
55static void throw_incompatible_class_change_error (jstring msg)
56 __attribute__ ((__noreturn__));
57static void throw_class_circularity_error (jstring msg)
58 __attribute__ ((__noreturn__));
59
60/**
61 * We define class reading using a class. It is practical, since then
62 * the entire class-reader can be a friend of class Class (it needs to
63 * write all it's different structures); but also because this makes it
64 * easy to make class definition reentrant, and thus two threads can be
65 * defining classes at the same time. This class (_Jv_ClassReader) is
66 * never exposed outside this file, so we don't have to worry about
67 * public or private members here.
68 */
69
70struct _Jv_ClassReader {
71
72 // do verification? Currently, there is no option to disable this.
73 // This flag just controls the verificaiton done by the class loader;
74 // i.e., checking the integrity of the constant pool; and it is
75 // allways on. You always want this as far as I can see, but it also
76 // controls weither identifiers and type descriptors/signatures are
77 // verified as legal. This could be somewhat more expensive since it
78 // will call Characher.isJavaIdentifier{Start,Part} for each character
79 // in any identifier (field name or method name) it comes by. Thus,
80 // it might be useful to turn off this verification for classes that
81 // come from a trusted source. However, for GCJ, trusted classes are
82 // most likely to be linked in.
83
84 bool verify;
85
86 // input data.
87 unsigned char *bytes;
88 int len;
89
90 // current input position
91 int pos;
92
93 // the constant pool data
94 int pool_count;
95 unsigned char *tags;
96 unsigned int *offsets;
97
98 // the class to define (see java-interp.h)
99 _Jv_InterpClass *def;
100
101 /* check that the given number of input bytes are available */
102 inline void check (int num)
103 {
104 if (pos + num > len)
105 throw_class_format_error ("Premature end of data");
106 }
107
108 /* skip a given number of bytes in input */
109 inline void skip (int num)
110 {
111 check (num);
112 pos += num;
113 }
114
115 /* read an unsignend 1-byte unit */
116 inline static jint get1u (unsigned char* bytes)
117 {
118 return bytes[0];
119 }
120
121 /* read an unsigned 1-byte unit */
122 inline jint read1u ()
123 {
124 skip (1);
125 return get1u (bytes+pos-1);
126 }
127
128 /* read an unsigned 2-byte unit */
129 inline static jint get2u (unsigned char *bytes)
130 {
131 return (((jint)bytes[0]) << 8) | ((jint)bytes[1]);
132 }
133
134 /* read an unsigned 2-byte unit */
135 inline jint read2u ()
136 {
137 skip (2);
138 return get2u (bytes+pos-2);
139 }
140
141 /* read a 4-byte unit */
142 static jint get4 (unsigned char *bytes)
143 {
144 return (((jint)bytes[0]) << 24)
145 | (((jint)bytes[1]) << 16)
146 | (((jint)bytes[2]) << 8)
147 | (((jint)bytes[3]) << 0);
148 }
149
150 /* read a 4-byte unit, (we don't do that quite so often) */
151 inline jint read4 ()
152 {
153 skip (4);
154 return get4 (bytes+pos-4);
155 }
156
157 /* read a 8-byte unit */
158 static jlong get8 (unsigned char* bytes)
159 {
160 return (((jlong)bytes[0]) << 56)
161 | (((jlong)bytes[1]) << 48)
162 | (((jlong)bytes[2]) << 40)
163 | (((jlong)bytes[3]) << 32)
164 | (((jlong)bytes[4]) << 24)
165 | (((jlong)bytes[5]) << 16)
166 | (((jlong)bytes[6]) << 8)
167 | (((jlong)bytes[7]) << 0);
168 }
169
170 /* read a 8-byte unit */
171 inline jlong read8 ()
172 {
173 skip (8);
174 return get8 (bytes+pos-8);
175 }
176
177 inline void check_tag (int index, char expected_tag)
178 {
179 if (index < 0
180 || index > pool_count
181 || tags[index] != expected_tag)
182 throw_class_format_error ("erroneous constant pool tag");
183 }
184
185 inline void verify_identifier (_Jv_Utf8Const* name)
186 {
187 if (! _Jv_VerifyIdentifier (name))
188 throw_class_format_error ("erroneous identifier");
189 }
190
191 inline void verify_classname (unsigned char* ptr, _Jv_ushort length)
192 {
193 if (! _Jv_VerifyClassName (ptr, length))
194 throw_class_format_error ("erroneous class name");
195 }
196
197 inline void verify_classname (_Jv_Utf8Const *name)
198 {
199 if (! _Jv_VerifyClassName (name))
200 throw_class_format_error ("erroneous class name");
201 }
202
203 inline void verify_field_signature (_Jv_Utf8Const *sig)
204 {
205 if (! _Jv_VerifyFieldSignature (sig))
206 throw_class_format_error ("erroneous type descriptor");
207 }
208
209 inline void verify_method_signature (_Jv_Utf8Const *sig)
210 {
211 if (! _Jv_VerifyMethodSignature (sig))
212 throw_class_format_error ("erroneous type descriptor");
213 }
214
215 _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length)
216 {
217 if (klass == 0 || length < 0 || offset+length > data->length)
218 throw_internal_error ("arguments to _Jv_DefineClass");
219
220 verify = true;
221 bytes = (unsigned char*) (elements (data)+offset);
222 len = length;
223 pos = 0;
224 def = (_Jv_InterpClass*) klass;
225 }
226
227 /** and here goes the parser members defined out-of-line */
228 void parse ();
229 void read_constpool ();
230 void prepare_pool_entry (int index, unsigned char tag);
231 void read_fields ();
232 void read_methods ();
233 void read_one_class_attribute ();
234 void read_one_method_attribute (int method);
235 void read_one_code_attribute (int method);
236 void read_one_field_attribute (int field);
237 void throw_class_format_error (char *msg);
238
239 /** check an utf8 entry, without creating a Utf8Const object */
240 bool is_attribute_name (int index, char *name);
241
242 /** here goes the class-loader members defined out-of-line */
243 void handleConstantPool ();
244 void handleClassBegin (int, int, int);
245 void handleInterfacesBegin (int);
246 void handleInterface (int, int);
247 void handleFieldsBegin (int);
248 void handleField (int, int, int, int);
249 void handleFieldsEnd ();
250 void handleConstantValueAttribute (int,int);
251 void handleMethodsBegin (int);
252 void handleMethod (int, int, int, int);
253 void handleMethodsEnd ();
254 void handleCodeAttribute (int, int, int, int, int, int);
255 void handleExceptionTableEntry (int, int, int, int, int, int);
256
257 void checkExtends (jclass sub, jclass super);
258 void checkImplements (jclass sub, jclass super);
259
260 /*
261 * FIXME: we should keep a hash table of utf8-strings, since many will
262 * be the same. It's a little tricky, however, because the hash table
263 * needs to interact gracefully with the garbage collector. Much
264 * memory is to be saved by this, however! perhaps the improvement
265 * could be implemented in prims.cc (_Jv_makeUtf8Const), since it
266 * computes the hash value anyway.
267 */
268};
269
270void
271_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length)
272{
273 _Jv_ClassReader reader (klass, data, offset, length);
274 reader.parse();
275
276 /* that's it! */
277}
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
635/* this section defines the semantic actions of the parser */
636
637void _Jv_ClassReader::handleConstantPool ()
638{
639 /** now, we actually define the class' constant pool */
640
641 // the pool is scanned explicitly by the collector
642 jbyte *pool_tags = (jbyte*) _Jv_AllocBytes (pool_count);
643 _Jv_word *pool_data
644 = (_Jv_word*) _Jv_AllocBytes (pool_count * sizeof (_Jv_word));
645
646 def->constants.tags = pool_tags;
647 def->constants.data = pool_data;
648 def->constants.size = pool_count;
649
650 // Here we make a pass to collect the strings! We do this, because
651 // internally in the GCJ runtime, classes are encoded with .'s not /'s.
652 // Therefore, we first collect the strings, and then translate the rest
653 // of the utf8-entries (thus not representing strings) from /-notation
654 // to .-notation.
655 for (int i = 1; i < pool_count; i++)
656 {
657 if (tags[i] == JV_CONSTANT_String)
658 {
659 unsigned char* str_data = bytes + offsets [i];
660 int utf_index = get2u (str_data);
661 check_tag (utf_index, JV_CONSTANT_Utf8);
662 unsigned char *utf_data = bytes + offsets[utf_index];
663 int len = get2u (utf_data);
664 pool_data[i].utf8 = _Jv_makeUtf8Const ((char*)(utf_data+2), len);
665 pool_tags[i] = JV_CONSTANT_String;
666 }
667 else
668 {
669 pool_tags[i] = JV_CONSTANT_Undefined;
670 }
671 }
672
673 // and now, we scan everything else but strings & utf8-entries. This
674 // leaves out those utf8-entries which are not used; which will be left
675 // with a tag of JV_CONSTANT_Undefined in the class definition.
676 for (int index = 1; index < pool_count; index++)
677 {
678 switch (tags[index])
679 {
680 case JV_CONSTANT_Undefined:
681 case JV_CONSTANT_String:
682 case JV_CONSTANT_Utf8:
683 continue;
684
685 default:
686 prepare_pool_entry (index, tags[index]);
687 }
688 }
689
690}
691
692/* this is a recursive procedure, which will prepare pool entries as needed.
693 Which is how we avoid initializing those entries which go unused. */
694void
695_Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
696{
697 /* these two, pool_data and pool_tags, point into the class
698 structure we are currently defining */
699
700 unsigned char *pool_tags = (unsigned char*) def->constants.tags;
701 _Jv_word *pool_data = def->constants.data;
702
703 /* this entry was already prepared */
704 if (pool_tags[index] == this_tag)
705 return;
706
707 /* this_data points to the constant-pool information for the current
708 constant-pool entry */
709
710 unsigned char *this_data = bytes + offsets[index];
711
712 switch (this_tag)
713 {
714 case JV_CONSTANT_Utf8:
715 {
716 // If we came here, it is because some other tag needs this
717 // utf8-entry for type information! Thus, we translate /'s to .'s in
718 // order to accomondate gcj's internal representation.
719
720 int len = get2u (this_data);
721 char *buffer = (char*) __builtin_alloca (len);
722 char *s = ((char*) this_data)+2;
723
724 /* FIXME: avoid using a buffer here */
725 for (int i = 0; i < len; i++)
726 {
727 if (s[i] == '/')
728 buffer[i] = '.';
729 else
730 buffer[i] = (char) s[i];
731 }
732
733 pool_data[index].utf8 = _Jv_makeUtf8Const (buffer, len);
734 pool_tags[index] = JV_CONSTANT_Utf8;
735 }
736 break;
737
738 case JV_CONSTANT_Class:
739 {
740 int utf_index = get2u (this_data);
741 check_tag (utf_index, JV_CONSTANT_Utf8);
742 prepare_pool_entry (utf_index, JV_CONSTANT_Utf8);
743
744 if (verify)
745 verify_classname (pool_data[utf_index].utf8);
746
747 pool_data[index].utf8 = pool_data[utf_index].utf8;
748 pool_tags[index] = JV_CONSTANT_Class;
749 }
750 break;
751
752 case JV_CONSTANT_String:
753 // already handled before...
754 break;
755
756 case JV_CONSTANT_Fieldref:
757 case JV_CONSTANT_Methodref:
758 case JV_CONSTANT_InterfaceMethodref:
759 {
760 int class_index = get2u (this_data);
761 int nat_index = get2u (this_data+2);
762
763 check_tag (class_index, JV_CONSTANT_Class);
764 prepare_pool_entry (class_index, JV_CONSTANT_Class);
765
766 check_tag (nat_index, JV_CONSTANT_NameAndType);
767 prepare_pool_entry (nat_index, JV_CONSTANT_NameAndType);
768
769 // here, verify the signature and identifier name
770 if (verify)
771 {
772 _Jv_ushort name_index, type_index;
773 _Jv_loadIndexes (&pool_data[nat_index],
774 name_index, type_index);
775
776 if (this_tag == JV_CONSTANT_Fieldref)
777 _Jv_VerifyFieldSignature (pool_data[type_index].utf8);
778 else
779 _Jv_VerifyMethodSignature (pool_data[type_index].utf8);
780
781 _Jv_Utf8Const* name = pool_data[name_index].utf8;
782
783 if (this_tag != JV_CONSTANT_Fieldref
784 && ( _Jv_equalUtf8Consts (name, clinit_name)
785 || _Jv_equalUtf8Consts (name, init_name)))
786 /* ignore */;
787 else
788 verify_identifier (pool_data[name_index].utf8);
789 }
790
791 _Jv_storeIndexes (&pool_data[index], class_index, nat_index);
792 pool_tags[index] = this_tag;
793 }
794 break;
795
796 case JV_CONSTANT_NameAndType:
797 {
798 _Jv_ushort name_index = get2u (this_data);
799 _Jv_ushort type_index = get2u (this_data+2);
800
801 check_tag (name_index, JV_CONSTANT_Utf8);
802 prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
803
804 check_tag (type_index, JV_CONSTANT_Utf8);
805 prepare_pool_entry (type_index, JV_CONSTANT_Utf8);
806
807 _Jv_storeIndexes (&pool_data[index], name_index, type_index);
808 pool_tags[index] = JV_CONSTANT_NameAndType;
809 }
810 break;
811
812 case JV_CONSTANT_Float:
813 {
814 jfloat f = java::lang::Float::intBitsToFloat ((jint) get4 (this_data));
815 _Jv_storeFloat (&pool_data[index], f);
816 pool_tags[index] = JV_CONSTANT_Float;
817 }
818 break;
819
820 case JV_CONSTANT_Integer:
821 {
822 int i = get4 (this_data);
823 _Jv_storeInt (&pool_data[index], i);
824 pool_tags[index] = JV_CONSTANT_Integer;
825 }
826 break;
827
828 case JV_CONSTANT_Double:
829 {
830 jdouble d
831 = java::lang::Double::longBitsToDouble ((jlong) get8 (this_data));
832 _Jv_storeDouble (&pool_data[index], d);
833 pool_tags[index] = JV_CONSTANT_Double;
834 }
835 break;
836
837 case JV_CONSTANT_Long:
838 {
839 jlong i = get8 (this_data);
840 _Jv_storeLong (&pool_data[index], i);
841 pool_tags[index] = JV_CONSTANT_Long;
842 }
843 break;
844
845 default:
846 throw_class_format_error ("erroneous constant pool tag");
847 }
848}
849
850
851void
852_Jv_ClassReader::handleClassBegin
853 (int access_flags, int this_class, int super_class)
854{
855 using namespace java::lang::reflect;
856
857 unsigned char *pool_tags = (unsigned char*) def->constants.tags;
858 _Jv_word *pool_data = def->constants.data;
859
860 check_tag (this_class, JV_CONSTANT_Class);
861 _Jv_Utf8Const *loadedName = pool_data[this_class].utf8;
862
863 // was ClassLoader.defineClass called with an expected class name?
864 if (def->name == 0)
865 {
866 jclass orig = _Jv_FindClassInCache (loadedName, def->loader);
867
868 if (orig == 0)
869 {
870 def->name = loadedName;
871 }
872 else
873 {
874 jstring msg = JvNewStringUTF ("anonymous "
875 "class data denotes "
876 "existing class ");
877 msg = msg->concat (orig->getName ());
878
879 throw_no_class_def_found_error (msg);
880 }
881 }
882
883 // assert that the loaded class has the expected name, 5.3.5
884 else if (! _Jv_equalUtf8Consts (loadedName, def->name))
885 {
886 jstring msg = JvNewStringUTF ("loaded class ");
887 msg = msg->concat (def->getName ());
888 msg = msg->concat (_Jv_NewStringUTF (" was in fact named "));
889 jstring klass_name = _Jv_NewStringUTF (loadedName->data);
890 msg = msg->concat (klass_name);
891
892 throw_no_class_def_found_error (msg);
893 }
894
895 def->accflags = access_flags | java::lang::reflect::Modifier::INTERPRETED;
896 pool_data[this_class].clazz = def;
897 pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
898
899 if (super_class == 0 && ! (access_flags & Modifier::INTERFACE))
900 {
901 // FIXME: Consider this carefully!
902 if (! _Jv_equalUtf8Consts (def->name, java::lang::Object::class$.name))
903 throw_no_class_def_found_error ("loading java.lang.Object");
904 }
905
906 // In the pre-loading state, it can be looked up in the
907 // cache only by this thread! This allows the super-class
908 // to include references to this class.
909
910 def->state = JV_STATE_PRELOADING;
911
912 {
913 JvSynchronize sync (&java::lang::Class::class$);
914 _Jv_RegisterClass (def);
915 }
916
917 if (super_class != 0)
918 {
919 // Load the superclass.
920 check_tag (super_class, JV_CONSTANT_Class);
921 _Jv_Utf8Const* super_name = pool_data[super_class].utf8;
922
923 // Load the superclass using our defining loader.
924 jclass the_super = _Jv_FindClass (super_name,
925 def->loader);
926
927 // This will establish that we are allowed to be a subclass,
928 // and check for class circularity error.
929 checkExtends (def, the_super);
930
931 // Note: for an interface we will find Object as the
932 // superclass. We still check it above to ensure class file
933 // validity, but we simply assign `null' to the actual field in
934 // this case.
935 def->superclass = (((access_flags & Modifier::INTERFACE))
936 ? NULL : the_super);
937 pool_data[super_class].clazz = the_super;
938 pool_tags[super_class] = JV_CONSTANT_ResolvedClass;
939 }
940
941 // Now we've come past the circularity problem, we can
942 // now say that we're loading.
943
944 def->state = JV_STATE_LOADING;
945 def->notifyAll ();
946}
947
948///// implements the checks described in sect. 5.3.5.3
949void
950_Jv_ClassReader::checkExtends (jclass sub, jclass super)
951{
952 using namespace java::lang::reflect;
953
954 // having an interface or a final class as a superclass is no good
955 if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
956 {
957 throw_incompatible_class_change_error (sub->getName ());
958 }
959
960 // if the super class is not public, we need to check some more
961 if ((super->accflags & Modifier::PUBLIC) == 0)
962 {
963 // With package scope, the classes must have the same
964 // class loader.
965 if ( sub->loader != super->loader
966 || !_Jv_ClassNameSamePackage (sub->name, super->name))
967 {
968 throw_incompatible_class_change_error (sub->getName ());
969 }
970 }
971
972 for (; super != 0; super = super->superclass)
973 {
974 if (super == sub)
975 throw_class_circularity_error (sub->getName ());
976 }
977}
978
979
980
981void _Jv_ClassReader::handleInterfacesBegin (int count)
982{
983 def->interfaces = (jclass*) _Jv_AllocBytes (count*sizeof (jclass));
984 def->interface_count = count;
985}
986
987void _Jv_ClassReader::handleInterface (int if_number, int offset)
988{
989 _Jv_word * pool_data = def->constants.data;
990 unsigned char * pool_tags = (unsigned char*) def->constants.tags;
991
992 jclass the_interface;
993
994 if (pool_tags[offset] == JV_CONSTANT_Class)
995 {
996 _Jv_Utf8Const* name = pool_data[offset].utf8;
997 the_interface = _Jv_FindClass (name, def->loader);
998 }
999 else if (pool_tags[offset] == JV_CONSTANT_ResolvedClass)
1000 {
1001 the_interface = pool_data[offset].clazz;
1002 }
1003 else
1004 {
1005 throw_no_class_def_found_error ("erroneous constant pool tag");
1006 }
1007
1008 // checks the validity of the_interface, and that we are in fact
1009 // allowed to implement that interface.
1010 checkImplements (def, the_interface);
1011
1012 pool_data[offset].clazz = the_interface;
1013 pool_tags[offset] = JV_CONSTANT_ResolvedClass;
1014
1015 def->interfaces[if_number] = the_interface;
1016}
1017
1018void
1019_Jv_ClassReader::checkImplements (jclass sub, jclass super)
1020{
1021 using namespace java::lang::reflect;
1022
1023 // well, it *must* be an interface
1024 if ((super->accflags & Modifier::INTERFACE) == 0)
1025 {
1026 throw_incompatible_class_change_error (sub->getName ());
1027 }
1028
1029 // if it has package scope, it must also be defined by the
1030 // same loader.
1031 if ((super->accflags & Modifier::PUBLIC) == 0)
1032 {
1033 if ( sub->loader != super->loader
1034 || !_Jv_ClassNameSamePackage (sub->name, super->name))
1035 {
1036 throw_incompatible_class_change_error (sub->getName ());
1037 }
1038 }
1039
1040 // FIXME: add interface circularity check here
1041 if (sub == super)
1042 {
1043 throw_class_circularity_error (sub->getName ());
1044 }
1045}
1046
1047void _Jv_ClassReader::handleFieldsBegin (int count)
1048{
1049 def->fields = (_Jv_Field*)
1050 _Jv_AllocBytes (count * sizeof (_Jv_Field));
1051 def->field_count = count;
1052 def->field_initializers = (_Jv_ushort*)
1053 _Jv_AllocBytes (count * sizeof (_Jv_ushort));
1054 for (int i = 0; i < count; i++)
1055 def->field_initializers[i] = (_Jv_ushort) 0;
1056}
1057
1058void _Jv_ClassReader::handleField (int field_no,
1059 int flags,
1060 int name,
1061 int desc)
1062{
1063 using namespace java::lang::reflect;
1064
1065 _Jv_word *pool_data = def->constants.data;
1066
1067 _Jv_Field *field = &def->fields[field_no];
1068 _Jv_Utf8Const *field_name = pool_data[name].utf8;
1069
1070#ifndef COMPACT_FIELDS
1071 field->name = field_name;
1072#else
1073 field->nameIndex = name;
1074#endif
1075
1076 if (verify)
1077 verify_identifier (field_name);
1078
1079 // ignore flags we don't know about.
1080 field->flags = flags & Modifier::ALL_FLAGS;
1081
1082 if (verify)
1083 {
1084 if (field->flags & (Modifier::SYNCHRONIZED
1085 | Modifier::NATIVE
1086 | Modifier::INTERFACE
1087 | Modifier::ABSTRACT))
1088 throw_class_format_error ("erroneous field access flags");
1089
1090 if (1 < ( ((field->flags & Modifier::PUBLIC) ? 1 : 0)
1091 +((field->flags & Modifier::PRIVATE) ? 1 : 0)
1092 +((field->flags & Modifier::PROTECTED) ? 1 : 0)))
1093 throw_class_format_error ("erroneous field access flags");
1094 }
1095
1096 _Jv_Utf8Const* sig = pool_data[desc].utf8;
1097
1098 if (verify)
1099 _Jv_VerifyFieldSignature (sig);
1100
1101 // field->type is really a jclass, but while it is still
1102 // unresolved we keep an _Jv_Utf8Const* instead.
1103 field->type = (jclass) sig;
1104 field->flags |= _Jv_FIELD_UNRESOLVED_FLAG;
1105 field->u.boffset = 0;
1106}
1107
1108
1109void _Jv_ClassReader::handleConstantValueAttribute (int field_index,
1110 int value)
1111{
1112 using namespace java::lang::reflect;
1113
1114 _Jv_Field *field = &def->fields[field_index];
1115
1116 if ((field->flags & (Modifier::STATIC
1117 | Modifier::FINAL
1118 | Modifier::PRIVATE)) == 0)
1119 {
1120 // Ignore, as per vmspec #4.7.2
1121 return;
1122 }
1123
1124 // do not allow multiple constant fields!
1125 if (field->flags & _Jv_FIELD_CONSTANT_VALUE)
1126 throw_class_format_error ("field has multiple ConstantValue attributes");
1127
1128 field->flags |= _Jv_FIELD_CONSTANT_VALUE;
1129 def->field_initializers[field_index] = value;
1130
1131 /* type check the initializer */
1132
1133 if (value <= 0 || value >= pool_count)
1134 throw_class_format_error ("erroneous ConstantValue attribute");
1135
1136 /* FIXME: do the rest */
1137}
1138
1139void _Jv_ClassReader::handleFieldsEnd ()
1140{
1141 using namespace java::lang::reflect;
1142
1143 // We need to reorganize the fields so that the static ones are first,
1144 // to conform to GCJ class layout.
1145
1146 int low = 0;
1147 int high = def->field_count-1;
1148 _Jv_Field *fields = def->fields;
1149 _Jv_ushort *inits = def->field_initializers;
1150
1151 // this is kind of a raw version of quicksort.
1152 while (low < high)
1153 {
1154 // go forward on low, while it's a static
1155 while (low < high && (fields[low].flags & Modifier::STATIC) != 0)
1156 low++;
1157
1158 // go backwards on high, while it's a non-static
1159 while (low < high && (fields[high].flags & Modifier::STATIC) == 0)
1160 high--;
1161
1162 if (low==high)
1163 break;
1164
1165 _Jv_Field tmp = fields[low];
1166 _Jv_ushort itmp = inits[low];
1167
1168 fields[low] = fields[high];
1169 inits[low] = inits[high];
1170
1171 fields[high] = tmp;
1172 inits[high] = itmp;
1173
1174 high -= 1;
1175 low += 1;
1176 }
1177
1178 if ((fields[low].flags & Modifier::STATIC) != 0)
1179 low += 1;
1180
1181 def->static_field_count = low;
1182}
1183
1184
1185
1186void
1187_Jv_ClassReader::handleMethodsBegin (int count)
1188{
1189 def->methods = (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method) * count);
1190
1191 def->interpreted_methods
1192 = (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *)
1193 * count);
1194
1195 for (int i = 0; i < count; i++)
1196 {
1197 def->interpreted_methods[i] = 0;
1198 def->methods[i].index = (_Jv_ushort) -1;
1199 }
1200
1201 def->method_count = count;
1202}
1203
1204
1205void _Jv_ClassReader::handleMethod
1206 (int mth_index, int accflags, int name, int desc)
1207{
1208 using namespace java::lang::reflect;
1209
1210 _Jv_word *pool_data = def->constants.data;
1211 _Jv_Method *method = &def->methods[mth_index];
1212
1213 check_tag (name, JV_CONSTANT_Utf8);
1214 prepare_pool_entry (name, JV_CONSTANT_Utf8);
1215 method->name = pool_data[name].utf8;
1216
1217 check_tag (desc, JV_CONSTANT_Utf8);
1218 prepare_pool_entry (desc, JV_CONSTANT_Utf8);
1219 method->signature = pool_data[desc].utf8;
1220
1221 // ignore unknown flags
1222 method->accflags = accflags & Modifier::ALL_FLAGS;
1223
1224 // intialize...
1225 method->ncode = 0;
1226 method->throws = NULL;
1227
1228 if (verify)
1229 {
1230 if (_Jv_equalUtf8Consts (method->name, clinit_name)
1231 || _Jv_equalUtf8Consts (method->name, init_name))
1232 /* ignore */;
1233 else
1234 verify_identifier (method->name);
1235
1236 _Jv_VerifyMethodSignature (method->signature);
1237
1238 if (method->accflags & (Modifier::VOLATILE
1239 | Modifier::TRANSIENT
1240 | Modifier::INTERFACE))
1241 throw_class_format_error ("erroneous method access flags");
1242
1243 if (1 < ( ((method->accflags & Modifier::PUBLIC) ? 1 : 0)
1244 +((method->accflags & Modifier::PRIVATE) ? 1 : 0)
1245 +((method->accflags & Modifier::PROTECTED) ? 1 : 0)))
1246 throw_class_format_error ("erroneous method access flags");
1247 }
1248}
1249
1250void _Jv_ClassReader::handleCodeAttribute
1251 (int method_index, int max_stack, int max_locals,
1252 int code_start, int code_length, int exc_table_length)
1253{
1254 int size = _Jv_InterpMethod::size (exc_table_length, code_length);
1255 _Jv_InterpMethod *method =
1256 (_Jv_InterpMethod*) (_Jv_AllocBytes (size));
1257
1258 method->max_stack = max_stack;
1259 method->max_locals = max_locals;
1260 method->code_length = code_length;
1261 method->exc_count = exc_table_length;
1262 method->defining_class = def;
1263 method->self = &def->methods[method_index];
1264 method->prepared = NULL;
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.i = start_pc;
1283 exc[exc_index].end_pc.i = end_pc;
1284 exc[exc_index].handler_pc.i = handler_pc;
1285 exc[exc_index].handler_type.i = 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
1354/** Here we define the exceptions that can be thrown */
1355
1356static void
1357throw_no_class_def_found_error (jstring msg)
1358{
1359 throw (msg
1360 ? new java::lang::NoClassDefFoundError (msg)
1361 : new java::lang::NoClassDefFoundError);
1362}
1363
1364static void
1365throw_no_class_def_found_error (char *msg)
1366{
1367 throw_no_class_def_found_error (JvNewStringLatin1 (msg));
1368}
1369
1370static void
1371throw_class_format_error (jstring msg)
1372{
1373 throw (msg
1374 ? new java::lang::ClassFormatError (msg)
1375 : new java::lang::ClassFormatError);
1376}
1377
1378static void
1379throw_internal_error (char *msg)
1380{
1381 throw new java::lang::InternalError (JvNewStringLatin1 (msg));
1382}
1383
1384static void
1385throw_incompatible_class_change_error (jstring msg)
1386{
1387 throw new java::lang::IncompatibleClassChangeError (msg);
1388}
1389
1390static void
1391throw_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.