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