]> gcc.gnu.org Git - gcc.git/blame - libjava/defineclass.cc
re PR c++/6892 (ICE from #include inside switch(){} inside template function)
[gcc.git] / libjava / defineclass.cc
CommitLineData
58eb6e7c
AG
1// defineclass.cc - defining a class from .class format.
2
b3208f56 3/* Copyright (C) 1999, 2000, 2001 Free Software Foundation
58eb6e7c
AG
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
27e934d8
TT
21#include <config.h>
22
58eb6e7c
AG
23#include <java-interp.h>
24
a9770f9a 25#include <stdlib.h>
58eb6e7c 26#include <java-cpool.h>
27e934d8 27#include <gcj/cni.h>
58eb6e7c
AG
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>
e409a2c8 40#include <java/lang/reflect/Modifier.h>
58eb6e7c 41
107abb2f 42using namespace gcj;
58eb6e7c 43
bea31ffb
TT
44#ifdef INTERPRETER
45
cc712abf 46// these go in some separate functions, to avoid having _Jv_InitClass
58eb6e7c
AG
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__));
58eb6e7c
AG
56static void throw_incompatible_class_change_error (jstring msg)
57 __attribute__ ((__noreturn__));
58static void throw_class_circularity_error (jstring msg)
59 __attribute__ ((__noreturn__));
60
58eb6e7c
AG
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
f9edddab
PB
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
58eb6e7c
AG
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);
f9edddab 238 void throw_class_format_error (char *msg);
58eb6e7c
AG
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 */
58eb6e7c
AG
269};
270
58eb6e7c
AG
271void
272_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length)
273{
58eb6e7c
AG
274 _Jv_ClassReader reader (klass, data, offset, length);
275 reader.parse();
276
277 /* that's it! */
278}
279
58eb6e7c
AG
280\f
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{
3610e0d5
TT
342 tags = (unsigned char*) _Jv_AllocBytes (pool_count);
343 offsets = (unsigned int *) _Jv_AllocBytes (sizeof (int)
58eb6e7c
AG
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);
64d3a1b4 488
58eb6e7c
AG
489 handleMethod (i, access_flags, name_index,
490 descriptor_index);
64d3a1b4 491
58eb6e7c
AG
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 {
224b7b7b
TT
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;
58eb6e7c 542 }
224b7b7b 543
58eb6e7c
AG
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
ef9f3bc4
TT
570 // END_PC can be equal to CODE_LENGTH.
571 // See JVM Spec 4.7.4.
572 || end_pc > code_length
58eb6e7c
AG
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\f
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
3610e0d5 641 jbyte *pool_tags = (jbyte*) _Jv_AllocBytes (pool_count);
7941ceab 642 _Jv_word *pool_data
3610e0d5 643 = (_Jv_word*) _Jv_AllocBytes (pool_count * sizeof (_Jv_word));
58eb6e7c
AG
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);
7941ceab 663 pool_data[i].utf8 = _Jv_makeUtf8Const ((char*)(utf_data+2), len);
58eb6e7c
AG
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;
7941ceab 700 _Jv_word *pool_data = def->constants.data;
58eb6e7c
AG
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);
c2200099 720 char *buffer = (char*) __builtin_alloca (len);
58eb6e7c
AG
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
7941ceab 732 pool_data[index].utf8 = _Jv_makeUtf8Const (buffer, len);
58eb6e7c
AG
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)
f9edddab 744 verify_classname (pool_data[utf_index].utf8);
58eb6e7c 745
7941ceab 746 pool_data[index].utf8 = pool_data[utf_index].utf8;
58eb6e7c
AG
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;
7941ceab 772 _Jv_loadIndexes (&pool_data[nat_index],
58eb6e7c
AG
773 name_index, type_index);
774
775 if (this_tag == JV_CONSTANT_Fieldref)
7941ceab 776 _Jv_VerifyFieldSignature (pool_data[type_index].utf8);
58eb6e7c 777 else
7941ceab 778 _Jv_VerifyMethodSignature (pool_data[type_index].utf8);
58eb6e7c 779
7941ceab 780 _Jv_Utf8Const* name = pool_data[name_index].utf8;
58eb6e7c
AG
781
782 if (this_tag != JV_CONSTANT_Fieldref
783 && ( _Jv_equalUtf8Consts (name, clinit_name)
784 || _Jv_equalUtf8Consts (name, init_name)))
785 /* ignore */;
786 else
f9edddab 787 verify_identifier (pool_data[name_index].utf8);
58eb6e7c
AG
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 {
a12fe13d 813 jfloat f = java::lang::Float::intBitsToFloat ((jint) get4 (this_data));
58eb6e7c
AG
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 {
a12fe13d
TT
829 jdouble d
830 = java::lang::Double::longBitsToDouble ((jlong) get8 (this_data));
58eb6e7c
AG
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{
e409a2c8
TT
854 using namespace java::lang::reflect;
855
58eb6e7c 856 unsigned char *pool_tags = (unsigned char*) def->constants.tags;
7941ceab 857 _Jv_word *pool_data = def->constants.data;
58eb6e7c
AG
858
859 check_tag (this_class, JV_CONSTANT_Class);
7941ceab 860 _Jv_Utf8Const *loadedName = pool_data[this_class].utf8;
58eb6e7c
AG
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;
7941ceab 895 pool_data[this_class].clazz = def;
58eb6e7c
AG
896 pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
897
898 if (super_class == 0)
899 {
900 // interfaces have java.lang.Object as super.
e409a2c8 901 if (access_flags & Modifier::INTERFACE)
58eb6e7c 902 {
a52706f2 903 def->superclass = (jclass)&java::lang::Object::class$;
58eb6e7c
AG
904 }
905
906 // FIXME: Consider this carefully!
1d336a09 907 else if (!_Jv_equalUtf8Consts (def->name,
a52706f2 908 java::lang::Object::class$.name))
58eb6e7c
AG
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;
107abb2f
BM
919
920 {
921 JvSynchronize sync (&java::lang::Class::class$);
922 _Jv_RegisterClass (def);
923 }
58eb6e7c
AG
924
925 if (super_class != 0)
926 {
927 // load the super class
928 check_tag (super_class, JV_CONSTANT_Class);
7941ceab 929 _Jv_Utf8Const* super_name = pool_data[super_class].utf8;
58eb6e7c
AG
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;
7941ceab 940 pool_data[super_class].clazz = the_super;
58eb6e7c
AG
941 pool_tags[super_class] = JV_CONSTANT_ResolvedClass;
942 }
6d8b1244 943
58eb6e7c
AG
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{
e409a2c8
TT
955 using namespace java::lang::reflect;
956
58eb6e7c 957 // having an interface or a final class as a superclass is no good
e409a2c8 958 if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
58eb6e7c
AG
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
e409a2c8 964 if ((super->accflags & Modifier::PUBLIC) == 0)
58eb6e7c
AG
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{
3610e0d5 986 def->interfaces = (jclass*) _Jv_AllocBytes (count*sizeof (jclass));
58eb6e7c
AG
987 def->interface_count = count;
988}
989
990void _Jv_ClassReader::handleInterface (int if_number, int offset)
991{
7941ceab 992 _Jv_word * pool_data = def->constants.data;
58eb6e7c
AG
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 {
7941ceab 999 _Jv_Utf8Const* name = pool_data[offset].utf8;
58eb6e7c
AG
1000 the_interface = _Jv_FindClass (name, def->loader);
1001 }
1002 else if (pool_tags[offset] == JV_CONSTANT_ResolvedClass)
1003 {
7941ceab 1004 the_interface = pool_data[offset].clazz;
58eb6e7c
AG
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
7941ceab 1015 pool_data[offset].clazz = the_interface;
58eb6e7c
AG
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{
e409a2c8
TT
1024 using namespace java::lang::reflect;
1025
58eb6e7c 1026 // well, it *must* be an interface
e409a2c8 1027 if ((super->accflags & Modifier::INTERFACE) == 0)
58eb6e7c
AG
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.
e409a2c8 1034 if ((super->accflags & Modifier::PUBLIC) == 0)
58eb6e7c
AG
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*)
3610e0d5 1053 _Jv_AllocBytes (count * sizeof (_Jv_Field));
58eb6e7c
AG
1054 def->field_count = count;
1055 def->field_initializers = (_Jv_ushort*)
3610e0d5 1056 _Jv_AllocBytes (count * sizeof (_Jv_ushort));
58eb6e7c
AG
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{
e409a2c8
TT
1066 using namespace java::lang::reflect;
1067
7941ceab 1068 _Jv_word *pool_data = def->constants.data;
58eb6e7c
AG
1069
1070 _Jv_Field *field = &def->fields[field_no];
7941ceab 1071 _Jv_Utf8Const *field_name = pool_data[name].utf8;
58eb6e7c
AG
1072
1073#ifndef COMPACT_FIELDS
1074 field->name = field_name;
1075#else
1076 field->nameIndex = name;
1077#endif
1078
1079 if (verify)
f9edddab 1080 verify_identifier (field_name);
58eb6e7c
AG
1081
1082 // ignore flags we don't know about.
e409a2c8 1083 field->flags = flags & Modifier::ALL_FLAGS;
58eb6e7c
AG
1084
1085 if (verify)
1086 {
e409a2c8
TT
1087 if (field->flags & (Modifier::SYNCHRONIZED
1088 | Modifier::NATIVE
1089 | Modifier::INTERFACE
1090 | Modifier::ABSTRACT))
58eb6e7c
AG
1091 throw_class_format_error ("erroneous field access flags");
1092
e409a2c8
TT
1093 if (1 < ( ((field->flags & Modifier::PUBLIC) ? 1 : 0)
1094 +((field->flags & Modifier::PRIVATE) ? 1 : 0)
1095 +((field->flags & Modifier::PROTECTED) ? 1 : 0)))
58eb6e7c
AG
1096 throw_class_format_error ("erroneous field access flags");
1097 }
1098
7941ceab 1099 _Jv_Utf8Const* sig = pool_data[desc].utf8;
58eb6e7c
AG
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{
e409a2c8
TT
1115 using namespace java::lang::reflect;
1116
58eb6e7c
AG
1117 _Jv_Field *field = &def->fields[field_index];
1118
e409a2c8
TT
1119 if ((field->flags & (Modifier::STATIC
1120 | Modifier::FINAL
1121 | Modifier::PRIVATE)) == 0)
58eb6e7c
AG
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{
e409a2c8
TT
1144 using namespace java::lang::reflect;
1145
58eb6e7c
AG
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
e409a2c8 1158 while (low < high && (fields[low].flags & Modifier::STATIC) != 0)
58eb6e7c
AG
1159 low++;
1160
1161 // go backwards on high, while it's a non-static
e409a2c8 1162 while (low < high && (fields[high].flags & Modifier::STATIC) == 0)
58eb6e7c
AG
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
e409a2c8 1181 if ((fields[low].flags & Modifier::STATIC) != 0)
58eb6e7c
AG
1182 low += 1;
1183
1184 def->static_field_count = low;
1185}
1186
1187
1188
facc279f
TT
1189void
1190_Jv_ClassReader::handleMethodsBegin (int count)
58eb6e7c
AG
1191{
1192 def->methods = (_Jv_Method*)
3610e0d5 1193 _Jv_AllocBytes (sizeof (_Jv_Method)*count);
58eb6e7c 1194
facc279f 1195 def->interpreted_methods
3610e0d5
TT
1196 = (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *)
1197 * count);
58eb6e7c
AG
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{
e409a2c8
TT
1209 using namespace java::lang::reflect;
1210
7941ceab 1211 _Jv_word *pool_data = def->constants.data;
58eb6e7c
AG
1212 _Jv_Method *method = &def->methods[mth_index];
1213
1214 check_tag (name, JV_CONSTANT_Utf8);
1215 prepare_pool_entry (name, JV_CONSTANT_Utf8);
7941ceab 1216 method->name = pool_data[name].utf8;
58eb6e7c
AG
1217
1218 check_tag (desc, JV_CONSTANT_Utf8);
1219 prepare_pool_entry (desc, JV_CONSTANT_Utf8);
7941ceab 1220 method->signature = pool_data[desc].utf8;
58eb6e7c
AG
1221
1222 // ignore unknown flags
e409a2c8 1223 method->accflags = accflags & Modifier::ALL_FLAGS;
58eb6e7c
AG
1224
1225 // intialize...
1226 method->ncode = 0;
224b7b7b 1227 method->throws = NULL;
58eb6e7c
AG
1228
1229 if (verify)
1230 {
1231 if (_Jv_equalUtf8Consts (method->name, clinit_name)
1232 || _Jv_equalUtf8Consts (method->name, init_name))
1233 /* ignore */;
1234 else
f9edddab 1235 verify_identifier (method->name);
58eb6e7c
AG
1236
1237 _Jv_VerifyMethodSignature (method->signature);
1238
e409a2c8
TT
1239 if (method->accflags & (Modifier::VOLATILE
1240 | Modifier::TRANSIENT
1241 | Modifier::INTERFACE))
58eb6e7c
AG
1242 throw_class_format_error ("erroneous method access flags");
1243
e409a2c8
TT
1244 if (1 < ( ((method->accflags & Modifier::PUBLIC) ? 1 : 0)
1245 +((method->accflags & Modifier::PRIVATE) ? 1 : 0)
1246 +((method->accflags & Modifier::PROTECTED) ? 1 : 0)))
58eb6e7c
AG
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 =
3610e0d5 1257 (_Jv_InterpMethod*) (_Jv_AllocBytes (size));
58eb6e7c
AG
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);
a12fe13d 1270
58eb6e7c 1271 def->interpreted_methods[method_index] = method;
58eb6e7c
AG
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{
facc279f
TT
1278 _Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
1279 (def->interpreted_methods[method_index]);
58eb6e7c
AG
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{
e409a2c8
TT
1290 using namespace java::lang::reflect;
1291
58eb6e7c
AG
1292 for (int i = 0; i < def->method_count; i++)
1293 {
1294 _Jv_Method *method = &def->methods[i];
facc279f
TT
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 *)
3610e0d5 1302 _Jv_AllocBytes (sizeof (_Jv_JNIMethod));
facc279f
TT
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)
58eb6e7c
AG
1310 {
1311 if (def->interpreted_methods[i] != 0)
facc279f 1312 throw_class_format_error ("code provided for abstract method");
58eb6e7c
AG
1313 }
1314 else
1315 {
1316 if (def->interpreted_methods[i] == 0)
facc279f 1317 throw_class_format_error ("method with no code");
58eb6e7c
AG
1318 }
1319 }
58eb6e7c
AG
1320}
1321
f9edddab
PB
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}
58eb6e7c 1352\f
bea31ffb
TT
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\f
1396
58eb6e7c
AG
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
bea31ffb 1405/* Verify one element of a type descriptor or signature. */
58eb6e7c
AG
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':
bea31ffb
TT
1417 if (! void_ok)
1418 return 0;
58eb6e7c
AG
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;
bea31ffb
TT
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 != ';');
f9edddab
PB
1439 if (! _Jv_VerifyClassName (start, (unsigned short) (end-start)))
1440 return 0;
58eb6e7c
AG
1441 }
1442 break;
1443
1444 case '[':
1445 return _Jv_VerifyOne (ptr, limit, false);
1446 break;
bea31ffb 1447
58eb6e7c
AG
1448 default:
1449 return 0;
1450 }
1451
1452 return ptr;
58eb6e7c
AG
1453}
1454
bea31ffb 1455/* Verification and loading procedures. */
f9edddab 1456bool
58eb6e7c
AG
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
f9edddab 1464 return ptr == limit;
58eb6e7c
AG
1465}
1466
f9edddab 1467bool
58eb6e7c
AG
1468_Jv_VerifyMethodSignature (_Jv_Utf8Const*sig)
1469{
1470 unsigned char* ptr = (unsigned char*) sig->data;
1471 unsigned char* limit = ptr + sig->length;
1472
f9edddab
PB
1473 if (ptr == limit || UTF8_GET(ptr,limit) != '(')
1474 return false;
58eb6e7c
AG
1475
1476 while (ptr && UTF8_PEEK (ptr, limit) != ')')
1477 ptr = _Jv_VerifyOne (ptr, limit, false);
bea31ffb 1478
58eb6e7c 1479 if (UTF8_GET (ptr, limit) != ')')
f9edddab 1480 return false;
58eb6e7c
AG
1481
1482 // get the return type
1483 ptr = _Jv_VerifyOne (ptr, limit, true);
1484
f9edddab 1485 return ptr == limit;
58eb6e7c
AG
1486}
1487
bea31ffb
TT
1488/* We try to avoid calling the Character methods all the time, in
1489 fact, they will only be called for non-standard things. */
58eb6e7c
AG
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
82ae7822 1502 return java::lang::Character::isJavaIdentifierStart ((jchar) ch);
58eb6e7c
AG
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
82ae7822 1519 return java::lang::Character::isJavaIdentifierStart ((jchar) ch);
58eb6e7c
AG
1520}
1521
f9edddab 1522bool
58eb6e7c
AG
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))
f9edddab 1531 return false;
58eb6e7c
AG
1532
1533 while (ptr != limit)
1534 {
1535 if ((ch = UTF8_GET (ptr, limit))==-1
1536 || ! is_identifier_part (ch))
f9edddab 1537 return false;
58eb6e7c 1538 }
f9edddab 1539 return true;
58eb6e7c
AG
1540}
1541
f9edddab 1542bool
58eb6e7c
AG
1543_Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length)
1544{
1545 unsigned char *limit = ptr+length;
1546 int ch;
1547
e3253af5
AG
1548 if ('[' == UTF8_PEEK (ptr, limit))
1549 {
bea31ffb
TT
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)
f9edddab 1554 return false;
e3253af5 1555 else
f9edddab 1556 return true;
e3253af5
AG
1557 }
1558
58eb6e7c 1559 next_level:
f9edddab 1560 for (;;) {
58eb6e7c 1561 if ((ch = UTF8_GET (ptr, limit))==-1)
f9edddab 1562 return false;
58eb6e7c 1563 if (! is_identifier_start (ch))
f9edddab
PB
1564 return false;
1565 for (;;) {
58eb6e7c 1566 if (ptr == limit)
f9edddab 1567 return true;
58eb6e7c 1568 else if ((ch = UTF8_GET (ptr, limit))==-1)
f9edddab 1569 return false;
58eb6e7c
AG
1570 else if (ch == '.')
1571 goto next_level;
1572 else if (! is_identifier_part (ch))
f9edddab
PB
1573 return false;
1574 }
1575 }
58eb6e7c
AG
1576}
1577
f9edddab 1578bool
58eb6e7c
AG
1579_Jv_VerifyClassName (_Jv_Utf8Const *name)
1580{
f9edddab
PB
1581 return _Jv_VerifyClassName ((unsigned char*)&name->data[0],
1582 (_Jv_ushort) name->length);
58eb6e7c
AG
1583}
1584
bea31ffb
TT
1585/* Returns true, if NAME1 and NAME2 represent classes in the same
1586 package. */
58eb6e7c
AG
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;
bea31ffb 1601
58eb6e7c
AG
1602 else if (ch1 == -1)
1603 return false;
1604 }
1605
bea31ffb 1606 // Now the length of NAME1's package name is LEN.
58eb6e7c
AG
1607 int len = last1 - (unsigned char*) name1->data;
1608
bea31ffb 1609 // If this is longer than NAME2, then we're off.
58eb6e7c
AG
1610 if (len > name2->length)
1611 return false;
1612
bea31ffb 1613 // Then compare the first len bytes for equality.
58eb6e7c
AG
1614 if (memcmp ((void*) name1->data, (void*) name2->data, len) == 0)
1615 {
bea31ffb 1616 // Check that there are no .'s after position LEN in NAME2.
58eb6e7c
AG
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}
This page took 0.366481 seconds and 5 git commands to generate.