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