]>
Commit | Line | Data |
---|---|---|
e04a16fb | 1 | /* Parser for Java(TM) .class files. |
df32d2ce | 2 | Copyright (C) 1996, 1998, 1999, 2000 Free Software Foundation, Inc. |
e04a16fb AG |
3 | |
4 | This file is part of GNU CC. | |
5 | ||
6 | GNU CC is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GNU CC is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU CC; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. | |
20 | ||
21 | Java and all Java-based marks are trademarks or registered trademarks | |
22 | of Sun Microsystems, Inc. in the United States and other countries. | |
23 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
24 | ||
25 | /* Written by Per Bothner <bothner@cygnus.com> */ | |
26 | ||
e04a16fb | 27 | #include "config.h" |
1f43f4b4 | 28 | #include "system.h" |
e04a16fb AG |
29 | #include "tree.h" |
30 | #include "obstack.h" | |
31 | #include "flags.h" | |
32 | #include "java-except.h" | |
33 | #include "input.h" | |
34 | #include "java-tree.h" | |
d4476be2 | 35 | #include "toplev.h" |
8e1f2d4c | 36 | #include "parse.h" |
19e223db | 37 | #include "ggc.h" |
e04a16fb | 38 | |
6b8a24cd TT |
39 | #ifdef HAVE_LOCALE_H |
40 | #include <locale.h> | |
41 | #endif | |
42 | ||
d19cbcb5 TT |
43 | #ifdef HAVE_NL_LANGINFO |
44 | #include <langinfo.h> | |
45 | #endif | |
46 | ||
e04a16fb AG |
47 | /* A CONSTANT_Utf8 element is converted to an IDENTIFIER_NODE at parse time. */ |
48 | #define JPOOL_UTF(JCF, INDEX) CPOOL_UTF(&(JCF)->cpool, INDEX) | |
49 | #define JPOOL_UTF_LENGTH(JCF, INDEX) IDENTIFIER_LENGTH (JPOOL_UTF (JCF, INDEX)) | |
50 | #define JPOOL_UTF_DATA(JCF, INDEX) \ | |
c8e7d2e6 | 51 | ((const unsigned char *) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX))) |
e04a16fb AG |
52 | #define HANDLE_CONSTANT_Utf8(JCF, INDEX, LENGTH) \ |
53 | do { \ | |
54 | unsigned char save; unsigned char *text; \ | |
55 | JCF_FILL (JCF, (LENGTH)+1); /* Make sure we read 1 byte beyond string. */ \ | |
56 | text = (JCF)->read_ptr; \ | |
57 | save = text[LENGTH]; \ | |
58 | text[LENGTH] = 0; \ | |
59 | (JCF)->cpool.data[INDEX] = (jword) get_identifier (text); \ | |
60 | text[LENGTH] = save; \ | |
61 | JCF_SKIP (JCF, LENGTH); } while (0) | |
62 | ||
63 | #include "jcf.h" | |
e04a16fb AG |
64 | |
65 | extern struct obstack *saveable_obstack; | |
66 | extern struct obstack temporary_obstack; | |
67 | extern struct obstack permanent_obstack; | |
68 | ||
3ff9925c AG |
69 | /* Set to non-zero value in order to emit class initilization code |
70 | before static field references. */ | |
71 | extern int always_initialize_class_p; | |
72 | ||
23a79c61 | 73 | /* The FIELD_DECL for the current field. */ |
e04a16fb AG |
74 | static tree current_field = NULL_TREE; |
75 | ||
5e942c50 | 76 | /* The METHOD_DECL for the current method. */ |
e04a16fb AG |
77 | static tree current_method = NULL_TREE; |
78 | ||
4f65832d KG |
79 | /* The Java .class file that provides main_class; the main input file. */ |
80 | static struct JCF main_jcf[1]; | |
81 | ||
5e942c50 | 82 | /* Declarations of some functions used here. */ |
df32d2ce KG |
83 | static tree give_name_to_class PARAMS ((JCF *jcf, int index)); |
84 | static void parse_zip_file_entries PARAMS ((void)); | |
85 | static void process_zip_dir PARAMS ((void)); | |
d19cbcb5 | 86 | static void parse_source_file PARAMS ((tree, FILE *)); |
df32d2ce KG |
87 | static void jcf_parse_source PARAMS ((void)); |
88 | static int jcf_figure_file_type PARAMS ((JCF *)); | |
89 | static int find_in_current_zip PARAMS ((const char *, struct JCF **)); | |
90 | static void parse_class_file PARAMS ((void)); | |
91 | static void set_source_filename PARAMS ((JCF *, int)); | |
92 | static int predefined_filename_p PARAMS ((tree)); | |
e04a16fb AG |
93 | |
94 | /* Handle "SourceFile" attribute. */ | |
95 | ||
c8e7d2e6 | 96 | static void |
e04a16fb AG |
97 | set_source_filename (jcf, index) |
98 | JCF *jcf; | |
99 | int index; | |
100 | { | |
101 | tree sfname_id = get_name_constant (jcf, index); | |
63ad61ed | 102 | const char *sfname = IDENTIFIER_POINTER (sfname_id); |
e04a16fb AG |
103 | if (input_filename != NULL) |
104 | { | |
105 | int old_len = strlen (input_filename); | |
106 | int new_len = IDENTIFIER_LENGTH (sfname_id); | |
107 | /* Use the current input_filename (derived from the class name) | |
108 | if it has a directory prefix, but otherwise matches sfname. */ | |
109 | if (old_len > new_len | |
110 | && strcmp (sfname, input_filename + old_len - new_len) == 0 | |
111 | && (input_filename[old_len - new_len - 1] == '/' | |
112 | || input_filename[old_len - new_len - 1] == '\\')) | |
113 | return; | |
114 | } | |
115 | input_filename = sfname; | |
116 | DECL_SOURCE_FILE (TYPE_NAME (current_class)) = sfname; | |
117 | if (current_class == main_class) main_input_filename = input_filename; | |
118 | } | |
119 | ||
120 | #define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX) | |
121 | ||
122 | #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \ | |
123 | { tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \ | |
124 | current_class = give_name_to_class (jcf, THIS); \ | |
125 | set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);} | |
126 | ||
127 | #define HANDLE_CLASS_INTERFACE(INDEX) \ | |
128 | add_interface (current_class, get_class_constant (jcf, INDEX)) | |
129 | ||
130 | #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \ | |
131 | { int sig_index = SIGNATURE; \ | |
132 | current_field = add_field (current_class, get_name_constant (jcf, NAME), \ | |
133 | parse_signature (jcf, sig_index), ACCESS_FLAGS); \ | |
134 | set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); } | |
135 | ||
136 | #define HANDLE_END_FIELDS() \ | |
137 | (current_field = NULL_TREE) | |
138 | ||
139 | #define HANDLE_CONSTANTVALUE(INDEX) \ | |
140 | { tree constant; int index = INDEX; \ | |
f868ca8f | 141 | if (! flag_emit_class_files && JPOOL_TAG (jcf, index) == CONSTANT_String) { \ |
e04a16fb AG |
142 | tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \ |
143 | constant = build_utf8_ref (name); \ | |
144 | } \ | |
145 | else \ | |
146 | constant = get_constant (jcf, index); \ | |
147 | set_constant_value (current_field, constant); } | |
148 | ||
149 | #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \ | |
150 | (current_method = add_method (current_class, ACCESS_FLAGS, \ | |
151 | get_name_constant (jcf, NAME), \ | |
152 | get_name_constant (jcf, SIGNATURE)), \ | |
153 | DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \ | |
154 | DECL_LINENUMBERS_OFFSET (current_method) = 0) | |
155 | ||
156 | #define HANDLE_END_METHODS() \ | |
157 | { tree handle_type = CLASS_TO_HANDLE_TYPE (current_class); \ | |
158 | if (handle_type != current_class) layout_type (handle_type); } | |
159 | ||
160 | #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \ | |
161 | { DECL_MAX_STACK (current_method) = (MAX_STACK); \ | |
162 | DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \ | |
163 | DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \ | |
164 | DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); } | |
165 | ||
166 | #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \ | |
167 | { int n = (COUNT); \ | |
168 | DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \ | |
169 | JCF_SKIP (jcf, n * 10); } | |
170 | ||
171 | #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \ | |
172 | { int n = (COUNT); \ | |
173 | DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \ | |
174 | JCF_SKIP (jcf, n * 4); } | |
175 | ||
0ef38928 PB |
176 | #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \ |
177 | { \ | |
178 | int n = COUNT; \ | |
179 | tree list = DECL_FUNCTION_THROWS (current_method); \ | |
180 | while (--n >= 0) \ | |
181 | { \ | |
182 | tree thrown_class = get_class_constant (jcf, JCF_readu2 (jcf)); \ | |
183 | list = tree_cons (NULL_TREE, thrown_class, list); \ | |
184 | } \ | |
185 | DECL_FUNCTION_THROWS (current_method) = nreverse (list); \ | |
186 | } | |
187 | ||
c2952b01 APB |
188 | /* Link seen inner classes to their outer context and register the |
189 | inner class to its outer context. They will be later loaded. */ | |
190 | #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \ | |
191 | { \ | |
192 | int c = (count); \ | |
193 | while (c--) \ | |
194 | { \ | |
1e12ab9b APB |
195 | tree class = get_class_constant (jcf, JCF_readu2 (jcf)); \ |
196 | tree decl = TYPE_NAME (class); \ | |
197 | if (DECL_P (decl) && !CLASS_COMPLETE_P (decl)) \ | |
c2952b01 APB |
198 | { \ |
199 | tree outer = TYPE_NAME (get_class_constant (jcf, \ | |
200 | JCF_readu2 (jcf))); \ | |
201 | tree alias = get_name_constant (jcf, JCF_readu2 (jcf)); \ | |
c2952b01 | 202 | JCF_SKIP (jcf, 2); \ |
c2952b01 APB |
203 | DECL_CONTEXT (decl) = outer; \ |
204 | DECL_INNER_CLASS_LIST (outer) = \ | |
205 | tree_cons (decl, alias, DECL_INNER_CLASS_LIST (outer)); \ | |
1e12ab9b | 206 | CLASS_COMPLETE_P (decl) = 1; \ |
c2952b01 APB |
207 | } \ |
208 | else \ | |
209 | JCF_SKIP (jcf, 6); \ | |
210 | } \ | |
211 | } | |
212 | ||
e04a16fb AG |
213 | #include "jcf-reader.c" |
214 | ||
215 | static int yydebug; | |
216 | ||
217 | tree | |
218 | parse_signature (jcf, sig_index) | |
219 | JCF *jcf; | |
220 | int sig_index; | |
221 | { | |
222 | if (sig_index <= 0 || sig_index >= JPOOL_SIZE(jcf) | |
223 | || JPOOL_TAG (jcf, sig_index) != CONSTANT_Utf8) | |
224 | fatal ("invalid field/method signature"); | |
225 | else | |
226 | { | |
227 | return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index), | |
228 | JPOOL_UTF_LENGTH (jcf, sig_index)); | |
229 | } | |
230 | } | |
231 | ||
232 | void | |
233 | init_lex () | |
234 | { | |
235 | /* Make identifier nodes long enough for the language-specific slots. */ | |
236 | set_identifier_size (sizeof (struct lang_identifier)); | |
237 | } | |
238 | ||
239 | void | |
240 | set_yydebug (value) | |
241 | int value; | |
242 | { | |
243 | yydebug = value; | |
244 | } | |
245 | ||
246 | tree | |
247 | get_constant (jcf, index) | |
248 | JCF *jcf; | |
249 | int index; | |
250 | { | |
251 | tree value; | |
252 | int tag; | |
253 | if (index <= 0 || index >= JPOOL_SIZE(jcf)) | |
254 | goto bad; | |
255 | tag = JPOOL_TAG (jcf, index); | |
256 | if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8) | |
257 | return (tree) jcf->cpool.data[index]; | |
e04a16fb AG |
258 | switch (tag) |
259 | { | |
260 | case CONSTANT_Integer: | |
261 | { | |
262 | jint num = JPOOL_INT(jcf, index); | |
263 | value = build_int_2 (num, num < 0 ? -1 : 0); | |
264 | TREE_TYPE (value) = int_type_node; | |
265 | break; | |
266 | } | |
267 | case CONSTANT_Long: | |
268 | { | |
269 | jint num = JPOOL_INT (jcf, index); | |
270 | HOST_WIDE_INT lo, hi; | |
271 | lshift_double (num, 0, 32, 64, &lo, &hi, 0); | |
9b1ee05b AH |
272 | num = JPOOL_INT (jcf, index+1) & 0xffffffff; |
273 | add_double (lo, hi, num, 0, &lo, &hi); | |
e04a16fb AG |
274 | value = build_int_2 (lo, hi); |
275 | TREE_TYPE (value) = long_type_node; | |
276 | force_fit_type (value, 0); | |
277 | break; | |
278 | } | |
279 | #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT | |
280 | case CONSTANT_Float: | |
281 | { | |
282 | jint num = JPOOL_INT(jcf, index); | |
283 | REAL_VALUE_TYPE d; | |
284 | #ifdef REAL_ARITHMETIC | |
285 | d = REAL_VALUE_FROM_TARGET_SINGLE (num); | |
286 | #else | |
287 | union { float f; jint i; } u; | |
288 | u.i = num; | |
289 | d = u.f; | |
290 | #endif | |
291 | value = build_real (float_type_node, d); | |
292 | break; | |
293 | } | |
294 | case CONSTANT_Double: | |
295 | { | |
296 | HOST_WIDE_INT num[2]; | |
297 | REAL_VALUE_TYPE d; | |
298 | HOST_WIDE_INT lo, hi; | |
299 | num[0] = JPOOL_INT (jcf, index); | |
300 | lshift_double (num[0], 0, 32, 64, &lo, &hi, 0); | |
301 | num[0] = JPOOL_INT (jcf, index+1); | |
302 | add_double (lo, hi, num[0], 0, &lo, &hi); | |
303 | if (FLOAT_WORDS_BIG_ENDIAN) | |
304 | { | |
305 | num[0] = hi; | |
306 | num[1] = lo; | |
307 | } | |
308 | else | |
309 | { | |
310 | num[0] = lo; | |
311 | num[1] = hi; | |
312 | } | |
313 | #ifdef REAL_ARITHMETIC | |
314 | d = REAL_VALUE_FROM_TARGET_DOUBLE (num); | |
315 | #else | |
2fe47729 AH |
316 | { |
317 | union { double d; jint i[2]; } u; | |
318 | u.i[0] = (jint) num[0]; | |
319 | u.i[1] = (jint) num[1]; | |
320 | d = u.d; | |
321 | } | |
e04a16fb AG |
322 | #endif |
323 | value = build_real (double_type_node, d); | |
324 | break; | |
325 | } | |
326 | #endif /* TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT */ | |
327 | case CONSTANT_String: | |
328 | { | |
e04a16fb | 329 | tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); |
c8e7d2e6 | 330 | const char *utf8_ptr = IDENTIFIER_POINTER (name); |
e04a16fb AG |
331 | unsigned char *str_ptr; |
332 | int utf8_len = IDENTIFIER_LENGTH (name); | |
c8e7d2e6 | 333 | const unsigned char *str = (const unsigned char *)utf8_ptr; |
e04a16fb AG |
334 | int i = utf8_len; |
335 | int str_len; | |
336 | ||
337 | /* Count the number of Unicode characters in the string, | |
338 | while checking for a malformed Utf8 string. */ | |
339 | for (str_len = 0; i > 0; str_len++) | |
340 | { | |
341 | int char_len = UT8_CHAR_LENGTH (*str); | |
34d4df06 APB |
342 | if (char_len < 0 || char_len > 3 || char_len > i) |
343 | fatal ("bad string constant"); | |
e04a16fb AG |
344 | str += char_len; |
345 | i -= char_len; | |
346 | } | |
347 | ||
348 | value = make_node (STRING_CST); | |
f868ca8f | 349 | TREE_TYPE (value) = build_pointer_type (string_type_node); |
e04a16fb | 350 | TREE_STRING_LENGTH (value) = 2 * str_len; |
1f8f4a0b | 351 | TREE_STRING_POINTER (value) = ggc_alloc (2 * str_len); |
e04a16fb | 352 | str_ptr = (unsigned char *) TREE_STRING_POINTER (value); |
c8e7d2e6 | 353 | str = (const unsigned char *)utf8_ptr; |
e04a16fb AG |
354 | for (i = 0; i < str_len; i++) |
355 | { | |
356 | int char_value; | |
357 | int char_len = UT8_CHAR_LENGTH (*str); | |
358 | switch (char_len) | |
359 | { | |
360 | case 1: | |
361 | char_value = *str++; | |
362 | break; | |
363 | case 2: | |
364 | char_value = *str++ & 0x1F; | |
365 | char_value = (char_value << 6) | (*str++ & 0x3F); | |
366 | break; | |
367 | case 3: | |
34d4df06 | 368 | char_value = *str++ & 0x0F; |
e04a16fb AG |
369 | char_value = (char_value << 6) | (*str++ & 0x3F); |
370 | char_value = (char_value << 6) | (*str++ & 0x3F); | |
371 | break; | |
372 | default: | |
373 | goto bad; | |
374 | } | |
375 | if (BYTES_BIG_ENDIAN) | |
376 | { | |
377 | *str_ptr++ = char_value >> 8; | |
378 | *str_ptr++ = char_value & 0xFF; | |
379 | } | |
380 | else | |
381 | { | |
382 | *str_ptr++ = char_value & 0xFF; | |
383 | *str_ptr++ = char_value >> 8; | |
384 | } | |
385 | } | |
386 | } | |
387 | break; | |
388 | default: | |
389 | goto bad; | |
390 | } | |
e04a16fb AG |
391 | JPOOL_TAG(jcf, index) = tag | CONSTANT_ResolvedFlag; |
392 | jcf->cpool.data [index] = (jword) value; | |
393 | return value; | |
394 | bad: | |
395 | fatal ("bad value constant type %d, index %d", | |
396 | JPOOL_TAG( jcf, index ), index); | |
397 | } | |
398 | ||
399 | tree | |
400 | get_name_constant (jcf, index) | |
401 | JCF *jcf; | |
402 | int index; | |
403 | { | |
404 | tree name = get_constant (jcf, index); | |
405 | if (TREE_CODE (name) != IDENTIFIER_NODE) | |
406 | fatal ("bad nameandtype index %d", index); | |
407 | return name; | |
408 | } | |
409 | ||
410 | static tree | |
411 | give_name_to_class (jcf, i) | |
412 | JCF *jcf; | |
413 | int i; | |
414 | { | |
415 | if (i <= 0 || i >= JPOOL_SIZE(jcf) | |
416 | || JPOOL_TAG (jcf, i) != CONSTANT_Class) | |
417 | fatal ("bad class index %d", i); | |
418 | else | |
419 | { | |
420 | tree this_class; | |
421 | int j = JPOOL_USHORT1 (jcf, i); | |
422 | /* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */ | |
423 | tree class_name = unmangle_classname (JPOOL_UTF_DATA (jcf, j), | |
424 | JPOOL_UTF_LENGTH (jcf, j)); | |
425 | this_class = lookup_class (class_name); | |
426 | input_filename = DECL_SOURCE_FILE (TYPE_NAME (this_class)); | |
427 | lineno = 0; | |
428 | if (main_input_filename == NULL && jcf == main_jcf) | |
429 | main_input_filename = input_filename; | |
430 | ||
431 | jcf->cpool.data[i] = (jword) this_class; | |
432 | JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass; | |
433 | return this_class; | |
434 | } | |
435 | } | |
436 | ||
437 | /* Get the class of the CONSTANT_Class whose constant pool index is I. */ | |
438 | ||
439 | tree | |
440 | get_class_constant (JCF *jcf , int i) | |
441 | { | |
442 | tree type; | |
443 | if (i <= 0 || i >= JPOOL_SIZE(jcf) | |
444 | || (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) != CONSTANT_Class) | |
445 | fatal ("bad class index %d", i); | |
446 | ||
447 | if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass) | |
448 | { | |
449 | int name_index = JPOOL_USHORT1 (jcf, i); | |
450 | /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */ | |
c8e7d2e6 | 451 | const char *name = JPOOL_UTF_DATA (jcf, name_index); |
e04a16fb AG |
452 | int nlength = JPOOL_UTF_LENGTH (jcf, name_index); |
453 | if (name[0] == '[') /* Handle array "classes". */ | |
e4de5a10 | 454 | type = TREE_TYPE (parse_signature_string (name, nlength)); |
e04a16fb AG |
455 | else |
456 | { | |
457 | tree cname = unmangle_classname (name, nlength); | |
458 | type = lookup_class (cname); | |
459 | } | |
460 | jcf->cpool.data[i] = (jword) type; | |
461 | JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass; | |
462 | } | |
463 | else | |
464 | type = (tree) jcf->cpool.data[i]; | |
465 | return type; | |
466 | } | |
467 | ||
bc3ca41b PB |
468 | /* Read a class with the fully qualified-name NAME. |
469 | Return 1 iff we read the requested file. | |
470 | (It is still possible we failed if the file did not | |
471 | define the class it is supposed to.) */ | |
472 | ||
473 | int | |
474 | read_class (name) | |
475 | tree name; | |
e04a16fb AG |
476 | { |
477 | JCF this_jcf, *jcf; | |
e04a16fb | 478 | tree save_current_class = current_class; |
3b304f5b | 479 | const char *save_input_filename = input_filename; |
e04a16fb | 480 | JCF *save_current_jcf = current_jcf; |
8e1f2d4c | 481 | long saved_pos = 0; |
e04a16fb AG |
482 | if (current_jcf->read_state) |
483 | saved_pos = ftell (current_jcf->read_state); | |
484 | ||
e04a16fb | 485 | /* Search in current zip first. */ |
8e1f2d4c | 486 | if (find_in_current_zip (IDENTIFIER_POINTER (name), &jcf) == 0) |
1ba305b5 APB |
487 | { |
488 | if (find_class (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name), | |
489 | &this_jcf, 1) == 0) | |
1f8f4a0b | 490 | return 0; |
1ba305b5 APB |
491 | else |
492 | { | |
493 | this_jcf.seen_in_zip = 0; | |
494 | current_jcf = &this_jcf; | |
1ba305b5 APB |
495 | } |
496 | } | |
e04a16fb AG |
497 | else |
498 | current_jcf = jcf; | |
499 | ||
500 | if (current_jcf->java_source) | |
8e1f2d4c | 501 | jcf_parse_source (); |
e04a16fb | 502 | else { |
23a79c61 APB |
503 | java_parser_context_save_global (); |
504 | java_push_parser_context (); | |
e04a16fb AG |
505 | input_filename = current_jcf->filename; |
506 | jcf_parse (current_jcf); | |
23a79c61 APB |
507 | java_pop_parser_context (0); |
508 | java_parser_context_restore_global (); | |
e04a16fb AG |
509 | } |
510 | ||
511 | if (!current_jcf->seen_in_zip) | |
512 | JCF_FINISH (current_jcf); | |
e04a16fb AG |
513 | |
514 | current_class = save_current_class; | |
515 | input_filename = save_input_filename; | |
516 | current_jcf = save_current_jcf; | |
517 | if (current_jcf->read_state) | |
518 | fseek (current_jcf->read_state, saved_pos, SEEK_SET); | |
bc3ca41b PB |
519 | return 1; |
520 | } | |
521 | ||
522 | /* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if | |
523 | called from the parser, otherwise it's a RECORD_TYPE node. If | |
524 | VERBOSE is 1, print error message on failure to load a class. */ | |
525 | ||
526 | /* Replace calls to load_class by having callers call read_class directly | |
527 | - and then perhaps rename read_class to load_class. FIXME */ | |
528 | ||
529 | void | |
530 | load_class (class_or_name, verbose) | |
531 | tree class_or_name; | |
532 | int verbose; | |
533 | { | |
534 | tree name; | |
535 | ||
536 | /* class_or_name can be the name of the class we want to load */ | |
537 | if (TREE_CODE (class_or_name) == IDENTIFIER_NODE) | |
538 | name = class_or_name; | |
539 | /* In some cases, it's a dependency that we process earlier that | |
540 | we though */ | |
541 | else if (TREE_CODE (class_or_name) == TREE_LIST) | |
542 | name = TYPE_NAME (TREE_PURPOSE (class_or_name)); | |
543 | /* Or it's a type in the making */ | |
544 | else | |
545 | name = DECL_NAME (TYPE_NAME (class_or_name)); | |
546 | ||
547 | if (read_class (name) == 0 && verbose) | |
2a1ed9c1 | 548 | fatal ("Cannot find file for class %s.", IDENTIFIER_POINTER (name)); |
e04a16fb AG |
549 | } |
550 | ||
b351b287 | 551 | /* Parse a source file when JCF refers to a source file. */ |
e04a16fb | 552 | |
8e1f2d4c KG |
553 | static void |
554 | jcf_parse_source () | |
e04a16fb | 555 | { |
5e942c50 | 556 | tree file; |
d19cbcb5 | 557 | FILE *finput; |
e04a16fb | 558 | |
5e942c50 APB |
559 | java_parser_context_save_global (); |
560 | java_push_parser_context (); | |
f15b9af9 | 561 | input_filename = ggc_strdup (current_jcf->filename); |
5e942c50 | 562 | file = get_identifier (input_filename); |
0ba154aa APB |
563 | current_class = NULL_TREE; |
564 | current_function_decl = NULL_TREE; | |
23a79c61 APB |
565 | if (!HAS_BEEN_ALREADY_PARSED_P (file)) |
566 | { | |
567 | if (!(finput = fopen (input_filename, "r"))) | |
568 | fatal ("input file `%s' just disappeared - jcf_parse_source", | |
569 | input_filename); | |
d19cbcb5 | 570 | parse_source_file (file, finput); |
23a79c61 APB |
571 | if (fclose (finput)) |
572 | fatal ("can't close input file `%s' stream - jcf_parse_source", | |
573 | input_filename); | |
574 | } | |
5e942c50 | 575 | java_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file)); |
e04a16fb AG |
576 | java_parser_context_restore_global (); |
577 | } | |
578 | ||
579 | /* Parse the .class file JCF. */ | |
580 | ||
1c7f3673 | 581 | void |
e04a16fb AG |
582 | jcf_parse (jcf) |
583 | JCF* jcf; | |
584 | { | |
585 | int i, code; | |
c2952b01 | 586 | tree current; |
e04a16fb AG |
587 | |
588 | if (jcf_parse_preamble (jcf) != 0) | |
589 | fatal ("Not a valid Java .class file.\n"); | |
590 | code = jcf_parse_constant_pool (jcf); | |
591 | if (code != 0) | |
592 | fatal ("error while parsing constant pool"); | |
593 | code = verify_constant_pool (jcf); | |
594 | if (code > 0) | |
595 | fatal ("error in constant pool entry #%d\n", code); | |
596 | ||
597 | jcf_parse_class (jcf); | |
598 | if (main_class == NULL_TREE) | |
599 | main_class = current_class; | |
600 | if (! quiet_flag && TYPE_NAME (current_class)) | |
48aedbca AG |
601 | fprintf (stderr, " %s %s", |
602 | (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class", | |
e04a16fb | 603 | IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); |
0b4d333e APB |
604 | if (CLASS_LOADED_P (current_class)) |
605 | return; | |
e04a16fb AG |
606 | CLASS_LOADED_P (current_class) = 1; |
607 | ||
608 | for (i = 1; i < JPOOL_SIZE(jcf); i++) | |
609 | { | |
610 | switch (JPOOL_TAG (jcf, i)) | |
611 | { | |
612 | case CONSTANT_Class: | |
613 | get_class_constant (jcf, i); | |
614 | break; | |
615 | } | |
616 | } | |
617 | ||
618 | code = jcf_parse_fields (jcf); | |
619 | if (code != 0) | |
620 | fatal ("error while parsing fields"); | |
621 | code = jcf_parse_methods (jcf); | |
622 | if (code != 0) | |
623 | fatal ("error while parsing methods"); | |
624 | code = jcf_parse_final_attributes (jcf); | |
625 | if (code != 0) | |
626 | fatal ("error while parsing final attributes"); | |
627 | ||
628 | /* The fields of class_type_node are already in correct order. */ | |
629 | if (current_class != class_type_node && current_class != object_type_node) | |
630 | TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class)); | |
631 | ||
e04a16fb | 632 | layout_class (current_class); |
23a79c61 APB |
633 | if (current_class == object_type_node) |
634 | layout_class_methods (object_type_node); | |
635 | else | |
636 | all_class_list = tree_cons (NULL_TREE, | |
637 | TYPE_NAME (current_class), all_class_list ); | |
c2952b01 APB |
638 | |
639 | /* And if we came accross inner classes, load them now. */ | |
640 | for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (current_class)); current; | |
641 | current = TREE_CHAIN (current)) | |
642 | load_class (DECL_NAME (TREE_PURPOSE (current)), 1); | |
e04a16fb AG |
643 | } |
644 | ||
645 | void | |
646 | init_outgoing_cpool () | |
647 | { | |
c2952b01 APB |
648 | current_constant_pool_data_ref = NULL_TREE; |
649 | outgoing_cpool = (struct CPool *)xmalloc (sizeof (struct CPool)); | |
650 | bzero (outgoing_cpool, sizeof (struct CPool)); | |
e04a16fb AG |
651 | } |
652 | ||
4bcde32e | 653 | static void |
e04a16fb AG |
654 | parse_class_file () |
655 | { | |
656 | tree method; | |
3b304f5b | 657 | const char *save_input_filename = input_filename; |
e04a16fb AG |
658 | int save_lineno = lineno; |
659 | ||
1886c9d8 | 660 | java_layout_seen_class_methods (); |
23a79c61 | 661 | |
e04a16fb AG |
662 | input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class)); |
663 | lineno = 0; | |
664 | debug_start_source_file (input_filename); | |
665 | init_outgoing_cpool (); | |
666 | ||
3ff9925c AG |
667 | /* Currently we always have to emit calls to _Jv_InitClass when |
668 | compiling from class files. */ | |
669 | always_initialize_class_p = 1; | |
670 | ||
e04a16fb AG |
671 | for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class)); |
672 | method != NULL_TREE; method = TREE_CHAIN (method)) | |
673 | { | |
674 | JCF *jcf = current_jcf; | |
675 | ||
7145d9fe | 676 | if (METHOD_ABSTRACT (method)) |
e04a16fb AG |
677 | continue; |
678 | ||
7145d9fe TT |
679 | if (METHOD_NATIVE (method)) |
680 | { | |
681 | if (! flag_jni) | |
682 | continue; | |
683 | DECL_MAX_LOCALS (method) | |
684 | = list_length (TYPE_ARG_TYPES (TREE_TYPE (method))); | |
685 | start_java_method (method); | |
686 | give_name_to_locals (jcf); | |
687 | expand_expr_stmt (build_jni_stub (method)); | |
688 | end_java_method (); | |
689 | continue; | |
690 | } | |
691 | ||
e04a16fb AG |
692 | if (DECL_CODE_OFFSET (method) == 0) |
693 | { | |
694 | error ("missing Code attribute"); | |
695 | continue; | |
696 | } | |
697 | ||
698 | lineno = 0; | |
699 | if (DECL_LINENUMBERS_OFFSET (method)) | |
700 | { | |
701 | register int i; | |
702 | register unsigned char *ptr; | |
703 | JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method)); | |
704 | linenumber_count = i = JCF_readu2 (jcf); | |
705 | linenumber_table = ptr = jcf->read_ptr; | |
706 | ||
707 | for (ptr += 2; --i >= 0; ptr += 4) | |
708 | { | |
709 | int line = GET_u2 (ptr); | |
710 | /* Set initial lineno lineno to smallest linenumber. | |
711 | * Needs to be set before init_function_start. */ | |
712 | if (lineno == 0 || line < lineno) | |
713 | lineno = line; | |
714 | } | |
715 | } | |
716 | else | |
717 | { | |
718 | linenumber_table = NULL; | |
719 | linenumber_count = 0; | |
720 | } | |
721 | ||
722 | start_java_method (method); | |
723 | ||
7e1cb6b6 APB |
724 | note_instructions (jcf, method); |
725 | ||
e04a16fb AG |
726 | give_name_to_locals (jcf); |
727 | ||
728 | /* Actually generate code. */ | |
729 | expand_byte_code (jcf, method); | |
730 | ||
731 | end_java_method (); | |
732 | } | |
733 | ||
734 | if (flag_emit_class_files) | |
735 | write_classfile (current_class); | |
de4c7b02 | 736 | |
d593dd8c | 737 | finish_class (); |
e04a16fb AG |
738 | |
739 | debug_end_source_file (save_lineno); | |
740 | input_filename = save_input_filename; | |
741 | lineno = save_lineno; | |
742 | } | |
743 | ||
5e942c50 | 744 | /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */ |
e04a16fb AG |
745 | |
746 | static void | |
d19cbcb5 | 747 | parse_source_file (file, finput) |
5e942c50 | 748 | tree file; |
d19cbcb5 | 749 | FILE *finput; |
e04a16fb | 750 | { |
bc3ca41b | 751 | int save_error_count = java_error_count; |
b351b287 | 752 | /* Mark the file as parsed */ |
5e942c50 | 753 | HAS_BEEN_ALREADY_PARSED_P (file) = 1; |
b351b287 | 754 | |
51ae4071 TT |
755 | jcf_dependency_add_file (input_filename, 0); |
756 | ||
e04a16fb | 757 | lang_init_source (1); /* Error msgs have no method prototypes */ |
bc3ca41b | 758 | |
d19cbcb5 TT |
759 | /* There's no point in trying to find the current encoding unless we |
760 | are going to do something intelligent with it -- hence the test | |
761 | for iconv. */ | |
762 | #ifdef HAVE_ICONV | |
763 | #ifdef HAVE_NL_LANGINFO | |
764 | setlocale (LC_CTYPE, ""); | |
765 | if (current_encoding == NULL) | |
766 | current_encoding = nl_langinfo (CODESET); | |
767 | #endif /* HAVE_NL_LANGINFO */ | |
768 | #endif /* HAVE_ICONV */ | |
769 | if (current_encoding == NULL || *current_encoding == '\0') | |
770 | current_encoding = DEFAULT_ENCODING; | |
771 | ||
772 | /* Initialize the parser */ | |
773 | java_init_lex (finput, current_encoding); | |
e04a16fb | 774 | java_parse_abort_on_error (); |
bc3ca41b | 775 | |
e04a16fb AG |
776 | java_parse (); /* Parse and build partial tree nodes. */ |
777 | java_parse_abort_on_error (); | |
778 | java_complete_class (); /* Parse unsatisfied class decl. */ | |
779 | java_parse_abort_on_error (); | |
780 | java_check_circular_reference (); /* Check on circular references */ | |
781 | java_parse_abort_on_error (); | |
e920ebc9 APB |
782 | java_fix_constructors (); /* Fix the constructors */ |
783 | java_parse_abort_on_error (); | |
c2952b01 | 784 | java_reorder_fields (); /* Reorder the fields */ |
e04a16fb AG |
785 | } |
786 | ||
5423609c APB |
787 | static int |
788 | predefined_filename_p (node) | |
789 | tree node; | |
790 | { | |
791 | int i; | |
19e223db | 792 | for (i = 0; i < PREDEF_FILENAMES_SIZE; i++) |
5423609c APB |
793 | if (predef_filenames [i] == node) |
794 | return 1; | |
795 | return 0; | |
796 | } | |
797 | ||
e04a16fb AG |
798 | int |
799 | yyparse () | |
800 | { | |
b351b287 | 801 | int several_files = 0; |
c2e3db92 | 802 | char *list = xstrdup (input_filename), *next; |
b351b287 | 803 | tree node, current_file_list = NULL_TREE; |
d19cbcb5 | 804 | FILE *finput; |
e04a16fb | 805 | |
b351b287 | 806 | do |
e04a16fb | 807 | { |
b351b287 APB |
808 | next = strchr (list, '&'); |
809 | if (next) | |
810 | { | |
811 | *next++ = '\0'; | |
812 | several_files = 1; | |
813 | } | |
814 | ||
815 | if (list[0]) | |
816 | { | |
5e1db167 | 817 | char *value; |
5423609c APB |
818 | tree id; |
819 | int twice = 0; | |
8603f9c5 | 820 | |
5e1db167 | 821 | int len = strlen (list); |
b351b287 APB |
822 | |
823 | if (*list != '/' && several_files) | |
824 | obstack_grow (&temporary_obstack, "./", 2); | |
8603f9c5 TT |
825 | |
826 | obstack_grow0 (&temporary_obstack, list, len); | |
b351b287 | 827 | value = obstack_finish (&temporary_obstack); |
5423609c APB |
828 | |
829 | /* Exclude file that we see twice on the command line. For | |
830 | all files except {Class,Error,Object,RuntimeException,String, | |
831 | Throwable}.java we can rely on maybe_get_identifier. For | |
832 | these files, we need to do a linear search of | |
833 | current_file_list. This search happens only for these | |
834 | files, presumably only when we're recompiling libgcj. */ | |
835 | ||
836 | if ((id = maybe_get_identifier (value))) | |
837 | { | |
838 | if (predefined_filename_p (id)) | |
839 | { | |
840 | tree c; | |
841 | for (c = current_file_list; c; c = TREE_CHAIN (c)) | |
842 | if (TREE_VALUE (c) == id) | |
843 | twice = 1; | |
844 | } | |
845 | else | |
846 | twice = 1; | |
847 | } | |
848 | ||
849 | if (twice) | |
850 | { | |
3b304f5b | 851 | const char *saved_input_filename = input_filename; |
5423609c | 852 | input_filename = value; |
c63b98cd | 853 | warning ("source file seen twice on command line and will be compiled only once."); |
5423609c APB |
854 | input_filename = saved_input_filename; |
855 | } | |
856 | else | |
857 | { | |
858 | node = get_identifier (value); | |
859 | IS_A_COMMAND_LINE_FILENAME_P (node) = 1; | |
860 | current_file_list = tree_cons (NULL_TREE, node, | |
861 | current_file_list); | |
862 | } | |
b351b287 APB |
863 | } |
864 | list = next; | |
865 | } | |
866 | while (next); | |
867 | ||
22eed1e6 | 868 | current_jcf = main_jcf; |
b351b287 APB |
869 | current_file_list = nreverse (current_file_list); |
870 | for (node = current_file_list; node; node = TREE_CHAIN (node)) | |
871 | { | |
22eed1e6 | 872 | tree name = TREE_VALUE (node); |
b351b287 | 873 | |
22eed1e6 APB |
874 | /* Skip already parsed files */ |
875 | if (HAS_BEEN_ALREADY_PARSED_P (name)) | |
876 | continue; | |
877 | ||
878 | /* Close previous descriptor, if any */ | |
879 | if (main_jcf->read_state && fclose (main_jcf->read_state)) | |
880 | fatal ("failed to close input file `%s' - yyparse", | |
881 | (main_jcf->filename ? main_jcf->filename : "<unknown>")); | |
882 | ||
883 | /* Set jcf up and open a new file */ | |
884 | JCF_ZERO (main_jcf); | |
1c7f3673 | 885 | main_jcf->read_state = fopen (IDENTIFIER_POINTER (name), "rb"); |
22eed1e6 APB |
886 | if (main_jcf->read_state == NULL) |
887 | pfatal_with_name (IDENTIFIER_POINTER (name)); | |
888 | ||
889 | /* Set new input_filename and finput */ | |
890 | finput = main_jcf->read_state; | |
891 | #ifdef IO_BUFFER_SIZE | |
892 | setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), | |
893 | _IOFBF, IO_BUFFER_SIZE); | |
894 | #endif | |
895 | input_filename = IDENTIFIER_POINTER (name); | |
896 | main_jcf->filbuf = jcf_filbuf_from_stdio; | |
b351b287 APB |
897 | |
898 | switch (jcf_figure_file_type (current_jcf)) | |
899 | { | |
900 | case JCF_ZIP: | |
901 | parse_zip_file_entries (); | |
b351b287 APB |
902 | break; |
903 | case JCF_CLASS: | |
904 | jcf_parse (current_jcf); | |
905 | parse_class_file (); | |
b351b287 APB |
906 | break; |
907 | case JCF_SOURCE: | |
5e942c50 APB |
908 | java_push_parser_context (); |
909 | java_parser_context_save_global (); | |
d19cbcb5 | 910 | parse_source_file (name, finput); |
5e942c50 APB |
911 | java_parser_context_restore_global (); |
912 | java_pop_parser_context (1); | |
b351b287 APB |
913 | break; |
914 | } | |
e04a16fb | 915 | } |
c877974e | 916 | |
b351b287 | 917 | java_expand_classes (); |
66b48140 | 918 | if (!java_report_errors () && !flag_syntax_only) |
866e9df8 | 919 | emit_register_classes (); |
e04a16fb AG |
920 | return 0; |
921 | } | |
922 | ||
923 | static struct ZipFileCache *localToFile; | |
924 | ||
925 | /* Process all class entries found in the zip file. */ | |
4bcde32e | 926 | static void |
e04a16fb AG |
927 | parse_zip_file_entries (void) |
928 | { | |
929 | struct ZipDirectory *zdir; | |
930 | int i; | |
931 | ||
932 | for (i = 0, zdir = (ZipDirectory *)localToFile->z.central_directory; | |
933 | i < localToFile->z.count; i++, zdir = ZIPDIR_NEXT (zdir)) | |
934 | { | |
935 | tree class; | |
936 | ||
937 | /* We don't need to consider those files. */ | |
938 | if (!zdir->size || !zdir->filename_offset) | |
939 | continue; | |
940 | ||
941 | class = lookup_class (get_identifier (ZIPDIR_FILENAME (zdir))); | |
c2952b01 | 942 | current_jcf = TYPE_JCF (class); |
e04a16fb AG |
943 | current_class = class; |
944 | ||
945 | if ( !CLASS_LOADED_P (class)) | |
946 | { | |
947 | fseek (current_jcf->read_state, current_jcf->zip_offset, SEEK_SET); | |
948 | jcf_parse (current_jcf); | |
949 | } | |
950 | ||
22eed1e6 APB |
951 | if (TYPE_SIZE (current_class) != error_mark_node) |
952 | { | |
953 | input_filename = current_jcf->filename; | |
954 | parse_class_file (); | |
955 | FREE (current_jcf->buffer); /* No longer necessary */ | |
956 | /* Note: there is a way to free this buffer right after a | |
957 | class seen in a zip file has been parsed. The idea is the | |
958 | set its jcf in such a way that buffer will be reallocated | |
959 | the time the code for the class will be generated. FIXME. */ | |
960 | } | |
e04a16fb AG |
961 | } |
962 | } | |
963 | ||
964 | /* Read all the entries of the zip file, creates a class and a JCF. Sets the | |
965 | jcf up for further processing and link it to the created class. */ | |
966 | ||
4bcde32e | 967 | static void process_zip_dir() |
e04a16fb AG |
968 | { |
969 | int i; | |
970 | ZipDirectory *zdir; | |
971 | ||
972 | for (i = 0, zdir = (ZipDirectory *)localToFile->z.central_directory; | |
973 | i < localToFile->z.count; i++, zdir = ZIPDIR_NEXT (zdir)) | |
974 | { | |
975 | char *class_name, *file_name, *class_name_in_zip_dir; | |
976 | tree class; | |
977 | JCF *jcf; | |
978 | int j; | |
979 | ||
980 | class_name_in_zip_dir = ZIPDIR_FILENAME (zdir); | |
981 | ||
982 | /* We choose to not to process entries with a zero size or entries | |
983 | not bearing the .class extention. */ | |
984 | if (!zdir->size || !zdir->filename_offset || | |
985 | strncmp (&class_name_in_zip_dir[zdir->filename_length-6], | |
986 | ".class", 6)) | |
987 | { | |
988 | /* So it will be skipped in parse_zip_file_entries */ | |
989 | zdir->size = 0; | |
990 | continue; | |
991 | } | |
992 | ||
993 | class_name = ALLOC (zdir->filename_length+1-6); | |
994 | file_name = ALLOC (zdir->filename_length+1); | |
995 | jcf = ALLOC (sizeof (JCF)); | |
996 | JCF_ZERO (jcf); | |
997 | ||
998 | strncpy (class_name, class_name_in_zip_dir, zdir->filename_length-6); | |
999 | class_name [zdir->filename_length-6] = '\0'; | |
1000 | strncpy (file_name, class_name_in_zip_dir, zdir->filename_length); | |
1001 | file_name [zdir->filename_length] = '\0'; | |
1002 | ||
1003 | for (j=0; class_name[j]; j++) | |
1004 | class_name [j] = (class_name [j] == '/' ? '.' : class_name [j]); | |
1005 | ||
1006 | /* Yes, we write back the true class name into the zip directory. */ | |
1007 | strcpy (class_name_in_zip_dir, class_name); | |
1008 | zdir->filename_length = j; | |
1009 | class = lookup_class (get_identifier (class_name)); | |
1010 | ||
1011 | jcf->read_state = finput; | |
1012 | jcf->filbuf = jcf_filbuf_from_stdio; | |
1013 | jcf->seen_in_zip = 1; | |
1014 | jcf->java_source = 0; | |
1015 | jcf->zip_offset = zdir->filestart; | |
1016 | jcf->classname = class_name; | |
1017 | jcf->filename = file_name; | |
1018 | ||
c2952b01 | 1019 | TYPE_JCF (class) = jcf; |
e04a16fb AG |
1020 | } |
1021 | } | |
1022 | ||
1023 | /* Lookup class NAME and figure whether is a class already found in the current | |
1024 | zip file. */ | |
4bcde32e | 1025 | static int |
e04a16fb | 1026 | DEFUN(find_in_current_zip, (name, length, jcf), |
c8e7d2e6 | 1027 | const char *name AND JCF **jcf) |
e04a16fb AG |
1028 | { |
1029 | JCF *local_jcf; | |
1030 | tree class_name = maybe_get_identifier (name), class, icv; | |
1031 | ||
1032 | if (!class_name) | |
1033 | return 0; | |
1034 | ||
1035 | if (!(icv = IDENTIFIER_CLASS_VALUE (class_name))) | |
1036 | return 0; | |
1037 | ||
1038 | class = TREE_TYPE (icv); | |
1039 | ||
1040 | /* Doesn't have jcf specific info ? It's not ours */ | |
c2952b01 | 1041 | if (!TYPE_JCF (class)) |
e04a16fb AG |
1042 | return 0; |
1043 | ||
c2952b01 | 1044 | *jcf = local_jcf = TYPE_JCF (class); |
e04a16fb AG |
1045 | fseek (local_jcf->read_state, local_jcf->zip_offset, SEEK_SET); |
1046 | return 1; | |
1047 | } | |
1048 | ||
1049 | /* Figure what kind of file we're dealing with */ | |
8e1f2d4c | 1050 | static int |
e04a16fb AG |
1051 | DEFUN(jcf_figure_file_type, (jcf), |
1052 | JCF *jcf) | |
1053 | { | |
1054 | unsigned char magic_string[4]; | |
1055 | uint32 magic; | |
1056 | ||
1057 | if (fread (magic_string, 1, 4, jcf->read_state) != 4) | |
1058 | jcf_unexpected_eof (jcf, 4); | |
1059 | ||
1060 | fseek (jcf->read_state, 0L, SEEK_SET); | |
1061 | magic = GET_u4 (magic_string); | |
1062 | ||
1063 | if (magic == 0xcafebabe) | |
1064 | return JCF_CLASS; | |
1065 | ||
8603f9c5 | 1066 | /* FIXME: is it a system file? */ |
63a212ed PB |
1067 | if (magic == (JCF_u4)ZIPMAGIC |
1068 | && !open_in_zip (jcf, input_filename, NULL, 0)) | |
e04a16fb AG |
1069 | { |
1070 | localToFile = ALLOC (sizeof (struct ZipFileCache)); | |
4504ead1 | 1071 | bcopy ((PTR) SeenZipFiles, (PTR) localToFile, sizeof (struct ZipFileCache)); |
e04a16fb AG |
1072 | process_zip_dir (); /* Register all the class defined there */ |
1073 | return JCF_ZIP; | |
1074 | } | |
1075 | ||
1076 | return JCF_SOURCE; | |
1077 | } | |
1078 | ||
19e223db MM |
1079 | /* Initialization. */ |
1080 | ||
1081 | void | |
1082 | init_jcf_parse () | |
1083 | { | |
1084 | /* Register roots with the garbage collector. */ | |
1085 | ggc_add_tree_root (¤t_field, 1); | |
1086 | ggc_add_tree_root (¤t_method, 1); | |
1087 | } |