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