Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / java / jcf-parse.c
blob3a4c780e77a30adb83a5ca225fa6e0930142262e
1 /* Parser for Java(TM) .class files.
2 Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Java and all Java-based marks are trademarks or registered trademarks
23 of Sun Microsystems, Inc. in the United States and other countries.
24 The Free Software Foundation is independent of Sun Microsystems, Inc. */
26 /* Written by Per Bothner <bothner@cygnus.com> */
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "tree.h"
33 #include "real.h"
34 #include "obstack.h"
35 #include "flags.h"
36 #include "java-except.h"
37 #include "input.h"
38 #include "java-tree.h"
39 #include "toplev.h"
40 #include "parse.h"
41 #include "ggc.h"
42 #include "debug.h"
43 #include "assert.h"
44 #include "tm_p.h"
45 #include "cgraph.h"
47 #ifdef HAVE_LOCALE_H
48 #include <locale.h>
49 #endif
51 #ifdef HAVE_LANGINFO_CODESET
52 #include <langinfo.h>
53 #endif
55 /* A CONSTANT_Utf8 element is converted to an IDENTIFIER_NODE at parse time. */
56 #define JPOOL_UTF(JCF, INDEX) CPOOL_UTF(&(JCF)->cpool, INDEX)
57 #define JPOOL_UTF_LENGTH(JCF, INDEX) IDENTIFIER_LENGTH (JPOOL_UTF (JCF, INDEX))
58 #define JPOOL_UTF_DATA(JCF, INDEX) \
59 ((const unsigned char *) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX)))
60 #define HANDLE_CONSTANT_Utf8(JCF, INDEX, LENGTH) \
61 do { \
62 unsigned char save; unsigned char *text; \
63 JCF_FILL (JCF, (LENGTH)+1); /* Make sure we read 1 byte beyond string. */ \
64 text = (JCF)->read_ptr; \
65 save = text[LENGTH]; \
66 text[LENGTH] = 0; \
67 (JCF)->cpool.data[INDEX].t = get_identifier ((const char *) text); \
68 text[LENGTH] = save; \
69 JCF_SKIP (JCF, LENGTH); } while (0)
71 #include "jcf.h"
73 extern struct obstack temporary_obstack;
75 static GTY(()) tree parse_roots[3];
77 /* The FIELD_DECL for the current field. */
78 #define current_field parse_roots[0]
80 /* The METHOD_DECL for the current method. */
81 #define current_method parse_roots[1]
83 /* A list of TRANSLATION_UNIT_DECLs for the files to be compiled. */
84 #define current_file_list parse_roots[2]
86 /* Line 0 in current file, if compiling from bytecode. */
87 static location_t file_start_location;
89 /* The Java archive that provides main_class; the main input file. */
90 static GTY(()) struct JCF * main_jcf;
92 static struct ZipFile *localToFile;
94 /* Declarations of some functions used here. */
95 static void handle_innerclass_attribute (int count, JCF *);
96 static tree give_name_to_class (JCF *jcf, int index);
97 static char *compute_class_name (struct ZipDirectory *zdir);
98 static int classify_zip_file (struct ZipDirectory *zdir);
99 static void parse_zip_file_entries (void);
100 static void process_zip_dir (FILE *);
101 static void parse_source_file_1 (tree, const char *, FILE *);
102 static void parse_source_file_2 (void);
103 static void parse_source_file_3 (void);
104 static void parse_class_file (void);
105 static void handle_deprecated (void);
106 static void set_source_filename (JCF *, int);
107 static void jcf_parse (struct JCF*);
108 static void load_inner_classes (tree);
110 /* Handle "Deprecated" attribute. */
111 static void
112 handle_deprecated (void)
114 if (current_field != NULL_TREE)
115 FIELD_DEPRECATED (current_field) = 1;
116 else if (current_method != NULL_TREE)
117 METHOD_DEPRECATED (current_method) = 1;
118 else if (current_class != NULL_TREE)
119 CLASS_DEPRECATED (TYPE_NAME (current_class)) = 1;
120 else
122 /* Shouldn't happen. */
123 abort ();
127 /* Handle "SourceFile" attribute. */
129 static void
130 set_source_filename (JCF *jcf, int index)
132 tree sfname_id = get_name_constant (jcf, index);
133 const char *sfname = IDENTIFIER_POINTER (sfname_id);
134 const char *old_filename = input_filename;
135 int new_len = IDENTIFIER_LENGTH (sfname_id);
136 if (old_filename != NULL)
138 int old_len = strlen (old_filename);
139 /* Use the current input_filename (derived from the class name)
140 if it has a directory prefix, but otherwise matches sfname. */
141 if (old_len > new_len
142 && strcmp (sfname, old_filename + old_len - new_len) == 0
143 && (old_filename[old_len - new_len - 1] == '/'
144 || old_filename[old_len - new_len - 1] == '\\'))
145 return;
147 if (strchr (sfname, '/') == NULL && strchr (sfname, '\\') == NULL)
149 const char *class_name
150 = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
151 char *dot = strrchr (class_name, '.');
152 if (dot != NULL)
154 /* Length of prefix, not counting final dot. */
155 int i = dot - class_name;
156 /* Concatenate current package prefix with new sfname. */
157 char *buf = xmalloc (i + new_len + 2); /* Space for '.' and '\0'. */
158 strcpy (buf + i + 1, sfname);
159 /* Copy package from class_name, replacing '.' by DIR_SEPARATOR.
160 Note we start at the end with the final package dot. */
161 for (; i >= 0; i--)
163 char c = class_name[i];
164 if (c == '.')
165 c = DIR_SEPARATOR;
166 buf[i] = c;
168 sfname_id = get_identifier (buf);
169 free (buf);
170 sfname = IDENTIFIER_POINTER (sfname_id);
174 #ifdef USE_MAPPED_LOCATION
175 line_table.maps[line_table.used-1].to_file = sfname;
176 #else
177 input_filename = sfname;
178 DECL_SOURCE_LOCATION (TYPE_NAME (current_class)) = input_location;
179 file_start_location = input_location;
180 #endif
181 if (current_class == main_class) main_input_filename = sfname;
184 #define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)
186 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
187 { tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
188 output_class = current_class = give_name_to_class (jcf, THIS); \
189 set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
191 #define HANDLE_CLASS_INTERFACE(INDEX) \
192 add_interface (current_class, get_class_constant (jcf, INDEX))
194 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
195 { int sig_index = SIGNATURE; \
196 current_field = add_field (current_class, get_name_constant (jcf, NAME), \
197 parse_signature (jcf, sig_index), ACCESS_FLAGS); \
198 set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); \
199 if ((ACCESS_FLAGS) & ACC_FINAL) \
200 MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (current_field); \
203 #define HANDLE_END_FIELDS() \
204 (current_field = NULL_TREE)
206 #define HANDLE_CONSTANTVALUE(INDEX) \
207 { tree constant; int index = INDEX; \
208 if (! flag_emit_class_files && JPOOL_TAG (jcf, index) == CONSTANT_String) { \
209 tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \
210 constant = build_utf8_ref (name); \
212 else \
213 constant = get_constant (jcf, index); \
214 set_constant_value (current_field, constant); }
216 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
217 (current_method = add_method (current_class, ACCESS_FLAGS, \
218 get_name_constant (jcf, NAME), \
219 get_name_constant (jcf, SIGNATURE)), \
220 DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \
221 DECL_LINENUMBERS_OFFSET (current_method) = 0)
223 #define HANDLE_END_METHODS() \
224 { current_method = NULL_TREE; }
226 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
227 { DECL_MAX_STACK (current_method) = (MAX_STACK); \
228 DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \
229 DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \
230 DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); }
232 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
233 { int n = (COUNT); \
234 DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
235 JCF_SKIP (jcf, n * 10); }
237 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
238 { int n = (COUNT); \
239 DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
240 JCF_SKIP (jcf, n * 4); }
242 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
244 int n = COUNT; \
245 tree list = DECL_FUNCTION_THROWS (current_method); \
246 while (--n >= 0) \
248 tree thrown_class = get_class_constant (jcf, JCF_readu2 (jcf)); \
249 list = tree_cons (NULL_TREE, thrown_class, list); \
251 DECL_FUNCTION_THROWS (current_method) = nreverse (list); \
254 #define HANDLE_DEPRECATED_ATTRIBUTE() handle_deprecated ()
256 /* Link seen inner classes to their outer context and register the
257 inner class to its outer context. They will be later loaded. */
258 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
259 handle_innerclass_attribute (COUNT, jcf)
261 #define HANDLE_SYNTHETIC_ATTRIBUTE() \
263 /* Irrelevant decls should have been nullified by the END macros. \
264 We only handle the `Synthetic' attribute on method DECLs. \
265 DECL_ARTIFICIAL on fields is used for something else (See \
266 PUSH_FIELD in java-tree.h) */ \
267 if (current_method) \
268 DECL_ARTIFICIAL (current_method) = 1; \
271 #define HANDLE_GCJCOMPILED_ATTRIBUTE() \
273 if (current_class == object_type_node) \
274 jcf->right_zip = 1; \
277 #include "jcf-reader.c"
279 tree
280 parse_signature (JCF *jcf, int sig_index)
282 if (sig_index <= 0 || sig_index >= JPOOL_SIZE (jcf)
283 || JPOOL_TAG (jcf, sig_index) != CONSTANT_Utf8)
284 abort ();
285 else
286 return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index),
287 JPOOL_UTF_LENGTH (jcf, sig_index));
290 tree
291 get_constant (JCF *jcf, int index)
293 tree value;
294 int tag;
295 if (index <= 0 || index >= JPOOL_SIZE(jcf))
296 goto bad;
297 tag = JPOOL_TAG (jcf, index);
298 if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
299 return jcf->cpool.data[index].t;
300 switch (tag)
302 case CONSTANT_Integer:
304 jint num = JPOOL_INT(jcf, index);
305 value = build_int_cst (int_type_node, num);
306 break;
308 case CONSTANT_Long:
310 unsigned HOST_WIDE_INT num = JPOOL_UINT (jcf, index);
311 unsigned HOST_WIDE_INT lo;
312 HOST_WIDE_INT hi;
314 lshift_double (num, 0, 32, 64, &lo, &hi, 0);
315 num = JPOOL_UINT (jcf, index+1);
316 add_double (lo, hi, num, 0, &lo, &hi);
317 value = build_int_cst_wide (long_type_node, lo, hi);
318 value = force_fit_type (value, 0, false, false);
319 break;
322 case CONSTANT_Float:
324 jint num = JPOOL_INT(jcf, index);
325 long buf = num;
326 REAL_VALUE_TYPE d;
328 real_from_target_fmt (&d, &buf, &ieee_single_format);
329 value = build_real (float_type_node, d);
330 break;
333 case CONSTANT_Double:
335 long buf[2], lo, hi;
336 REAL_VALUE_TYPE d;
338 hi = JPOOL_UINT (jcf, index);
339 lo = JPOOL_UINT (jcf, index+1);
341 if (FLOAT_WORDS_BIG_ENDIAN)
342 buf[0] = hi, buf[1] = lo;
343 else
344 buf[0] = lo, buf[1] = hi;
346 real_from_target_fmt (&d, buf, &ieee_double_format);
347 value = build_real (double_type_node, d);
348 break;
351 case CONSTANT_String:
353 tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
354 const char *utf8_ptr = IDENTIFIER_POINTER (name);
355 int utf8_len = IDENTIFIER_LENGTH (name);
356 const unsigned char *utf8;
357 int i;
359 /* Check for a malformed Utf8 string. */
360 utf8 = (const unsigned char *) utf8_ptr;
361 i = utf8_len;
362 while (i > 0)
364 int char_len = UT8_CHAR_LENGTH (*utf8);
365 if (char_len < 0 || char_len > 3 || char_len > i)
366 fatal_error ("bad string constant");
368 utf8 += char_len;
369 i -= char_len;
372 /* Allocate a new string value. */
373 value = build_string (utf8_len, utf8_ptr);
374 TREE_TYPE (value) = build_pointer_type (string_type_node);
376 break;
377 default:
378 goto bad;
380 JPOOL_TAG (jcf, index) = tag | CONSTANT_ResolvedFlag;
381 jcf->cpool.data[index].t = value;
382 return value;
383 bad:
384 internal_error ("bad value constant type %d, index %d",
385 JPOOL_TAG (jcf, index), index);
388 tree
389 get_name_constant (JCF *jcf, int index)
391 tree name = get_constant (jcf, index);
393 if (TREE_CODE (name) != IDENTIFIER_NODE)
394 abort ();
396 return name;
399 /* Handle reading innerclass attributes. If a nonzero entry (denoting
400 a non anonymous entry) is found, We augment the inner class list of
401 the outer context with the newly resolved innerclass. */
403 static void
404 handle_innerclass_attribute (int count, JCF *jcf)
406 int c = (count);
407 while (c--)
409 /* Read inner_class_info_index. This may be 0 */
410 int icii = JCF_readu2 (jcf);
411 /* Read outer_class_info_index. If the innerclasses attribute
412 entry isn't a member (like an inner class) the value is 0. */
413 int ocii = JCF_readu2 (jcf);
414 /* Read inner_name_index. If the class we're dealing with is
415 an anonymous class, it must be 0. */
416 int ini = JCF_readu2 (jcf);
417 /* Read the access flag. */
418 int acc = JCF_readu2 (jcf);
419 /* If icii is 0, don't try to read the class. */
420 if (icii >= 0)
422 tree class = get_class_constant (jcf, icii);
423 tree decl = TYPE_NAME (class);
424 /* Skip reading further if ocii is null */
425 if (DECL_P (decl) && !CLASS_COMPLETE_P (decl) && ocii)
427 tree outer = TYPE_NAME (get_class_constant (jcf, ocii));
428 tree alias = (ini ? get_name_constant (jcf, ini) : NULL_TREE);
429 set_class_decl_access_flags (acc, decl);
430 DECL_CONTEXT (decl) = outer;
431 DECL_INNER_CLASS_LIST (outer) =
432 tree_cons (decl, alias, DECL_INNER_CLASS_LIST (outer));
433 CLASS_COMPLETE_P (decl) = 1;
439 static tree
440 give_name_to_class (JCF *jcf, int i)
442 if (i <= 0 || i >= JPOOL_SIZE (jcf)
443 || JPOOL_TAG (jcf, i) != CONSTANT_Class)
444 abort ();
445 else
447 tree this_class;
448 int j = JPOOL_USHORT1 (jcf, i);
449 /* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */
450 tree class_name = unmangle_classname ((const char *) JPOOL_UTF_DATA (jcf, j),
451 JPOOL_UTF_LENGTH (jcf, j));
452 this_class = lookup_class (class_name);
453 #ifdef USE_MAPPED_LOCATION
455 tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
456 const char *sfname = IDENTIFIER_POINTER (source_name);
457 linemap_add (&line_table, LC_ENTER, false, sfname, 0);
458 input_location = linemap_line_start (&line_table, 0, 1);
459 file_start_location = input_location;
460 DECL_SOURCE_LOCATION (TYPE_NAME (this_class)) = input_location;
461 if (main_input_filename == NULL && jcf == main_jcf)
462 main_input_filename = sfname;
464 #else
465 input_location = DECL_SOURCE_LOCATION (TYPE_NAME (this_class));
466 if (main_input_filename == NULL && jcf == main_jcf)
467 main_input_filename = input_filename;
468 #endif
470 jcf->cpool.data[i].t = this_class;
471 JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
472 return this_class;
476 /* Get the class of the CONSTANT_Class whose constant pool index is I. */
478 tree
479 get_class_constant (JCF *jcf, int i)
481 tree type;
482 if (i <= 0 || i >= JPOOL_SIZE (jcf)
483 || (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) != CONSTANT_Class)
484 abort ();
486 if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)
488 int name_index = JPOOL_USHORT1 (jcf, i);
489 /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */
490 const char *name = (const char *) JPOOL_UTF_DATA (jcf, name_index);
491 int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
493 if (name[0] == '[') /* Handle array "classes". */
494 type = TREE_TYPE (parse_signature_string ((const unsigned char *) name, nlength));
495 else
497 tree cname = unmangle_classname (name, nlength);
498 type = lookup_class (cname);
500 jcf->cpool.data[i].t = type;
501 JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
503 else
504 type = jcf->cpool.data[i].t;
505 return type;
508 /* Read a class with the fully qualified-name NAME.
509 Return 1 iff we read the requested file.
510 (It is still possible we failed if the file did not
511 define the class it is supposed to.) */
514 read_class (tree name)
516 JCF this_jcf, *jcf;
517 tree icv, class = NULL_TREE;
518 tree save_current_class = current_class;
519 tree save_output_class = output_class;
520 location_t save_location = input_location;
521 JCF *save_current_jcf = current_jcf;
523 if ((icv = IDENTIFIER_CLASS_VALUE (name)) != NULL_TREE)
525 class = TREE_TYPE (icv);
526 jcf = TYPE_JCF (class);
528 else
529 jcf = NULL;
531 if (jcf == NULL)
533 const char* path_name;
534 this_jcf.zipd = NULL;
535 jcf = &this_jcf;
537 path_name = find_class (IDENTIFIER_POINTER (name),
538 IDENTIFIER_LENGTH (name),
539 &this_jcf, 1);
540 if (path_name == 0)
541 return 0;
542 else
543 free((char *) path_name);
546 current_jcf = jcf;
548 if (current_jcf->java_source)
550 const char *filename = current_jcf->filename;
551 char *real_path;
552 tree given_file, real_file;
553 FILE *finput;
554 int generate;
556 java_parser_context_save_global ();
557 java_push_parser_context ();
559 given_file = get_identifier (filename);
560 filename = IDENTIFIER_POINTER (given_file);
561 real_path = lrealpath (filename);
562 real_file = get_identifier (real_path);
563 free (real_path);
565 generate = IS_A_COMMAND_LINE_FILENAME_P (given_file);
566 output_class = current_class = NULL_TREE;
567 current_function_decl = NULL_TREE;
569 if (! HAS_BEEN_ALREADY_PARSED_P (real_file))
571 if (! (finput = fopen (filename, "r")))
572 fatal_error ("can't reopen %s: %m", filename);
574 parse_source_file_1 (real_file, filename, finput);
575 parse_source_file_2 ();
576 parse_source_file_3 ();
578 if (fclose (finput))
579 fatal_error ("can't close %s: %m", input_filename);
580 #ifdef USE_MAPPED_LOCATION
581 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
582 #endif
584 JCF_FINISH (current_jcf);
585 java_pop_parser_context (generate);
586 java_parser_context_restore_global ();
588 else
590 if (class == NULL_TREE || ! CLASS_PARSED_P (class))
592 java_parser_context_save_global ();
593 java_push_parser_context ();
594 output_class = current_class = class;
595 ctxp->save_location = input_location;
596 if (JCF_SEEN_IN_ZIP (current_jcf))
597 read_zip_member(current_jcf,
598 current_jcf->zipd, current_jcf->zipd->zipf);
599 jcf_parse (current_jcf);
600 /* Parsing might change the class, in which case we have to
601 put it back where we found it. */
602 if (current_class != class && icv != NULL_TREE)
603 TREE_TYPE (icv) = current_class;
604 class = current_class;
605 java_pop_parser_context (0);
606 java_parser_context_restore_global ();
608 layout_class (class);
609 load_inner_classes (class);
612 output_class = save_output_class;
613 current_class = save_current_class;
614 input_location = save_location;
615 current_jcf = save_current_jcf;
616 return 1;
619 /* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if
620 called from the parser, otherwise it's a RECORD_TYPE node. If
621 VERBOSE is 1, print error message on failure to load a class. */
622 void
623 load_class (tree class_or_name, int verbose)
625 tree name, saved;
626 int class_loaded = 0;
627 tree class_decl = NULL_TREE;
628 bool is_compiled_class = false;
630 /* We've already failed, don't try again. */
631 if (TREE_CODE (class_or_name) == RECORD_TYPE
632 && TYPE_DUMMY (class_or_name))
633 return;
635 /* class_or_name can be the name of the class we want to load */
636 if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
637 name = class_or_name;
638 /* In some cases, it's a dependency that we process earlier that
639 we though */
640 else if (TREE_CODE (class_or_name) == TREE_LIST)
641 name = TYPE_NAME (TREE_PURPOSE (class_or_name));
642 /* Or it's a type in the making */
643 else
644 name = DECL_NAME (TYPE_NAME (class_or_name));
646 class_decl = IDENTIFIER_CLASS_VALUE (name);
647 if (class_decl != NULL_TREE)
649 tree type = TREE_TYPE (class_decl);
650 is_compiled_class
651 = ((TYPE_JCF (type) && JCF_SEEN_IN_ZIP (TYPE_JCF (type)))
652 || CLASS_FROM_CURRENTLY_COMPILED_P (type));
655 /* If the class is from source code, then it must already be loaded. */
656 class_decl = IDENTIFIER_CLASS_VALUE (name);
657 if (class_decl && CLASS_FROM_SOURCE_P (TREE_TYPE (class_decl)))
658 return;
660 saved = name;
662 /* If flag_verify_invocations is unset, we don't try to load a class
663 unless we're looking for Object (which is fixed by the ABI) or
664 it's a class that we're going to compile. */
665 if (flag_verify_invocations
666 || class_or_name == object_type_node
667 || is_compiled_class
668 || TREE_CODE (class_or_name) == IDENTIFIER_NODE)
670 while (1)
672 char *separator;
674 /* We've already loaded it. */
675 if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE)
677 tree tmp_decl = IDENTIFIER_CLASS_VALUE (name);
678 if (CLASS_PARSED_P (TREE_TYPE (tmp_decl)))
679 break;
682 if (read_class (name))
683 break;
685 /* We failed loading name. Now consider that we might be looking
686 for a inner class. */
687 if ((separator = strrchr (IDENTIFIER_POINTER (name), '$'))
688 || (separator = strrchr (IDENTIFIER_POINTER (name), '.')))
690 int c = *separator;
691 *separator = '\0';
692 name = get_identifier (IDENTIFIER_POINTER (name));
693 *separator = c;
695 /* Otherwise, we failed, we bail. */
696 else
697 break;
701 /* have we found the class we're looking for? */
702 tree type_decl = IDENTIFIER_CLASS_VALUE (saved);
703 tree type = type_decl ? TREE_TYPE (type_decl) : NULL;
704 class_loaded = type && CLASS_PARSED_P (type);
708 if (!class_loaded)
710 if (flag_verify_invocations || ! flag_indirect_dispatch
711 || flag_emit_class_files)
713 if (verbose)
714 error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
716 else if (verbose)
718 /* This is just a diagnostic during testing, not a real problem. */
719 if (!quiet_flag)
720 warning("cannot find file for class %s",
721 IDENTIFIER_POINTER (saved));
723 /* Fake it. */
724 if (TREE_CODE (class_or_name) == RECORD_TYPE)
726 set_super_info (0, class_or_name, object_type_node, 0);
727 TYPE_DUMMY (class_or_name) = 1;
728 /* We won't be able to output any debug info for this class. */
729 DECL_IGNORED_P (TYPE_NAME (class_or_name)) = 1;
735 /* Parse the .class file JCF. */
737 static void
738 jcf_parse (JCF* jcf)
740 int i, code;
742 if (jcf_parse_preamble (jcf) != 0)
743 fatal_error ("not a valid Java .class file");
744 code = jcf_parse_constant_pool (jcf);
745 if (code != 0)
746 fatal_error ("error while parsing constant pool");
747 code = verify_constant_pool (jcf);
748 if (code > 0)
749 fatal_error ("error in constant pool entry #%d\n", code);
751 jcf_parse_class (jcf);
752 if (main_class == NULL_TREE)
753 main_class = current_class;
754 if (! quiet_flag && TYPE_NAME (current_class))
755 fprintf (stderr, " %s %s",
756 (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class",
757 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
758 if (CLASS_PARSED_P (current_class))
760 /* FIXME - where was first time */
761 fatal_error ("reading class %s for the second time from %s",
762 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))),
763 jcf->filename);
765 CLASS_PARSED_P (current_class) = 1;
767 for (i = 1; i < JPOOL_SIZE(jcf); i++)
769 switch (JPOOL_TAG (jcf, i))
771 case CONSTANT_Class:
772 get_class_constant (jcf, i);
773 break;
777 code = jcf_parse_fields (jcf);
778 if (code != 0)
779 fatal_error ("error while parsing fields");
780 code = jcf_parse_methods (jcf);
781 if (code != 0)
782 fatal_error ("error while parsing methods");
783 code = jcf_parse_final_attributes (jcf);
784 if (code != 0)
785 fatal_error ("error while parsing final attributes");
786 #ifdef USE_MAPPED_LOCATION
787 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
788 #endif
790 /* The fields of class_type_node are already in correct order. */
791 if (current_class != class_type_node && current_class != object_type_node)
792 TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));
794 if (current_class == object_type_node)
796 layout_class_methods (object_type_node);
797 /* If we don't have the right archive, emit a verbose warning.
798 If we're generating bytecode, emit the warning only if
799 -fforce-classes-archive-check was specified. */
800 if (!jcf->right_zip
801 && (!flag_emit_class_files || flag_force_classes_archive_check))
802 fatal_error ("the %<java.lang.Object%> that was found in %qs didn't have the special zero-length %<gnu.gcj.gcj-compiled%> attribute. This generally means that your classpath is incorrectly set. Use %<info gcj \"Input Options\"%> to see the info page describing how to set the classpath", jcf->filename);
804 else
805 all_class_list = tree_cons (NULL_TREE,
806 TYPE_NAME (current_class), all_class_list );
809 /* If we came across inner classes, load them now. */
810 static void
811 load_inner_classes (tree cur_class)
813 tree current;
814 for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (cur_class)); current;
815 current = TREE_CHAIN (current))
817 tree name = DECL_NAME (TREE_PURPOSE (current));
818 tree decl = IDENTIFIER_GLOBAL_VALUE (name);
819 if (decl && ! CLASS_LOADED_P (TREE_TYPE (decl))
820 && !CLASS_BEING_LAIDOUT (TREE_TYPE (decl)))
821 load_class (name, 1);
825 static void
826 parse_class_file (void)
828 tree method;
829 location_t save_location = input_location;
831 java_layout_seen_class_methods ();
833 input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class));
834 file_start_location = input_location;
835 (*debug_hooks->start_source_file) (input_line, input_filename);
837 gen_indirect_dispatch_tables (current_class);
839 java_mark_class_local (current_class);
841 for (method = TYPE_METHODS (current_class);
842 method != NULL_TREE; method = TREE_CHAIN (method))
844 JCF *jcf = current_jcf;
846 if (METHOD_ABSTRACT (method) || METHOD_DUMMY (method))
847 continue;
849 if (METHOD_NATIVE (method))
851 tree arg;
852 int decl_max_locals;
854 if (! flag_jni)
855 continue;
856 /* We need to compute the DECL_MAX_LOCALS. We need to take
857 the wide types into account too. */
858 for (arg = TYPE_ARG_TYPES (TREE_TYPE (method)), decl_max_locals = 0;
859 arg != end_params_node;
860 arg = TREE_CHAIN (arg), decl_max_locals += 1)
862 if (TREE_VALUE (arg) && TYPE_IS_WIDE (TREE_VALUE (arg)))
863 decl_max_locals += 1;
865 DECL_MAX_LOCALS (method) = decl_max_locals;
866 start_java_method (method);
867 give_name_to_locals (jcf);
868 *get_stmts () = build_jni_stub (method);
869 end_java_method ();
870 continue;
873 if (DECL_CODE_OFFSET (method) == 0)
875 current_function_decl = method;
876 error ("missing Code attribute");
877 continue;
880 input_location = file_start_location;
881 if (DECL_LINENUMBERS_OFFSET (method))
883 int i;
884 int min_line = 0;
885 unsigned char *ptr;
886 JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method));
887 linenumber_count = i = JCF_readu2 (jcf);
888 linenumber_table = ptr = jcf->read_ptr;
890 for (ptr += 2; --i >= 0; ptr += 4)
892 int line = GET_u2 (ptr);
893 /* Set initial input_line to smallest linenumber.
894 * Needs to be set before init_function_start. */
895 if (min_line == 0 || line < min_line)
896 min_line = line;
898 #ifdef USE_MAPPED_LOCATION
899 if (min_line != 0)
900 input_location = linemap_line_start (&line_table, min_line, 1);
901 #else
902 if (min_line != 0)
903 input_line = min_line;
904 #endif
906 else
908 linenumber_table = NULL;
909 linenumber_count = 0;
912 start_java_method (method);
914 note_instructions (jcf, method);
916 give_name_to_locals (jcf);
918 /* Convert bytecode to trees. */
919 expand_byte_code (jcf, method);
921 end_java_method ();
924 if (flag_emit_class_files)
925 write_classfile (current_class);
927 finish_class ();
929 (*debug_hooks->end_source_file) (LOCATION_LINE (save_location));
930 input_location = save_location;
933 /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */
935 static void
936 parse_source_file_1 (tree real_file, const char *filename, FILE *finput)
938 int save_error_count = java_error_count;
940 /* Mark the file as parsed. */
941 HAS_BEEN_ALREADY_PARSED_P (real_file) = 1;
943 lang_init_source (1); /* Error msgs have no method prototypes */
945 /* There's no point in trying to find the current encoding unless we
946 are going to do something intelligent with it -- hence the test
947 for iconv. */
948 #if defined (HAVE_LOCALE_H) && defined (HAVE_ICONV) && defined (HAVE_LANGINFO_CODESET)
949 setlocale (LC_CTYPE, "");
950 if (current_encoding == NULL)
951 current_encoding = nl_langinfo (CODESET);
952 #endif
953 if (current_encoding == NULL || *current_encoding == '\0')
954 current_encoding = DEFAULT_ENCODING;
956 #ifdef USE_MAPPED_LOCATION
957 linemap_add (&line_table, LC_ENTER, false, filename, 0);
958 input_location = linemap_line_start (&line_table, 0, 125);
959 #else
960 input_filename = filename;
961 input_line = 0;
962 #endif
963 ctxp->file_start_location = input_location;
964 ctxp->filename = filename;
966 jcf_dependency_add_file (input_filename, 0);
968 /* Initialize the parser */
969 java_init_lex (finput, current_encoding);
970 java_parse_abort_on_error ();
972 java_parse (); /* Parse and build partial tree nodes. */
973 java_parse_abort_on_error ();
976 /* Process a parsed source file, resolving names etc. */
978 static void
979 parse_source_file_2 (void)
981 int save_error_count = java_error_count;
982 flag_verify_invocations = true;
983 java_complete_class (); /* Parse unsatisfied class decl. */
984 java_parse_abort_on_error ();
987 static void
988 parse_source_file_3 (void)
990 int save_error_count = java_error_count;
991 java_check_circular_reference (); /* Check on circular references */
992 java_parse_abort_on_error ();
993 java_fix_constructors (); /* Fix the constructors */
994 java_parse_abort_on_error ();
995 java_reorder_fields (); /* Reorder the fields */
998 void
999 add_predefined_file (tree name)
1001 predef_filenames = tree_cons (NULL_TREE, name, predef_filenames);
1005 predefined_filename_p (tree node)
1007 tree iter;
1009 for (iter = predef_filenames; iter != NULL_TREE; iter = TREE_CHAIN (iter))
1011 if (TREE_VALUE (iter) == node)
1012 return 1;
1014 return 0;
1017 /* Generate a function that does all static initialization for this
1018 translation unit. */
1020 static void
1021 java_emit_static_constructor (void)
1023 tree body = NULL;
1025 emit_register_classes (&body);
1026 write_resource_constructor (&body);
1028 if (body)
1029 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
1032 void
1033 java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
1035 int filename_count = 0;
1036 location_t save_location = input_location;
1037 char *file_list = NULL, *list, *next;
1038 tree node;
1039 FILE *finput = NULL;
1040 int in_quotes = 0;
1042 if (flag_filelist_file)
1044 int avail = 2000;
1045 finput = fopen (main_input_filename, "r");
1046 if (finput == NULL)
1047 fatal_error ("can't open %s: %m", input_filename);
1048 list = xmalloc(avail);
1049 next = list;
1050 for (;;)
1052 int count;
1053 if (avail < 500)
1055 count = next - list;
1056 avail = 2 * (count + avail);
1057 list = xrealloc (list, avail);
1058 next = list + count;
1059 avail = avail - count;
1061 /* Subtract to to guarantee space for final '\0'. */
1062 count = fread (next, 1, avail - 1, finput);
1063 if (count == 0)
1065 if (! feof (finput))
1066 fatal_error ("error closing %s: %m", input_filename);
1067 *next = '\0';
1068 break;
1070 avail -= count;
1071 next += count;
1073 fclose (finput);
1074 finput = NULL;
1075 file_list = list;
1077 else
1078 list = (char *) main_input_filename;
1080 while (list)
1082 for (next = list; ; )
1084 char ch = *next;
1085 if (flag_filelist_file && ! in_quotes
1086 && (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' '
1087 || ch == '&') /* FIXME */)
1089 if (next == list)
1091 next++;
1092 list = next;
1093 continue;
1095 else
1097 *next++ = '\0';
1098 break;
1101 if (flag_filelist_file && ch == '"')
1103 in_quotes = ! in_quotes;
1104 *next++ = '\0';
1105 if (in_quotes)
1106 list = next;
1107 else
1108 break;
1110 if (ch == '\0')
1112 next = NULL;
1113 break;
1115 next++;
1118 if (list[0])
1120 node = get_identifier (list);
1122 filename_count++;
1124 /* Exclude file that we see twice on the command line. */
1126 if (IS_A_COMMAND_LINE_FILENAME_P (node))
1128 location_t warn_loc;
1129 #ifdef USE_MAPPED_LOCATION
1130 linemap_add (&line_table, LC_RENAME, 0,
1131 IDENTIFIER_POINTER (node), 0);
1132 warn_loc = linemap_line_start (&line_table, 0, 1);
1133 #else
1134 warn_loc.file = IDENTIFIER_POINTER (node);
1135 warn_loc.line = 0;
1136 #endif
1137 warning ("%Hsource file seen twice on command line and "
1138 "will be compiled only once", &warn_loc);
1140 else
1142 tree file_decl = build_decl (TRANSLATION_UNIT_DECL, node, NULL);
1143 TREE_CHAIN (file_decl) = current_file_list;
1144 current_file_list = file_decl;
1145 IS_A_COMMAND_LINE_FILENAME_P (node) = 1;
1148 list = next;
1151 if (file_list != NULL)
1152 free (file_list);
1154 if (filename_count == 0)
1155 warning ("no input file specified");
1157 if (resource_name)
1159 const char *resource_filename;
1161 /* Only one resource file may be compiled at a time. */
1162 assert (TREE_CHAIN (current_file_list) == NULL);
1164 resource_filename = IDENTIFIER_POINTER (DECL_NAME (current_file_list));
1165 compile_resource_file (resource_name, resource_filename);
1167 goto finish;
1170 current_jcf = main_jcf;
1171 current_file_list = nreverse (current_file_list);
1172 for (node = current_file_list; node; node = TREE_CHAIN (node))
1174 unsigned char magic_string[4];
1175 char *real_path;
1176 uint32 magic = 0;
1177 tree name = DECL_NAME (node);
1178 tree real_file;
1179 const char *filename = IDENTIFIER_POINTER (name);
1181 /* Skip already parsed files */
1182 real_path = lrealpath (filename);
1183 real_file = get_identifier (real_path);
1184 free (real_path);
1185 if (HAS_BEEN_ALREADY_PARSED_P (real_file))
1186 continue;
1188 /* Close previous descriptor, if any */
1189 if (finput && fclose (finput))
1190 fatal_error ("can't close input file %s: %m", main_input_filename);
1192 finput = fopen (filename, "rb");
1193 if (finput == NULL)
1194 fatal_error ("can't open %s: %m", filename);
1196 #ifdef IO_BUFFER_SIZE
1197 setvbuf (finput, xmalloc (IO_BUFFER_SIZE),
1198 _IOFBF, IO_BUFFER_SIZE);
1199 #endif
1201 /* Figure what kind of file we're dealing with */
1202 if (fread (magic_string, 1, 4, finput) == 4)
1204 fseek (finput, 0L, SEEK_SET);
1205 magic = GET_u4 (magic_string);
1207 if (magic == 0xcafebabe)
1209 CLASS_FILE_P (node) = 1;
1210 current_jcf = ggc_alloc (sizeof (JCF));
1211 JCF_ZERO (current_jcf);
1212 current_jcf->read_state = finput;
1213 current_jcf->filbuf = jcf_filbuf_from_stdio;
1214 jcf_parse (current_jcf);
1215 DECL_SOURCE_LOCATION (node) = file_start_location;
1216 TYPE_JCF (current_class) = current_jcf;
1217 CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1218 TREE_TYPE (node) = current_class;
1220 else if (magic == (JCF_u4)ZIPMAGIC)
1222 main_jcf = ggc_alloc (sizeof (JCF));
1223 JCF_ZERO (main_jcf);
1224 main_jcf->read_state = finput;
1225 main_jcf->filbuf = jcf_filbuf_from_stdio;
1226 #ifdef USE_MAPPED_LOCATION
1227 linemap_add (&line_table, LC_ENTER, false, filename, 0);
1228 input_location = linemap_line_start (&line_table, 0, 1);
1229 #endif
1230 if (open_in_zip (main_jcf, filename, NULL, 0) < 0)
1231 fatal_error ("bad zip/jar file %s", filename);
1232 localToFile = SeenZipFiles;
1233 /* Register all the classes defined there. */
1234 process_zip_dir (main_jcf->read_state);
1235 #ifdef USE_MAPPED_LOCATION
1236 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1237 #endif
1238 parse_zip_file_entries ();
1240 for (each entry)
1241 CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1244 else
1246 java_push_parser_context ();
1247 java_parser_context_save_global ();
1249 parse_source_file_1 (real_file, filename, finput);
1250 java_parser_context_restore_global ();
1251 java_pop_parser_context (1);
1252 #ifdef USE_MAPPED_LOCATION
1253 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1254 #endif
1258 for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
1260 input_location = ctxp->file_start_location;
1261 parse_source_file_2 ();
1264 for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
1266 input_location = ctxp->file_start_location;
1267 parse_source_file_3 ();
1270 for (node = current_file_list; node; node = TREE_CHAIN (node))
1272 input_location = DECL_SOURCE_LOCATION (node);
1273 if (CLASS_FILE_P (node))
1275 /* FIXME: These two flags really should be independent. We
1276 should be able to compile fully binary compatible, but
1277 with flag_verify_invocations on. */
1278 flag_verify_invocations = ! flag_indirect_dispatch;
1279 output_class = current_class = TREE_TYPE (node);
1281 current_jcf = TYPE_JCF (current_class);
1282 layout_class (current_class);
1283 load_inner_classes (current_class);
1284 parse_class_file ();
1285 JCF_FINISH (current_jcf);
1288 input_location = save_location;
1290 java_expand_classes ();
1291 if (java_report_errors () || flag_syntax_only)
1292 return;
1294 /* Expand all classes compiled from source. */
1295 java_finish_classes ();
1297 finish:
1298 /* Arrange for any necessary initialization to happen. */
1299 java_emit_static_constructor ();
1301 /* Only finalize the compilation unit after we've told cgraph which
1302 functions have their addresses stored. */
1303 cgraph_finalize_compilation_unit ();
1304 cgraph_optimize ();
1308 /* Return the name of the class corresponding to the name of the file
1309 in this zip entry. The result is newly allocated using ALLOC. */
1310 static char *
1311 compute_class_name (struct ZipDirectory *zdir)
1313 char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1314 char *class_name;
1315 int i;
1316 int filename_length = zdir->filename_length;
1318 while (filename_length > 2 && strncmp (class_name_in_zip_dir, "./", 2) == 0)
1320 class_name_in_zip_dir += 2;
1321 filename_length -= 2;
1324 filename_length -= strlen (".class");
1325 class_name = ALLOC (filename_length + 1);
1326 memcpy (class_name, class_name_in_zip_dir, filename_length);
1327 class_name [filename_length] = '\0';
1329 for (i = 0; i < filename_length; i++)
1330 if (class_name[i] == '/')
1331 class_name[i] = '.';
1333 return class_name;
1336 /* Return 0 if we should skip this entry, 1 if it is a .class file, 2
1337 if it is a property file of some sort. */
1338 static int
1339 classify_zip_file (struct ZipDirectory *zdir)
1341 char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1343 if (zdir->filename_length > 6
1344 && !strncmp (&class_name_in_zip_dir[zdir->filename_length - 6],
1345 ".class", 6))
1346 return 1;
1348 /* For now we drop the manifest, but not other information. */
1349 if (zdir->filename_length == 20
1350 && !strncmp (class_name_in_zip_dir, "META-INF/MANIFEST.MF", 20))
1351 return 0;
1353 /* Drop directory entries. */
1354 if (zdir->filename_length > 0
1355 && class_name_in_zip_dir[zdir->filename_length - 1] == '/')
1356 return 0;
1358 return 2;
1361 /* Process all class entries found in the zip file. */
1362 static void
1363 parse_zip_file_entries (void)
1365 struct ZipDirectory *zdir;
1366 int i;
1368 for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1369 i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1371 tree class;
1373 switch (classify_zip_file (zdir))
1375 case 0:
1376 continue;
1378 case 1:
1380 char *class_name = compute_class_name (zdir);
1381 class = lookup_class (get_identifier (class_name));
1382 FREE (class_name);
1383 current_jcf = TYPE_JCF (class);
1384 output_class = current_class = class;
1386 if (TYPE_DUMMY (class))
1388 /* This is a dummy class, and now we're compiling it
1389 for real. */
1390 abort ();
1393 /* This is for a corner case where we have a superclass
1394 but no superclass fields.
1396 This can happen if we earlier failed to lay out this
1397 class because its superclass was still in the process
1398 of being laid out; this occurs when we have recursive
1399 class dependencies via inner classes. Setting
1400 TYPE_SIZE to null here causes CLASS_LOADED_P to return
1401 false, so layout_class() will be called again. */
1402 if (TYPE_SIZE (class) && CLASSTYPE_SUPER (class)
1403 && integer_zerop (TYPE_SIZE (class)))
1404 TYPE_SIZE (class) = NULL_TREE;
1406 if (! CLASS_LOADED_P (class))
1408 if (! CLASS_PARSED_P (class))
1410 read_zip_member (current_jcf, zdir, localToFile);
1411 jcf_parse (current_jcf);
1413 layout_class (current_class);
1414 load_inner_classes (current_class);
1417 if (TYPE_SIZE (current_class) != error_mark_node)
1419 parse_class_file ();
1420 FREE (current_jcf->buffer); /* No longer necessary */
1421 /* Note: there is a way to free this buffer right after a
1422 class seen in a zip file has been parsed. The idea is the
1423 set its jcf in such a way that buffer will be reallocated
1424 the time the code for the class will be generated. FIXME. */
1427 break;
1429 case 2:
1431 char *file_name, *class_name_in_zip_dir, *buffer;
1432 JCF *jcf;
1433 file_name = ALLOC (zdir->filename_length + 1);
1434 class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1435 strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
1436 file_name[zdir->filename_length] = '\0';
1437 jcf = ALLOC (sizeof (JCF));
1438 JCF_ZERO (jcf);
1439 jcf->read_state = finput;
1440 jcf->filbuf = jcf_filbuf_from_stdio;
1441 jcf->java_source = 0;
1442 jcf->classname = NULL;
1443 jcf->filename = file_name;
1444 jcf->zipd = zdir;
1446 if (read_zip_member (jcf, zdir, localToFile) < 0)
1447 fatal_error ("error while reading %s from zip file", file_name);
1449 buffer = ALLOC (zdir->filename_length + 1 +
1450 (jcf->buffer_end - jcf->buffer));
1451 strcpy (buffer, file_name);
1452 /* This is not a typo: we overwrite the trailing \0 of the
1453 file name; this is just how the data is laid out. */
1454 memcpy (buffer + zdir->filename_length,
1455 jcf->buffer, jcf->buffer_end - jcf->buffer);
1457 compile_resource_data (file_name, buffer,
1458 jcf->buffer_end - jcf->buffer);
1459 JCF_FINISH (jcf);
1460 FREE (jcf);
1461 FREE (buffer);
1463 break;
1465 default:
1466 abort ();
1471 /* Read all the entries of the zip file, creates a class and a JCF. Sets the
1472 jcf up for further processing and link it to the created class. */
1474 static void
1475 process_zip_dir (FILE *finput)
1477 int i;
1478 ZipDirectory *zdir;
1480 for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1481 i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1483 char *class_name, *file_name, *class_name_in_zip_dir;
1484 tree class;
1485 JCF *jcf;
1487 class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1489 /* Here we skip non-class files; we handle them later. */
1490 if (classify_zip_file (zdir) != 1)
1491 continue;
1493 class_name = compute_class_name (zdir);
1494 file_name = ALLOC (zdir->filename_length+1);
1495 jcf = ggc_alloc (sizeof (JCF));
1496 JCF_ZERO (jcf);
1498 strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
1499 file_name [zdir->filename_length] = '\0';
1501 class = lookup_class (get_identifier (class_name));
1503 jcf->read_state = finput;
1504 jcf->filbuf = jcf_filbuf_from_stdio;
1505 jcf->java_source = 0;
1506 jcf->classname = class_name;
1507 jcf->filename = file_name;
1508 jcf->zipd = zdir;
1510 TYPE_JCF (class) = jcf;
1514 /* Initialization. */
1516 void
1517 init_jcf_parse (void)
1519 init_src_parse ();
1522 #include "gt-java-jcf-parse.h"