]> gcc.gnu.org Git - gcc.git/blob - libjava/defineclass.cc
Avoid exponential runtime
[gcc.git] / libjava / defineclass.cc
1 // defineclass.cc - defining a class from .class format.
2
3 /* Copyright (C) 1999, 2000 Free Software Foundation
4
5 This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
10
11 /*
12 Author: Kresten Krab Thorup <krab@gnu.org>
13
14 Written using the online versions of Java Language Specification (1st
15 ed.) and The Java Virtual Machine Specification (2nd ed.).
16
17 Future work may include reading (and handling) attributes which are
18 currently being ignored ("InnerClasses", "LineNumber", etc...).
19 */
20
21 #include <config.h>
22
23 #include <java-interp.h>
24
25 #ifdef INTERPRETER
26
27 #include <stdlib.h>
28 #include <java-cpool.h>
29 #include <gcj/cni.h>
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>
42 #include <java/lang/reflect/Modifier.h>
43
44 // we don't verify method names that match these.
45 static _Jv_Utf8Const *clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
46 static _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.
51 static void throw_internal_error (char *msg)
52 __attribute__ ((__noreturn__));
53 static void throw_no_class_def_found_error (jstring msg)
54 __attribute__ ((__noreturn__));
55 static void throw_no_class_def_found_error (char *msg)
56 __attribute__ ((__noreturn__));
57 static void throw_class_format_error (jstring msg)
58 __attribute__ ((__noreturn__));
59 static void throw_incompatible_class_change_error (jstring msg)
60 __attribute__ ((__noreturn__));
61 static void throw_class_circularity_error (jstring msg)
62 __attribute__ ((__noreturn__));
63
64 static jdouble long_bits_to_double (jlong);
65 static 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
77 struct _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
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
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);
244 void throw_class_format_error (char *msg);
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 */
275 };
276
277 /* This is used for the isJavaIdentifierStart & isJavaIdentifierPart
278 methods, so we avoid doing _Jv_InitClass all the time */
279
280 static const java::lang::Character *character = 0;
281 static void prepare_character ();
282
283 void
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 */
296 static 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
304 void
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
361 void _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
417 void _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
446 bool
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
457 void _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
491 void _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
522 void _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
596 void _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
608 void _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
623 void _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);
629 _Jv_word *pool_data
630 = (_Jv_word*) _Jv_AllocBytesChecked (pool_count * sizeof (_Jv_word));
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);
650 pool_data[i].utf8 = _Jv_makeUtf8Const ((char*)(utf_data+2), len);
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. */
680 void
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;
687 _Jv_word *pool_data = def->constants.data;
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);
707 char *buffer = (char*) __builtin_alloca (len);
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
719 pool_data[index].utf8 = _Jv_makeUtf8Const (buffer, len);
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)
731 verify_classname (pool_data[utf_index].utf8);
732
733 pool_data[index].utf8 = pool_data[utf_index].utf8;
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;
759 _Jv_loadIndexes (&pool_data[nat_index],
760 name_index, type_index);
761
762 if (this_tag == JV_CONSTANT_Fieldref)
763 _Jv_VerifyFieldSignature (pool_data[type_index].utf8);
764 else
765 _Jv_VerifyMethodSignature (pool_data[type_index].utf8);
766
767 _Jv_Utf8Const* name = pool_data[name_index].utf8;
768
769 if (this_tag != JV_CONSTANT_Fieldref
770 && ( _Jv_equalUtf8Consts (name, clinit_name)
771 || _Jv_equalUtf8Consts (name, init_name)))
772 /* ignore */;
773 else
774 verify_identifier (pool_data[name_index].utf8);
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
836 void
837 _Jv_ClassReader::handleClassBegin
838 (int access_flags, int this_class, int super_class)
839 {
840 using namespace java::lang::reflect;
841
842 unsigned char *pool_tags = (unsigned char*) def->constants.tags;
843 _Jv_word *pool_data = def->constants.data;
844
845 check_tag (this_class, JV_CONSTANT_Class);
846 _Jv_Utf8Const *loadedName = pool_data[this_class].utf8;
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;
881 pool_data[this_class].clazz = def;
882 pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
883
884 if (super_class == 0)
885 {
886 // interfaces have java.lang.Object as super.
887 if (access_flags & Modifier::INTERFACE)
888 {
889 def->superclass = (jclass)&java::lang::Class::class$;
890 }
891
892 // FIXME: Consider this carefully!
893 else if (!_Jv_equalUtf8Consts (def->name,
894 java::lang::Class::class$.name))
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);
911 _Jv_Utf8Const* super_name = pool_data[super_class].utf8;
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;
922 pool_data[super_class].clazz = the_super;
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
934 void
935 _Jv_ClassReader::checkExtends (jclass sub, jclass super)
936 {
937 using namespace java::lang::reflect;
938
939 // having an interface or a final class as a superclass is no good
940 if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
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
946 if ((super->accflags & Modifier::PUBLIC) == 0)
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
966 void _Jv_ClassReader::handleInterfacesBegin (int count)
967 {
968 def->interfaces = (jclass*) _Jv_AllocBytesChecked (count*sizeof (jclass));
969 def->interface_count = count;
970 }
971
972 void _Jv_ClassReader::handleInterface (int if_number, int offset)
973 {
974 _Jv_word * pool_data = def->constants.data;
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 {
981 _Jv_Utf8Const* name = pool_data[offset].utf8;
982 the_interface = _Jv_FindClass (name, def->loader);
983 }
984 else if (pool_tags[offset] == JV_CONSTANT_ResolvedClass)
985 {
986 the_interface = pool_data[offset].clazz;
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
997 pool_data[offset].clazz = the_interface;
998 pool_tags[offset] = JV_CONSTANT_ResolvedClass;
999
1000 def->interfaces[if_number] = the_interface;
1001 }
1002
1003 void
1004 _Jv_ClassReader::checkImplements (jclass sub, jclass super)
1005 {
1006 using namespace java::lang::reflect;
1007
1008 // well, it *must* be an interface
1009 if ((super->accflags & Modifier::INTERFACE) == 0)
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.
1016 if ((super->accflags & Modifier::PUBLIC) == 0)
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
1032 void _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
1043 void _Jv_ClassReader::handleField (int field_no,
1044 int flags,
1045 int name,
1046 int desc)
1047 {
1048 using namespace java::lang::reflect;
1049
1050 _Jv_word *pool_data = def->constants.data;
1051
1052 _Jv_Field *field = &def->fields[field_no];
1053 _Jv_Utf8Const *field_name = pool_data[name].utf8;
1054
1055 #ifndef COMPACT_FIELDS
1056 field->name = field_name;
1057 #else
1058 field->nameIndex = name;
1059 #endif
1060
1061 if (verify)
1062 verify_identifier (field_name);
1063
1064 // ignore flags we don't know about.
1065 field->flags = flags & Modifier::ALL_FLAGS;
1066
1067 if (verify)
1068 {
1069 if (field->flags & (Modifier::SYNCHRONIZED
1070 | Modifier::NATIVE
1071 | Modifier::INTERFACE
1072 | Modifier::ABSTRACT))
1073 throw_class_format_error ("erroneous field access flags");
1074
1075 if (1 < ( ((field->flags & Modifier::PUBLIC) ? 1 : 0)
1076 +((field->flags & Modifier::PRIVATE) ? 1 : 0)
1077 +((field->flags & Modifier::PROTECTED) ? 1 : 0)))
1078 throw_class_format_error ("erroneous field access flags");
1079 }
1080
1081 _Jv_Utf8Const* sig = pool_data[desc].utf8;
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
1094 void _Jv_ClassReader::handleConstantValueAttribute (int field_index,
1095 int value)
1096 {
1097 using namespace java::lang::reflect;
1098
1099 _Jv_Field *field = &def->fields[field_index];
1100
1101 if ((field->flags & (Modifier::STATIC
1102 | Modifier::FINAL
1103 | Modifier::PRIVATE)) == 0)
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
1124 void _Jv_ClassReader::handleFieldsEnd ()
1125 {
1126 using namespace java::lang::reflect;
1127
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
1140 while (low < high && (fields[low].flags & Modifier::STATIC) != 0)
1141 low++;
1142
1143 // go backwards on high, while it's a non-static
1144 while (low < high && (fields[high].flags & Modifier::STATIC) == 0)
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
1163 if ((fields[low].flags & Modifier::STATIC) != 0)
1164 low += 1;
1165
1166 def->static_field_count = low;
1167 }
1168
1169
1170
1171 void
1172 _Jv_ClassReader::handleMethodsBegin (int count)
1173 {
1174 def->methods = (_Jv_Method*)
1175 _Jv_AllocBytesChecked (sizeof (_Jv_Method)*count);
1176
1177 def->interpreted_methods
1178 = (_Jv_MethodBase **) _Jv_AllocBytesChecked (sizeof (_Jv_MethodBase *)
1179 * count);
1180
1181 for (int i = 0; i < count; i++)
1182 def->interpreted_methods[i] = 0;
1183
1184 def->method_count = count;
1185 }
1186
1187
1188 void _Jv_ClassReader::handleMethod
1189 (int mth_index, int accflags, int name, int desc)
1190 {
1191 using namespace java::lang::reflect;
1192
1193 _Jv_word *pool_data = def->constants.data;
1194 _Jv_Method *method = &def->methods[mth_index];
1195
1196 check_tag (name, JV_CONSTANT_Utf8);
1197 prepare_pool_entry (name, JV_CONSTANT_Utf8);
1198 method->name = pool_data[name].utf8;
1199
1200 check_tag (desc, JV_CONSTANT_Utf8);
1201 prepare_pool_entry (desc, JV_CONSTANT_Utf8);
1202 method->signature = pool_data[desc].utf8;
1203
1204 // ignore unknown flags
1205 method->accflags = accflags & Modifier::ALL_FLAGS;
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
1216 verify_identifier (method->name);
1217
1218 _Jv_VerifyMethodSignature (method->signature);
1219
1220 if (method->accflags & (Modifier::VOLATILE
1221 | Modifier::TRANSIENT
1222 | Modifier::INTERFACE))
1223 throw_class_format_error ("erroneous method access flags");
1224
1225 if (1 < ( ((method->accflags & Modifier::PUBLIC) ? 1 : 0)
1226 +((method->accflags & Modifier::PRIVATE) ? 1 : 0)
1227 +((method->accflags & Modifier::PROTECTED) ? 1 : 0)))
1228 throw_class_format_error ("erroneous method access flags");
1229 }
1230 }
1231
1232 void _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
1257 void _Jv_ClassReader::handleExceptionTableEntry
1258 (int method_index, int exc_index,
1259 int start_pc, int end_pc, int handler_pc, int catch_type)
1260 {
1261 _Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
1262 (def->interpreted_methods[method_index]);
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
1271 void _Jv_ClassReader::handleMethodsEnd ()
1272 {
1273 using namespace java::lang::reflect;
1274
1275 for (int i = 0; i < def->method_count; i++)
1276 {
1277 _Jv_Method *method = &def->methods[i];
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)
1293 {
1294 if (def->interpreted_methods[i] != 0)
1295 throw_class_format_error ("code provided for abstract method");
1296 }
1297 else
1298 {
1299 if (def->interpreted_methods[i] == 0)
1300 throw_class_format_error ("method with no code");
1301 }
1302 }
1303
1304 }
1305
1306 void _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 }
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 */
1346 static 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 != ';');
1376 if (! _Jv_VerifyClassName (start, (unsigned short) (end-start)))
1377 return 0;
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
1396 bool
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
1404 return ptr == limit;
1405 }
1406
1407 bool
1408 _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig)
1409 {
1410 unsigned char* ptr = (unsigned char*) sig->data;
1411 unsigned char* limit = ptr + sig->length;
1412
1413 if (ptr == limit || UTF8_GET(ptr,limit) != '(')
1414 return false;
1415
1416 while (ptr && UTF8_PEEK (ptr, limit) != ')')
1417 ptr = _Jv_VerifyOne (ptr, limit, false);
1418
1419 if (UTF8_GET (ptr, limit) != ')')
1420 return false;
1421
1422 // get the return type
1423 ptr = _Jv_VerifyOne (ptr, limit, true);
1424
1425 return ptr == limit;
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
1431 static __inline__ int
1432 is_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
1446 static __inline__ int
1447 is_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
1463 bool
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))
1472 return false;
1473
1474 while (ptr != limit)
1475 {
1476 if ((ch = UTF8_GET (ptr, limit))==-1
1477 || ! is_identifier_part (ch))
1478 return false;
1479 }
1480 return true;
1481 }
1482
1483 bool
1484 _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length)
1485 {
1486 unsigned char *limit = ptr+length;
1487 int ch;
1488
1489 if ('[' == UTF8_PEEK (ptr, limit))
1490 {
1491 if (! _Jv_VerifyOne (++ptr, limit, false))
1492 return false;
1493 else
1494 return true;
1495 }
1496
1497 next_level:
1498 for (;;) {
1499 if ((ch = UTF8_GET (ptr, limit))==-1)
1500 return false;
1501 if (! is_identifier_start (ch))
1502 return false;
1503 for (;;) {
1504 if (ptr == limit)
1505 return true;
1506 else if ((ch = UTF8_GET (ptr, limit))==-1)
1507 return false;
1508 else if (ch == '.')
1509 goto next_level;
1510 else if (! is_identifier_part (ch))
1511 return false;
1512 }
1513 }
1514 }
1515
1516 bool
1517 _Jv_VerifyClassName (_Jv_Utf8Const *name)
1518 {
1519 return _Jv_VerifyClassName ((unsigned char*)&name->data[0],
1520 (_Jv_ushort) name->length);
1521 }
1522
1523 /** returns true, if name1 and name2 represents classes in the same
1524 package. */
1525
1526 bool
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
1576 static void
1577 throw_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
1585 static void
1586 throw_no_class_def_found_error (char *msg)
1587 {
1588 throw_no_class_def_found_error (JvNewStringLatin1 (msg));
1589 }
1590
1591 static void
1592 throw_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
1600 static void
1601 throw_internal_error (char *msg)
1602 {
1603 JvThrow
1604 (new java::lang::InternalError (JvNewStringLatin1 (msg)));
1605 }
1606
1607 static jfloat int_bits_to_float (jint value)
1608 {
1609 return java::lang::Float::intBitsToFloat (value);
1610 }
1611
1612 static jdouble long_bits_to_double (jlong value)
1613 {
1614 return java::lang::Double::longBitsToDouble (value);
1615 }
1616
1617 static void throw_incompatible_class_change_error (jstring msg)
1618 {
1619 JvThrow (new java::lang::IncompatibleClassChangeError (msg));
1620 }
1621
1622 static 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.113285 seconds and 5 git commands to generate.