2006-06-30 Andrew Pinski <pinskia@gmail.com>
[official-gcc.git] / gcc / java / jcf-parse.c
blobb9d52b61f8c86c75f0c5874a137b8ce391f280b4
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, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, 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 gcc_unreachable ();
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] == '\\'))
146 #ifndef USE_MAPPED_LOCATION
147 DECL_SOURCE_LOCATION (TYPE_NAME (current_class)) = input_location;
148 file_start_location = input_location;
149 #endif
150 return;
153 if (strchr (sfname, '/') == NULL && strchr (sfname, '\\') == NULL)
155 const char *class_name
156 = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
157 char *dot = strrchr (class_name, '.');
158 if (dot != NULL)
160 /* Length of prefix, not counting final dot. */
161 int i = dot - class_name;
162 /* Concatenate current package prefix with new sfname. */
163 char *buf = XNEWVEC (char, i + new_len + 2); /* Space for '.' and '\0'. */
164 strcpy (buf + i + 1, sfname);
165 /* Copy package from class_name, replacing '.' by DIR_SEPARATOR.
166 Note we start at the end with the final package dot. */
167 for (; i >= 0; i--)
169 char c = class_name[i];
170 if (c == '.')
171 c = DIR_SEPARATOR;
172 buf[i] = c;
174 sfname_id = get_identifier (buf);
175 free (buf);
176 sfname = IDENTIFIER_POINTER (sfname_id);
180 #ifdef USE_MAPPED_LOCATION
181 line_table.maps[line_table.used-1].to_file = sfname;
182 #else
183 input_filename = sfname;
184 DECL_SOURCE_LOCATION (TYPE_NAME (current_class)) = input_location;
185 file_start_location = input_location;
186 #endif
187 if (current_class == main_class) main_input_filename = sfname;
190 #define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)
192 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
193 { tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
194 output_class = current_class = give_name_to_class (jcf, THIS); \
195 set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
197 #define HANDLE_CLASS_INTERFACE(INDEX) \
198 add_interface (current_class, get_class_constant (jcf, INDEX))
200 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
201 { int sig_index = SIGNATURE; \
202 current_field = add_field (current_class, get_name_constant (jcf, NAME), \
203 parse_signature (jcf, sig_index), ACCESS_FLAGS); \
204 set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); \
205 if ((ACCESS_FLAGS) & ACC_FINAL) \
206 MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (current_field); \
209 #define HANDLE_END_FIELDS() \
210 (current_field = NULL_TREE)
212 #define HANDLE_CONSTANTVALUE(INDEX) \
213 { tree constant; int index = INDEX; \
214 if (! flag_emit_class_files && JPOOL_TAG (jcf, index) == CONSTANT_String) { \
215 tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \
216 constant = build_utf8_ref (name); \
218 else \
219 constant = get_constant (jcf, index); \
220 set_constant_value (current_field, constant); }
222 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
223 (current_method = add_method (current_class, ACCESS_FLAGS, \
224 get_name_constant (jcf, NAME), \
225 get_name_constant (jcf, SIGNATURE)), \
226 DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \
227 DECL_LINENUMBERS_OFFSET (current_method) = 0)
229 #define HANDLE_END_METHODS() \
230 { current_method = NULL_TREE; }
232 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
233 { DECL_MAX_STACK (current_method) = (MAX_STACK); \
234 DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \
235 DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \
236 DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); }
238 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
239 { int n = (COUNT); \
240 DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
241 JCF_SKIP (jcf, n * 10); }
243 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
244 { int n = (COUNT); \
245 DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
246 JCF_SKIP (jcf, n * 4); }
248 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
250 int n = COUNT; \
251 tree list = DECL_FUNCTION_THROWS (current_method); \
252 while (--n >= 0) \
254 tree thrown_class = get_class_constant (jcf, JCF_readu2 (jcf)); \
255 list = tree_cons (NULL_TREE, thrown_class, list); \
257 DECL_FUNCTION_THROWS (current_method) = nreverse (list); \
260 #define HANDLE_DEPRECATED_ATTRIBUTE() handle_deprecated ()
262 /* Link seen inner classes to their outer context and register the
263 inner class to its outer context. They will be later loaded. */
264 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
265 handle_innerclass_attribute (COUNT, jcf)
267 #define HANDLE_SYNTHETIC_ATTRIBUTE() \
269 /* Irrelevant decls should have been nullified by the END macros. \
270 We only handle the `Synthetic' attribute on method DECLs. \
271 DECL_ARTIFICIAL on fields is used for something else (See \
272 PUSH_FIELD in java-tree.h) */ \
273 if (current_method) \
274 DECL_ARTIFICIAL (current_method) = 1; \
277 #define HANDLE_GCJCOMPILED_ATTRIBUTE() \
279 if (current_class == object_type_node) \
280 jcf->right_zip = 1; \
283 #include "jcf-reader.c"
285 tree
286 parse_signature (JCF *jcf, int sig_index)
288 gcc_assert (sig_index > 0
289 && sig_index < JPOOL_SIZE (jcf)
290 && JPOOL_TAG (jcf, sig_index) == CONSTANT_Utf8);
292 return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index),
293 JPOOL_UTF_LENGTH (jcf, sig_index));
296 tree
297 get_constant (JCF *jcf, int index)
299 tree value;
300 int tag;
301 if (index <= 0 || index >= JPOOL_SIZE(jcf))
302 goto bad;
303 tag = JPOOL_TAG (jcf, index);
304 if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
305 return jcf->cpool.data[index].t;
306 switch (tag)
308 case CONSTANT_Integer:
310 jint num = JPOOL_INT(jcf, index);
311 value = build_int_cst (int_type_node, num);
312 break;
314 case CONSTANT_Long:
316 unsigned HOST_WIDE_INT num = JPOOL_UINT (jcf, index);
317 unsigned HOST_WIDE_INT lo;
318 HOST_WIDE_INT hi;
320 lshift_double (num, 0, 32, 64, &lo, &hi, 0);
321 num = JPOOL_UINT (jcf, index+1);
322 add_double (lo, hi, num, 0, &lo, &hi);
323 value = build_int_cst_wide (long_type_node, lo, hi);
324 value = force_fit_type (value, 0, false, false);
325 break;
328 case CONSTANT_Float:
330 jint num = JPOOL_INT(jcf, index);
331 long buf = num;
332 REAL_VALUE_TYPE d;
334 real_from_target_fmt (&d, &buf, &ieee_single_format);
335 value = build_real (float_type_node, d);
336 break;
339 case CONSTANT_Double:
341 long buf[2], lo, hi;
342 REAL_VALUE_TYPE d;
344 hi = JPOOL_UINT (jcf, index);
345 lo = JPOOL_UINT (jcf, index+1);
347 if (FLOAT_WORDS_BIG_ENDIAN)
348 buf[0] = hi, buf[1] = lo;
349 else
350 buf[0] = lo, buf[1] = hi;
352 real_from_target_fmt (&d, buf, &ieee_double_format);
353 value = build_real (double_type_node, d);
354 break;
357 case CONSTANT_String:
359 tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
360 const char *utf8_ptr = IDENTIFIER_POINTER (name);
361 int utf8_len = IDENTIFIER_LENGTH (name);
362 const unsigned char *utf8;
363 int i;
365 /* Check for a malformed Utf8 string. */
366 utf8 = (const unsigned char *) utf8_ptr;
367 i = utf8_len;
368 while (i > 0)
370 int char_len = UT8_CHAR_LENGTH (*utf8);
371 if (char_len < 0 || char_len > 3 || char_len > i)
372 fatal_error ("bad string constant");
374 utf8 += char_len;
375 i -= char_len;
378 /* Allocate a new string value. */
379 value = build_string (utf8_len, utf8_ptr);
380 TREE_TYPE (value) = build_pointer_type (string_type_node);
382 break;
383 default:
384 goto bad;
386 JPOOL_TAG (jcf, index) = tag | CONSTANT_ResolvedFlag;
387 jcf->cpool.data[index].t = value;
388 return value;
389 bad:
390 internal_error ("bad value constant type %d, index %d",
391 JPOOL_TAG (jcf, index), index);
394 tree
395 get_name_constant (JCF *jcf, int index)
397 tree name = get_constant (jcf, index);
398 gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
399 return name;
402 /* Handle reading innerclass attributes. If a nonzero entry (denoting
403 a non anonymous entry) is found, We augment the inner class list of
404 the outer context with the newly resolved innerclass. */
406 static void
407 handle_innerclass_attribute (int count, JCF *jcf)
409 int c = (count);
410 while (c--)
412 /* Read inner_class_info_index. This may be 0 */
413 int icii = JCF_readu2 (jcf);
414 /* Read outer_class_info_index. If the innerclasses attribute
415 entry isn't a member (like an inner class) the value is 0. */
416 int ocii = JCF_readu2 (jcf);
417 /* Read inner_name_index. If the class we're dealing with is
418 an anonymous class, it must be 0. */
419 int ini = JCF_readu2 (jcf);
420 /* Read the access flag. */
421 int acc = JCF_readu2 (jcf);
422 /* If icii is 0, don't try to read the class. */
423 if (icii >= 0)
425 tree class = get_class_constant (jcf, icii);
426 tree decl = TYPE_NAME (class);
427 /* Skip reading further if ocii is null */
428 if (DECL_P (decl) && !CLASS_COMPLETE_P (decl) && ocii)
430 tree outer = TYPE_NAME (get_class_constant (jcf, ocii));
431 tree alias = (ini ? get_name_constant (jcf, ini) : NULL_TREE);
432 set_class_decl_access_flags (acc, decl);
433 DECL_CONTEXT (decl) = outer;
434 DECL_INNER_CLASS_LIST (outer) =
435 tree_cons (decl, alias, DECL_INNER_CLASS_LIST (outer));
436 CLASS_COMPLETE_P (decl) = 1;
442 static tree
443 give_name_to_class (JCF *jcf, int i)
445 gcc_assert (i > 0
446 && i < JPOOL_SIZE (jcf)
447 && JPOOL_TAG (jcf, i) == CONSTANT_Class);
450 tree package_name = NULL_TREE, tmp;
451 tree this_class;
452 int j = JPOOL_USHORT1 (jcf, i);
453 /* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */
454 tree class_name = unmangle_classname ((const char *) JPOOL_UTF_DATA (jcf, j),
455 JPOOL_UTF_LENGTH (jcf, j));
456 this_class = lookup_class (class_name);
457 #ifdef USE_MAPPED_LOCATION
459 tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
460 const char *sfname = IDENTIFIER_POINTER (source_name);
461 linemap_add (&line_table, LC_ENTER, false, sfname, 0);
462 input_location = linemap_line_start (&line_table, 0, 1);
463 file_start_location = input_location;
464 DECL_SOURCE_LOCATION (TYPE_NAME (this_class)) = input_location;
465 if (main_input_filename == NULL && jcf == main_jcf)
466 main_input_filename = sfname;
468 #else
469 input_location = DECL_SOURCE_LOCATION (TYPE_NAME (this_class));
470 if (main_input_filename == NULL && jcf == main_jcf)
471 main_input_filename = input_filename;
472 #endif
474 jcf->cpool.data[i].t = this_class;
475 JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
476 split_qualified_name (&package_name, &tmp,
477 DECL_NAME (TYPE_NAME (this_class)));
478 TYPE_PACKAGE (this_class) = package_name;
479 return this_class;
483 /* Get the class of the CONSTANT_Class whose constant pool index is I. */
485 tree
486 get_class_constant (JCF *jcf, int i)
488 tree type;
489 gcc_assert (i > 0
490 && i < JPOOL_SIZE (jcf)
491 && (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) == CONSTANT_Class);
493 if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)
495 int name_index = JPOOL_USHORT1 (jcf, i);
496 /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */
497 const char *name = (const char *) JPOOL_UTF_DATA (jcf, name_index);
498 int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
500 if (name[0] == '[') /* Handle array "classes". */
501 type = TREE_TYPE (parse_signature_string ((const unsigned char *) name, nlength));
502 else
504 tree cname = unmangle_classname (name, nlength);
505 type = lookup_class (cname);
507 jcf->cpool.data[i].t = type;
508 JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
510 else
511 type = jcf->cpool.data[i].t;
512 return type;
515 /* Read a class with the fully qualified-name NAME.
516 Return 1 iff we read the requested file.
517 (It is still possible we failed if the file did not
518 define the class it is supposed to.) */
521 read_class (tree name)
523 JCF this_jcf, *jcf;
524 tree icv, class = NULL_TREE;
525 tree save_current_class = current_class;
526 tree save_output_class = output_class;
527 location_t save_location = input_location;
528 JCF *save_current_jcf = current_jcf;
530 if ((icv = IDENTIFIER_CLASS_VALUE (name)) != NULL_TREE)
532 class = TREE_TYPE (icv);
533 jcf = TYPE_JCF (class);
535 else
536 jcf = NULL;
538 if (jcf == NULL)
540 const char* path_name;
541 this_jcf.zipd = NULL;
542 jcf = &this_jcf;
544 path_name = find_class (IDENTIFIER_POINTER (name),
545 IDENTIFIER_LENGTH (name),
546 &this_jcf, 1);
547 if (path_name == 0)
548 return 0;
549 else
550 free((char *) path_name);
553 current_jcf = jcf;
555 if (current_jcf->java_source)
557 const char *filename = current_jcf->filename;
558 char *real_path;
559 tree given_file, real_file;
560 FILE *finput;
561 int generate;
563 java_parser_context_save_global ();
564 java_push_parser_context ();
566 given_file = get_identifier (filename);
567 filename = IDENTIFIER_POINTER (given_file);
568 real_path = lrealpath (filename);
569 real_file = get_identifier (real_path);
570 free (real_path);
572 generate = IS_A_COMMAND_LINE_FILENAME_P (given_file);
573 output_class = current_class = NULL_TREE;
574 current_function_decl = NULL_TREE;
576 if (! HAS_BEEN_ALREADY_PARSED_P (real_file))
578 if (! (finput = fopen (filename, "r")))
579 fatal_error ("can't reopen %s: %m", filename);
581 parse_source_file_1 (real_file, filename, finput);
582 parse_source_file_2 ();
583 parse_source_file_3 ();
585 if (fclose (finput))
586 fatal_error ("can't close %s: %m", input_filename);
587 #ifdef USE_MAPPED_LOCATION
588 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
589 #endif
591 JCF_FINISH (current_jcf);
592 java_pop_parser_context (generate);
593 java_parser_context_restore_global ();
595 else
597 if (class == NULL_TREE || ! CLASS_PARSED_P (class))
599 java_parser_context_save_global ();
600 java_push_parser_context ();
601 output_class = current_class = class;
602 ctxp->save_location = input_location;
603 if (JCF_SEEN_IN_ZIP (current_jcf))
604 read_zip_member(current_jcf,
605 current_jcf->zipd, current_jcf->zipd->zipf);
606 jcf_parse (current_jcf);
607 /* Parsing might change the class, in which case we have to
608 put it back where we found it. */
609 if (current_class != class && icv != NULL_TREE)
610 TREE_TYPE (icv) = current_class;
611 class = current_class;
612 java_pop_parser_context (0);
613 java_parser_context_restore_global ();
615 layout_class (class);
616 load_inner_classes (class);
619 output_class = save_output_class;
620 current_class = save_current_class;
621 input_location = save_location;
622 current_jcf = save_current_jcf;
623 return 1;
626 /* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if
627 called from the parser, otherwise it's a RECORD_TYPE node. If
628 VERBOSE is 1, print error message on failure to load a class. */
629 void
630 load_class (tree class_or_name, int verbose)
632 tree name, saved;
633 int class_loaded = 0;
634 tree class_decl = NULL_TREE;
635 bool is_compiled_class = false;
637 /* We've already failed, don't try again. */
638 if (TREE_CODE (class_or_name) == RECORD_TYPE
639 && TYPE_DUMMY (class_or_name))
640 return;
642 /* class_or_name can be the name of the class we want to load */
643 if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
644 name = class_or_name;
645 /* In some cases, it's a dependency that we process earlier that
646 we though */
647 else if (TREE_CODE (class_or_name) == TREE_LIST)
648 name = TYPE_NAME (TREE_PURPOSE (class_or_name));
649 /* Or it's a type in the making */
650 else
651 name = DECL_NAME (TYPE_NAME (class_or_name));
653 class_decl = IDENTIFIER_CLASS_VALUE (name);
654 if (class_decl != NULL_TREE)
656 tree type = TREE_TYPE (class_decl);
657 is_compiled_class
658 = ((TYPE_JCF (type) && JCF_SEEN_IN_ZIP (TYPE_JCF (type)))
659 || CLASS_FROM_CURRENTLY_COMPILED_P (type));
662 /* If the class is from source code, then it must already be loaded. */
663 class_decl = IDENTIFIER_CLASS_VALUE (name);
664 if (class_decl && CLASS_FROM_SOURCE_P (TREE_TYPE (class_decl)))
665 return;
667 saved = name;
669 /* If flag_verify_invocations is unset, we don't try to load a class
670 unless we're looking for Object (which is fixed by the ABI) or
671 it's a class that we're going to compile. */
672 if (flag_verify_invocations
673 || class_or_name == object_type_node
674 || is_compiled_class
675 || TREE_CODE (class_or_name) == IDENTIFIER_NODE)
677 while (1)
679 char *separator;
681 /* We've already loaded it. */
682 if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE)
684 tree tmp_decl = IDENTIFIER_CLASS_VALUE (name);
685 if (CLASS_PARSED_P (TREE_TYPE (tmp_decl)))
686 break;
689 if (read_class (name))
690 break;
692 /* We failed loading name. Now consider that we might be looking
693 for an inner class. */
694 if ((separator = strrchr (IDENTIFIER_POINTER (name), '$'))
695 || (separator = strrchr (IDENTIFIER_POINTER (name), '.')))
697 int c = *separator;
698 *separator = '\0';
699 name = get_identifier (IDENTIFIER_POINTER (name));
700 *separator = c;
702 /* Otherwise, we failed, we bail. */
703 else
704 break;
708 /* have we found the class we're looking for? */
709 tree type_decl = IDENTIFIER_CLASS_VALUE (saved);
710 tree type = type_decl ? TREE_TYPE (type_decl) : NULL;
711 class_loaded = type && CLASS_PARSED_P (type);
715 if (!class_loaded)
717 if (flag_verify_invocations || ! flag_indirect_dispatch
718 || flag_emit_class_files)
720 if (verbose)
721 error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
723 else if (verbose)
725 /* This is just a diagnostic during testing, not a real problem. */
726 if (!quiet_flag)
727 warning (0, "cannot find file for class %s",
728 IDENTIFIER_POINTER (saved));
730 /* Fake it. */
731 if (TREE_CODE (class_or_name) == RECORD_TYPE)
733 set_super_info (0, class_or_name, object_type_node, 0);
734 TYPE_DUMMY (class_or_name) = 1;
735 /* We won't be able to output any debug info for this class. */
736 DECL_IGNORED_P (TYPE_NAME (class_or_name)) = 1;
742 /* Parse the .class file JCF. */
744 static void
745 jcf_parse (JCF* jcf)
747 int i, code;
749 if (jcf_parse_preamble (jcf) != 0)
750 fatal_error ("not a valid Java .class file");
751 code = jcf_parse_constant_pool (jcf);
752 if (code != 0)
753 fatal_error ("error while parsing constant pool");
754 code = verify_constant_pool (jcf);
755 if (code > 0)
756 fatal_error ("error in constant pool entry #%d\n", code);
758 jcf_parse_class (jcf);
759 if (main_class == NULL_TREE)
760 main_class = current_class;
761 if (! quiet_flag && TYPE_NAME (current_class))
762 fprintf (stderr, " %s %s",
763 (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class",
764 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
765 if (CLASS_PARSED_P (current_class))
767 /* FIXME - where was first time */
768 fatal_error ("reading class %s for the second time from %s",
769 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))),
770 jcf->filename);
772 CLASS_PARSED_P (current_class) = 1;
774 for (i = 1; i < JPOOL_SIZE(jcf); i++)
776 switch (JPOOL_TAG (jcf, i))
778 case CONSTANT_Class:
779 get_class_constant (jcf, i);
780 break;
784 code = jcf_parse_fields (jcf);
785 if (code != 0)
786 fatal_error ("error while parsing fields");
787 code = jcf_parse_methods (jcf);
788 if (code != 0)
789 fatal_error ("error while parsing methods");
790 code = jcf_parse_final_attributes (jcf);
791 if (code != 0)
792 fatal_error ("error while parsing final attributes");
793 #ifdef USE_MAPPED_LOCATION
794 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
795 #endif
797 /* The fields of class_type_node are already in correct order. */
798 if (current_class != class_type_node && current_class != object_type_node)
799 TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));
801 if (current_class == object_type_node)
803 layout_class_methods (object_type_node);
804 /* If we don't have the right archive, emit a verbose warning.
805 If we're generating bytecode, emit the warning only if
806 -fforce-classes-archive-check was specified. */
807 if (!jcf->right_zip
808 && (!flag_emit_class_files || flag_force_classes_archive_check))
809 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);
811 else
812 all_class_list = tree_cons (NULL_TREE,
813 TYPE_NAME (current_class), all_class_list );
816 /* If we came across inner classes, load them now. */
817 static void
818 load_inner_classes (tree cur_class)
820 tree current;
821 for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (cur_class)); current;
822 current = TREE_CHAIN (current))
824 tree name = DECL_NAME (TREE_PURPOSE (current));
825 tree decl = IDENTIFIER_GLOBAL_VALUE (name);
826 if (decl && ! CLASS_LOADED_P (TREE_TYPE (decl))
827 && !CLASS_BEING_LAIDOUT (TREE_TYPE (decl)))
828 load_class (name, 1);
832 static void
833 duplicate_class_warning (const char *filename)
835 location_t warn_loc;
836 #ifdef USE_MAPPED_LOCATION
837 linemap_add (&line_table, LC_RENAME, 0, filename, 0);
838 warn_loc = linemap_line_start (&line_table, 0, 1);
839 #else
840 warn_loc.file = filename;
841 warn_loc.line = 0;
842 #endif
843 warning (0, "%Hduplicate class will only be compiled once", &warn_loc);
846 static void
847 parse_class_file (void)
849 tree method;
850 location_t save_location = input_location;
852 java_layout_seen_class_methods ();
854 input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class));
855 file_start_location = input_location;
856 (*debug_hooks->start_source_file) (input_line, input_filename);
858 gen_indirect_dispatch_tables (current_class);
860 java_mark_class_local (current_class);
862 for (method = TYPE_METHODS (current_class);
863 method != NULL_TREE; method = TREE_CHAIN (method))
865 JCF *jcf = current_jcf;
867 if (METHOD_ABSTRACT (method) || METHOD_DUMMY (method))
868 continue;
870 if (METHOD_NATIVE (method))
872 tree arg;
873 int decl_max_locals;
875 if (! flag_jni)
876 continue;
877 /* We need to compute the DECL_MAX_LOCALS. We need to take
878 the wide types into account too. */
879 for (arg = TYPE_ARG_TYPES (TREE_TYPE (method)), decl_max_locals = 0;
880 arg != end_params_node;
881 arg = TREE_CHAIN (arg), decl_max_locals += 1)
883 if (TREE_VALUE (arg) && TYPE_IS_WIDE (TREE_VALUE (arg)))
884 decl_max_locals += 1;
886 DECL_MAX_LOCALS (method) = decl_max_locals;
887 start_java_method (method);
888 give_name_to_locals (jcf);
889 *get_stmts () = build_jni_stub (method);
890 end_java_method ();
891 continue;
894 if (DECL_CODE_OFFSET (method) == 0)
896 current_function_decl = method;
897 error ("missing Code attribute");
898 continue;
901 input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class));
902 if (DECL_LINENUMBERS_OFFSET (method))
904 int i;
905 int min_line = 0;
906 unsigned char *ptr;
907 JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method));
908 linenumber_count = i = JCF_readu2 (jcf);
909 linenumber_table = ptr = jcf->read_ptr;
911 for (ptr += 2; --i >= 0; ptr += 4)
913 int line = GET_u2 (ptr);
914 /* Set initial input_line to smallest linenumber.
915 * Needs to be set before init_function_start. */
916 if (min_line == 0 || line < min_line)
917 min_line = line;
919 #ifdef USE_MAPPED_LOCATION
920 if (min_line != 0)
921 input_location = linemap_line_start (&line_table, min_line, 1);
922 #else
923 if (min_line != 0)
924 input_line = min_line;
925 #endif
927 else
929 linenumber_table = NULL;
930 linenumber_count = 0;
933 start_java_method (method);
935 note_instructions (jcf, method);
937 give_name_to_locals (jcf);
939 /* Bump up start_label_pc_this_method so we get a unique label number
940 and reset highest_label_pc_this_method. */
941 if (highest_label_pc_this_method >= 0)
943 /* We adjust to the next multiple of 1000. This is just a frill
944 so the last 3 digits of the label number match the bytecode
945 offset, which might make debugging marginally more convenient. */
946 start_label_pc_this_method
947 = ((((start_label_pc_this_method + highest_label_pc_this_method)
948 / 1000)
949 + 1)
950 * 1000);
951 highest_label_pc_this_method = -1;
954 /* Convert bytecode to trees. */
955 expand_byte_code (jcf, method);
957 end_java_method ();
960 if (flag_emit_class_files)
961 write_classfile (current_class);
963 finish_class ();
965 (*debug_hooks->end_source_file) (LOCATION_LINE (save_location));
966 input_location = save_location;
969 /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */
971 static void
972 parse_source_file_1 (tree real_file, const char *filename, FILE *finput)
974 int save_error_count = java_error_count;
976 /* Mark the file as parsed. */
977 HAS_BEEN_ALREADY_PARSED_P (real_file) = 1;
979 lang_init_source (1); /* Error msgs have no method prototypes */
981 /* There's no point in trying to find the current encoding unless we
982 are going to do something intelligent with it -- hence the test
983 for iconv. */
984 #if defined (HAVE_LOCALE_H) && defined (HAVE_ICONV) && defined (HAVE_LANGINFO_CODESET)
985 setlocale (LC_CTYPE, "");
986 if (current_encoding == NULL)
987 current_encoding = nl_langinfo (CODESET);
988 #endif
989 if (current_encoding == NULL || *current_encoding == '\0')
990 current_encoding = DEFAULT_ENCODING;
992 #ifdef USE_MAPPED_LOCATION
993 linemap_add (&line_table, LC_ENTER, false, filename, 0);
994 input_location = linemap_line_start (&line_table, 0, 125);
995 #else
996 input_filename = filename;
997 input_line = 0;
998 #endif
999 ctxp->file_start_location = input_location;
1000 ctxp->filename = filename;
1002 jcf_dependency_add_file (input_filename, 0);
1004 /* Initialize the parser */
1005 java_init_lex (finput, current_encoding);
1006 java_parse_abort_on_error ();
1008 java_parse (); /* Parse and build partial tree nodes. */
1009 java_parse_abort_on_error ();
1012 /* Process a parsed source file, resolving names etc. */
1014 static void
1015 parse_source_file_2 (void)
1017 int save_error_count = java_error_count;
1018 flag_verify_invocations = true;
1019 java_complete_class (); /* Parse unsatisfied class decl. */
1020 java_parse_abort_on_error ();
1023 static void
1024 parse_source_file_3 (void)
1026 int save_error_count = java_error_count;
1027 java_check_circular_reference (); /* Check on circular references */
1028 java_parse_abort_on_error ();
1029 java_fix_constructors (); /* Fix the constructors */
1030 java_parse_abort_on_error ();
1031 java_reorder_fields (); /* Reorder the fields */
1034 void
1035 add_predefined_file (tree name)
1037 predef_filenames = tree_cons (NULL_TREE, name, predef_filenames);
1041 predefined_filename_p (tree node)
1043 tree iter;
1045 for (iter = predef_filenames; iter != NULL_TREE; iter = TREE_CHAIN (iter))
1047 if (TREE_VALUE (iter) == node)
1048 return 1;
1050 return 0;
1053 /* Generate a function that does all static initialization for this
1054 translation unit. */
1056 static void
1057 java_emit_static_constructor (void)
1059 tree body = NULL;
1061 emit_register_classes (&body);
1062 write_resource_constructor (&body);
1064 if (body)
1065 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
1068 void
1069 java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
1071 int filename_count = 0;
1072 location_t save_location = input_location;
1073 char *file_list = NULL, *list, *next;
1074 tree node;
1075 FILE *finput = NULL;
1076 int in_quotes = 0;
1078 if (flag_filelist_file)
1080 int avail = 2000;
1081 finput = fopen (main_input_filename, "r");
1082 if (finput == NULL)
1083 fatal_error ("can't open %s: %m", input_filename);
1084 list = XNEWVEC (char, avail);
1085 next = list;
1086 for (;;)
1088 int count;
1089 if (avail < 500)
1091 count = next - list;
1092 avail = 2 * (count + avail);
1093 list = xrealloc (list, avail);
1094 next = list + count;
1095 avail = avail - count;
1097 /* Subtract to to guarantee space for final '\0'. */
1098 count = fread (next, 1, avail - 1, finput);
1099 if (count == 0)
1101 if (! feof (finput))
1102 fatal_error ("error closing %s: %m", input_filename);
1103 *next = '\0';
1104 break;
1106 avail -= count;
1107 next += count;
1109 fclose (finput);
1110 finput = NULL;
1111 file_list = list;
1113 else
1114 list = (char *) main_input_filename;
1116 while (list)
1118 for (next = list; ; )
1120 char ch = *next;
1121 if (flag_filelist_file && ! in_quotes
1122 && (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' '
1123 || ch == '&') /* FIXME */)
1125 if (next == list)
1127 next++;
1128 list = next;
1129 continue;
1131 else
1133 *next++ = '\0';
1134 break;
1137 if (flag_filelist_file && ch == '"')
1139 in_quotes = ! in_quotes;
1140 *next++ = '\0';
1141 if (in_quotes)
1142 list = next;
1143 else
1144 break;
1146 if (ch == '\0')
1148 next = NULL;
1149 break;
1151 next++;
1154 if (list[0])
1156 node = get_identifier (list);
1158 filename_count++;
1160 /* Exclude file that we see twice on the command line. */
1162 if (IS_A_COMMAND_LINE_FILENAME_P (node))
1163 duplicate_class_warning (IDENTIFIER_POINTER (node));
1164 else
1166 tree file_decl = build_decl (TRANSLATION_UNIT_DECL, node, NULL);
1167 TREE_CHAIN (file_decl) = current_file_list;
1168 current_file_list = file_decl;
1169 IS_A_COMMAND_LINE_FILENAME_P (node) = 1;
1172 list = next;
1175 if (file_list != NULL)
1176 free (file_list);
1178 if (filename_count == 0)
1179 warning (0, "no input file specified");
1181 if (resource_name)
1183 const char *resource_filename;
1185 /* Only one resource file may be compiled at a time. */
1186 assert (TREE_CHAIN (current_file_list) == NULL);
1188 resource_filename = IDENTIFIER_POINTER (DECL_NAME (current_file_list));
1189 compile_resource_file (resource_name, resource_filename);
1191 goto finish;
1194 current_jcf = main_jcf;
1195 current_file_list = nreverse (current_file_list);
1196 for (node = current_file_list; node; node = TREE_CHAIN (node))
1198 unsigned char magic_string[4];
1199 char *real_path;
1200 uint32 magic = 0;
1201 tree name = DECL_NAME (node);
1202 tree real_file;
1203 const char *filename = IDENTIFIER_POINTER (name);
1205 /* Skip already parsed files */
1206 real_path = lrealpath (filename);
1207 real_file = get_identifier (real_path);
1208 free (real_path);
1209 if (HAS_BEEN_ALREADY_PARSED_P (real_file))
1210 continue;
1212 /* Close previous descriptor, if any */
1213 if (finput && fclose (finput))
1214 fatal_error ("can't close input file %s: %m", main_input_filename);
1216 finput = fopen (filename, "rb");
1217 if (finput == NULL)
1218 fatal_error ("can't open %s: %m", filename);
1220 #ifdef IO_BUFFER_SIZE
1221 setvbuf (finput, xmalloc (IO_BUFFER_SIZE),
1222 _IOFBF, IO_BUFFER_SIZE);
1223 #endif
1225 /* Figure what kind of file we're dealing with */
1226 if (fread (magic_string, 1, 4, finput) == 4)
1228 fseek (finput, 0L, SEEK_SET);
1229 magic = GET_u4 (magic_string);
1231 if (magic == 0xcafebabe)
1233 CLASS_FILE_P (node) = 1;
1234 current_jcf = ggc_alloc (sizeof (JCF));
1235 JCF_ZERO (current_jcf);
1236 current_jcf->read_state = finput;
1237 current_jcf->filbuf = jcf_filbuf_from_stdio;
1238 jcf_parse (current_jcf);
1239 DECL_SOURCE_LOCATION (node) = file_start_location;
1240 TYPE_JCF (current_class) = current_jcf;
1241 if (CLASS_FROM_CURRENTLY_COMPILED_P (current_class))
1243 /* We've already compiled this class. */
1244 duplicate_class_warning (filename);
1245 continue;
1247 CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1248 TREE_TYPE (node) = current_class;
1250 else if (magic == (JCF_u4)ZIPMAGIC)
1252 main_jcf = ggc_alloc (sizeof (JCF));
1253 JCF_ZERO (main_jcf);
1254 main_jcf->read_state = finput;
1255 main_jcf->filbuf = jcf_filbuf_from_stdio;
1256 #ifdef USE_MAPPED_LOCATION
1257 linemap_add (&line_table, LC_ENTER, false, filename, 0);
1258 input_location = linemap_line_start (&line_table, 0, 1);
1259 #endif
1260 if (open_in_zip (main_jcf, filename, NULL, 0) < 0)
1261 fatal_error ("bad zip/jar file %s", filename);
1262 localToFile = SeenZipFiles;
1263 /* Register all the classes defined there. */
1264 process_zip_dir (main_jcf->read_state);
1265 #ifdef USE_MAPPED_LOCATION
1266 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1267 #endif
1268 parse_zip_file_entries ();
1270 else
1272 java_push_parser_context ();
1273 java_parser_context_save_global ();
1275 parse_source_file_1 (real_file, filename, finput);
1276 java_parser_context_restore_global ();
1277 java_pop_parser_context (1);
1278 #ifdef USE_MAPPED_LOCATION
1279 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1280 #endif
1284 for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
1286 input_location = ctxp->file_start_location;
1287 parse_source_file_2 ();
1290 for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
1292 input_location = ctxp->file_start_location;
1293 parse_source_file_3 ();
1296 for (node = current_file_list; node; node = TREE_CHAIN (node))
1298 input_location = DECL_SOURCE_LOCATION (node);
1299 if (CLASS_FILE_P (node))
1301 /* FIXME: These two flags really should be independent. We
1302 should be able to compile fully binary compatible, but
1303 with flag_verify_invocations on. */
1304 flag_verify_invocations = ! flag_indirect_dispatch;
1305 output_class = current_class = TREE_TYPE (node);
1307 current_jcf = TYPE_JCF (current_class);
1308 layout_class (current_class);
1309 load_inner_classes (current_class);
1310 parse_class_file ();
1311 JCF_FINISH (current_jcf);
1314 input_location = save_location;
1316 java_expand_classes ();
1317 if (java_report_errors () || flag_syntax_only)
1318 return;
1320 /* Expand all classes compiled from source. */
1321 java_finish_classes ();
1323 finish:
1324 /* Arrange for any necessary initialization to happen. */
1325 java_emit_static_constructor ();
1327 /* Only finalize the compilation unit after we've told cgraph which
1328 functions have their addresses stored. */
1329 cgraph_finalize_compilation_unit ();
1330 cgraph_optimize ();
1334 /* Return the name of the class corresponding to the name of the file
1335 in this zip entry. The result is newly allocated using ALLOC. */
1336 static char *
1337 compute_class_name (struct ZipDirectory *zdir)
1339 char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1340 char *class_name;
1341 int i;
1342 int filename_length = zdir->filename_length;
1344 while (filename_length > 2 && strncmp (class_name_in_zip_dir, "./", 2) == 0)
1346 class_name_in_zip_dir += 2;
1347 filename_length -= 2;
1350 filename_length -= strlen (".class");
1351 class_name = XNEWVEC (char, filename_length + 1);
1352 memcpy (class_name, class_name_in_zip_dir, filename_length);
1353 class_name [filename_length] = '\0';
1355 for (i = 0; i < filename_length; i++)
1356 if (class_name[i] == '/')
1357 class_name[i] = '.';
1359 return class_name;
1362 /* Return 0 if we should skip this entry, 1 if it is a .class file, 2
1363 if it is a property file of some sort. */
1364 static int
1365 classify_zip_file (struct ZipDirectory *zdir)
1367 char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1369 if (zdir->filename_length > 6
1370 && !strncmp (&class_name_in_zip_dir[zdir->filename_length - 6],
1371 ".class", 6))
1372 return 1;
1374 /* For now we drop the manifest, but not other information. */
1375 if (zdir->filename_length == 20
1376 && !strncmp (class_name_in_zip_dir, "META-INF/MANIFEST.MF", 20))
1377 return 0;
1379 /* Drop directory entries. */
1380 if (zdir->filename_length > 0
1381 && class_name_in_zip_dir[zdir->filename_length - 1] == '/')
1382 return 0;
1384 return 2;
1387 /* Process all class entries found in the zip file. */
1388 static void
1389 parse_zip_file_entries (void)
1391 struct ZipDirectory *zdir;
1392 int i;
1394 for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1395 i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1397 tree class;
1399 switch (classify_zip_file (zdir))
1401 case 0:
1402 continue;
1404 case 1:
1406 char *class_name = compute_class_name (zdir);
1407 class = lookup_class (get_identifier (class_name));
1408 FREE (class_name);
1409 current_jcf = TYPE_JCF (class);
1410 output_class = current_class = class;
1412 if (CLASS_FROM_CURRENTLY_COMPILED_P (current_class))
1414 /* We've already compiled this class. */
1415 duplicate_class_warning (current_jcf->filename);
1416 break;
1419 CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1421 /* This is a dummy class, and now we're compiling it for
1422 real. */
1423 gcc_assert (! TYPE_DUMMY (class));
1425 /* This is for a corner case where we have a superclass
1426 but no superclass fields.
1428 This can happen if we earlier failed to lay out this
1429 class because its superclass was still in the process
1430 of being laid out; this occurs when we have recursive
1431 class dependencies via inner classes. Setting
1432 TYPE_SIZE to null here causes CLASS_LOADED_P to return
1433 false, so layout_class() will be called again. */
1434 if (TYPE_SIZE (class) && CLASSTYPE_SUPER (class)
1435 && integer_zerop (TYPE_SIZE (class)))
1436 TYPE_SIZE (class) = NULL_TREE;
1438 if (! CLASS_LOADED_P (class))
1440 if (! CLASS_PARSED_P (class))
1442 read_zip_member (current_jcf, zdir, localToFile);
1443 jcf_parse (current_jcf);
1445 layout_class (current_class);
1446 load_inner_classes (current_class);
1449 if (TYPE_SIZE (current_class) != error_mark_node)
1451 parse_class_file ();
1452 free (current_jcf->buffer); /* No longer necessary */
1453 /* Note: there is a way to free this buffer right after a
1454 class seen in a zip file has been parsed. The idea is the
1455 set its jcf in such a way that buffer will be reallocated
1456 the time the code for the class will be generated. FIXME. */
1459 break;
1461 case 2:
1463 char *file_name, *class_name_in_zip_dir, *buffer;
1464 JCF *jcf;
1465 file_name = XNEWVEC (char, zdir->filename_length + 1);
1466 class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1467 strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
1468 file_name[zdir->filename_length] = '\0';
1469 jcf = XNEW (JCF);
1470 JCF_ZERO (jcf);
1471 jcf->read_state = finput;
1472 jcf->filbuf = jcf_filbuf_from_stdio;
1473 jcf->java_source = 0;
1474 jcf->classname = NULL;
1475 jcf->filename = file_name;
1476 jcf->zipd = zdir;
1478 if (read_zip_member (jcf, zdir, localToFile) < 0)
1479 fatal_error ("error while reading %s from zip file", file_name);
1481 buffer = XNEWVEC (char, zdir->filename_length + 1 +
1482 (jcf->buffer_end - jcf->buffer));
1483 strcpy (buffer, file_name);
1484 /* This is not a typo: we overwrite the trailing \0 of the
1485 file name; this is just how the data is laid out. */
1486 memcpy (buffer + zdir->filename_length,
1487 jcf->buffer, jcf->buffer_end - jcf->buffer);
1489 compile_resource_data (file_name, buffer,
1490 jcf->buffer_end - jcf->buffer);
1491 JCF_FINISH (jcf);
1492 free (jcf);
1493 free (buffer);
1495 break;
1497 default:
1498 gcc_unreachable ();
1503 /* Read all the entries of the zip file, creates a class and a JCF. Sets the
1504 jcf up for further processing and link it to the created class. */
1506 static void
1507 process_zip_dir (FILE *finput)
1509 int i;
1510 ZipDirectory *zdir;
1512 for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1513 i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1515 char *class_name, *file_name, *class_name_in_zip_dir;
1516 tree class;
1517 JCF *jcf;
1519 class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1521 /* Here we skip non-class files; we handle them later. */
1522 if (classify_zip_file (zdir) != 1)
1523 continue;
1525 class_name = compute_class_name (zdir);
1526 file_name = XNEWVEC (char, zdir->filename_length+1);
1527 jcf = ggc_alloc (sizeof (JCF));
1528 JCF_ZERO (jcf);
1530 strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
1531 file_name [zdir->filename_length] = '\0';
1533 class = lookup_class (get_identifier (class_name));
1535 jcf->read_state = finput;
1536 jcf->filbuf = jcf_filbuf_from_stdio;
1537 jcf->java_source = 0;
1538 jcf->classname = class_name;
1539 jcf->filename = file_name;
1540 jcf->zipd = zdir;
1542 TYPE_JCF (class) = jcf;
1546 /* Initialization. */
1548 void
1549 init_jcf_parse (void)
1551 init_src_parse ();
1554 #include "gt-java-jcf-parse.h"