* config/fp-bit.h (LSHIFT): Take shift count parameter.
[official-gcc.git] / gcc / java / jcf-parse.c
blob5d22f88d843b346c9f83fcd3b26123f432ddc825
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 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 package_name = NULL_TREE, tmp;
448 tree this_class;
449 int j = JPOOL_USHORT1 (jcf, i);
450 /* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */
451 tree class_name = unmangle_classname ((const char *) JPOOL_UTF_DATA (jcf, j),
452 JPOOL_UTF_LENGTH (jcf, j));
453 this_class = lookup_class (class_name);
454 #ifdef USE_MAPPED_LOCATION
456 tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
457 const char *sfname = IDENTIFIER_POINTER (source_name);
458 linemap_add (&line_table, LC_ENTER, false, sfname, 0);
459 input_location = linemap_line_start (&line_table, 0, 1);
460 file_start_location = input_location;
461 DECL_SOURCE_LOCATION (TYPE_NAME (this_class)) = input_location;
462 if (main_input_filename == NULL && jcf == main_jcf)
463 main_input_filename = sfname;
465 #else
466 input_location = DECL_SOURCE_LOCATION (TYPE_NAME (this_class));
467 if (main_input_filename == NULL && jcf == main_jcf)
468 main_input_filename = input_filename;
469 #endif
471 jcf->cpool.data[i].t = this_class;
472 JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
473 split_qualified_name (&package_name, &tmp,
474 DECL_NAME (TYPE_NAME (this_class)));
475 TYPE_PACKAGE (this_class) = package_name;
476 return this_class;
480 /* Get the class of the CONSTANT_Class whose constant pool index is I. */
482 tree
483 get_class_constant (JCF *jcf, int i)
485 tree type;
486 if (i <= 0 || i >= JPOOL_SIZE (jcf)
487 || (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) != CONSTANT_Class)
488 abort ();
490 if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)
492 int name_index = JPOOL_USHORT1 (jcf, i);
493 /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */
494 const char *name = (const char *) JPOOL_UTF_DATA (jcf, name_index);
495 int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
497 if (name[0] == '[') /* Handle array "classes". */
498 type = TREE_TYPE (parse_signature_string ((const unsigned char *) name, nlength));
499 else
501 tree cname = unmangle_classname (name, nlength);
502 type = lookup_class (cname);
504 jcf->cpool.data[i].t = type;
505 JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
507 else
508 type = jcf->cpool.data[i].t;
509 return type;
512 /* Read a class with the fully qualified-name NAME.
513 Return 1 iff we read the requested file.
514 (It is still possible we failed if the file did not
515 define the class it is supposed to.) */
518 read_class (tree name)
520 JCF this_jcf, *jcf;
521 tree icv, class = NULL_TREE;
522 tree save_current_class = current_class;
523 tree save_output_class = output_class;
524 location_t save_location = input_location;
525 JCF *save_current_jcf = current_jcf;
527 if ((icv = IDENTIFIER_CLASS_VALUE (name)) != NULL_TREE)
529 class = TREE_TYPE (icv);
530 jcf = TYPE_JCF (class);
532 else
533 jcf = NULL;
535 if (jcf == NULL)
537 const char* path_name;
538 this_jcf.zipd = NULL;
539 jcf = &this_jcf;
541 path_name = find_class (IDENTIFIER_POINTER (name),
542 IDENTIFIER_LENGTH (name),
543 &this_jcf, 1);
544 if (path_name == 0)
545 return 0;
546 else
547 free((char *) path_name);
550 current_jcf = jcf;
552 if (current_jcf->java_source)
554 const char *filename = current_jcf->filename;
555 char *real_path;
556 tree given_file, real_file;
557 FILE *finput;
558 int generate;
560 java_parser_context_save_global ();
561 java_push_parser_context ();
563 given_file = get_identifier (filename);
564 filename = IDENTIFIER_POINTER (given_file);
565 real_path = lrealpath (filename);
566 real_file = get_identifier (real_path);
567 free (real_path);
569 generate = IS_A_COMMAND_LINE_FILENAME_P (given_file);
570 output_class = current_class = NULL_TREE;
571 current_function_decl = NULL_TREE;
573 if (! HAS_BEEN_ALREADY_PARSED_P (real_file))
575 if (! (finput = fopen (filename, "r")))
576 fatal_error ("can't reopen %s: %m", filename);
578 parse_source_file_1 (real_file, filename, finput);
579 parse_source_file_2 ();
580 parse_source_file_3 ();
582 if (fclose (finput))
583 fatal_error ("can't close %s: %m", input_filename);
584 #ifdef USE_MAPPED_LOCATION
585 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
586 #endif
588 JCF_FINISH (current_jcf);
589 java_pop_parser_context (generate);
590 java_parser_context_restore_global ();
592 else
594 if (class == NULL_TREE || ! CLASS_PARSED_P (class))
596 java_parser_context_save_global ();
597 java_push_parser_context ();
598 output_class = current_class = class;
599 ctxp->save_location = input_location;
600 if (JCF_SEEN_IN_ZIP (current_jcf))
601 read_zip_member(current_jcf,
602 current_jcf->zipd, current_jcf->zipd->zipf);
603 jcf_parse (current_jcf);
604 /* Parsing might change the class, in which case we have to
605 put it back where we found it. */
606 if (current_class != class && icv != NULL_TREE)
607 TREE_TYPE (icv) = current_class;
608 class = current_class;
609 java_pop_parser_context (0);
610 java_parser_context_restore_global ();
612 layout_class (class);
613 load_inner_classes (class);
616 output_class = save_output_class;
617 current_class = save_current_class;
618 input_location = save_location;
619 current_jcf = save_current_jcf;
620 return 1;
623 /* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if
624 called from the parser, otherwise it's a RECORD_TYPE node. If
625 VERBOSE is 1, print error message on failure to load a class. */
626 void
627 load_class (tree class_or_name, int verbose)
629 tree name, saved;
630 int class_loaded = 0;
631 tree class_decl = NULL_TREE;
632 bool is_compiled_class = false;
634 /* We've already failed, don't try again. */
635 if (TREE_CODE (class_or_name) == RECORD_TYPE
636 && TYPE_DUMMY (class_or_name))
637 return;
639 /* class_or_name can be the name of the class we want to load */
640 if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
641 name = class_or_name;
642 /* In some cases, it's a dependency that we process earlier that
643 we though */
644 else if (TREE_CODE (class_or_name) == TREE_LIST)
645 name = TYPE_NAME (TREE_PURPOSE (class_or_name));
646 /* Or it's a type in the making */
647 else
648 name = DECL_NAME (TYPE_NAME (class_or_name));
650 class_decl = IDENTIFIER_CLASS_VALUE (name);
651 if (class_decl != NULL_TREE)
653 tree type = TREE_TYPE (class_decl);
654 is_compiled_class
655 = ((TYPE_JCF (type) && JCF_SEEN_IN_ZIP (TYPE_JCF (type)))
656 || CLASS_FROM_CURRENTLY_COMPILED_P (type));
659 /* If the class is from source code, then it must already be loaded. */
660 class_decl = IDENTIFIER_CLASS_VALUE (name);
661 if (class_decl && CLASS_FROM_SOURCE_P (TREE_TYPE (class_decl)))
662 return;
664 saved = name;
666 /* If flag_verify_invocations is unset, we don't try to load a class
667 unless we're looking for Object (which is fixed by the ABI) or
668 it's a class that we're going to compile. */
669 if (flag_verify_invocations
670 || class_or_name == object_type_node
671 || is_compiled_class
672 || TREE_CODE (class_or_name) == IDENTIFIER_NODE)
674 while (1)
676 char *separator;
678 /* We've already loaded it. */
679 if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE)
681 tree tmp_decl = IDENTIFIER_CLASS_VALUE (name);
682 if (CLASS_PARSED_P (TREE_TYPE (tmp_decl)))
683 break;
686 if (read_class (name))
687 break;
689 /* We failed loading name. Now consider that we might be looking
690 for an inner class. */
691 if ((separator = strrchr (IDENTIFIER_POINTER (name), '$'))
692 || (separator = strrchr (IDENTIFIER_POINTER (name), '.')))
694 int c = *separator;
695 *separator = '\0';
696 name = get_identifier (IDENTIFIER_POINTER (name));
697 *separator = c;
699 /* Otherwise, we failed, we bail. */
700 else
701 break;
705 /* have we found the class we're looking for? */
706 tree type_decl = IDENTIFIER_CLASS_VALUE (saved);
707 tree type = type_decl ? TREE_TYPE (type_decl) : NULL;
708 class_loaded = type && CLASS_PARSED_P (type);
712 if (!class_loaded)
714 if (flag_verify_invocations || ! flag_indirect_dispatch
715 || flag_emit_class_files)
717 if (verbose)
718 error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
720 else if (verbose)
722 /* This is just a diagnostic during testing, not a real problem. */
723 if (!quiet_flag)
724 warning (0, "cannot find file for class %s",
725 IDENTIFIER_POINTER (saved));
727 /* Fake it. */
728 if (TREE_CODE (class_or_name) == RECORD_TYPE)
730 set_super_info (0, class_or_name, object_type_node, 0);
731 TYPE_DUMMY (class_or_name) = 1;
732 /* We won't be able to output any debug info for this class. */
733 DECL_IGNORED_P (TYPE_NAME (class_or_name)) = 1;
739 /* Parse the .class file JCF. */
741 static void
742 jcf_parse (JCF* jcf)
744 int i, code;
746 if (jcf_parse_preamble (jcf) != 0)
747 fatal_error ("not a valid Java .class file");
748 code = jcf_parse_constant_pool (jcf);
749 if (code != 0)
750 fatal_error ("error while parsing constant pool");
751 code = verify_constant_pool (jcf);
752 if (code > 0)
753 fatal_error ("error in constant pool entry #%d\n", code);
755 jcf_parse_class (jcf);
756 if (main_class == NULL_TREE)
757 main_class = current_class;
758 if (! quiet_flag && TYPE_NAME (current_class))
759 fprintf (stderr, " %s %s",
760 (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class",
761 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
762 if (CLASS_PARSED_P (current_class))
764 /* FIXME - where was first time */
765 fatal_error ("reading class %s for the second time from %s",
766 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))),
767 jcf->filename);
769 CLASS_PARSED_P (current_class) = 1;
771 for (i = 1; i < JPOOL_SIZE(jcf); i++)
773 switch (JPOOL_TAG (jcf, i))
775 case CONSTANT_Class:
776 get_class_constant (jcf, i);
777 break;
781 code = jcf_parse_fields (jcf);
782 if (code != 0)
783 fatal_error ("error while parsing fields");
784 code = jcf_parse_methods (jcf);
785 if (code != 0)
786 fatal_error ("error while parsing methods");
787 code = jcf_parse_final_attributes (jcf);
788 if (code != 0)
789 fatal_error ("error while parsing final attributes");
790 #ifdef USE_MAPPED_LOCATION
791 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
792 #endif
794 /* The fields of class_type_node are already in correct order. */
795 if (current_class != class_type_node && current_class != object_type_node)
796 TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));
798 if (current_class == object_type_node)
800 layout_class_methods (object_type_node);
801 /* If we don't have the right archive, emit a verbose warning.
802 If we're generating bytecode, emit the warning only if
803 -fforce-classes-archive-check was specified. */
804 if (!jcf->right_zip
805 && (!flag_emit_class_files || flag_force_classes_archive_check))
806 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);
808 else
809 all_class_list = tree_cons (NULL_TREE,
810 TYPE_NAME (current_class), all_class_list );
813 /* If we came across inner classes, load them now. */
814 static void
815 load_inner_classes (tree cur_class)
817 tree current;
818 for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (cur_class)); current;
819 current = TREE_CHAIN (current))
821 tree name = DECL_NAME (TREE_PURPOSE (current));
822 tree decl = IDENTIFIER_GLOBAL_VALUE (name);
823 if (decl && ! CLASS_LOADED_P (TREE_TYPE (decl))
824 && !CLASS_BEING_LAIDOUT (TREE_TYPE (decl)))
825 load_class (name, 1);
829 static void
830 duplicate_class_warning (const char *filename)
832 location_t warn_loc;
833 #ifdef USE_MAPPED_LOCATION
834 linemap_add (&line_table, LC_RENAME, 0, filename, 0);
835 warn_loc = linemap_line_start (&line_table, 0, 1);
836 #else
837 warn_loc.file = filename;
838 warn_loc.line = 0;
839 #endif
840 warning (0, "%Hduplicate class will only be compiled once", &warn_loc);
843 static void
844 parse_class_file (void)
846 tree method;
847 location_t save_location = input_location;
849 java_layout_seen_class_methods ();
851 input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class));
852 file_start_location = input_location;
853 (*debug_hooks->start_source_file) (input_line, input_filename);
855 gen_indirect_dispatch_tables (current_class);
857 java_mark_class_local (current_class);
859 for (method = TYPE_METHODS (current_class);
860 method != NULL_TREE; method = TREE_CHAIN (method))
862 JCF *jcf = current_jcf;
864 if (METHOD_ABSTRACT (method) || METHOD_DUMMY (method))
865 continue;
867 if (METHOD_NATIVE (method))
869 tree arg;
870 int decl_max_locals;
872 if (! flag_jni)
873 continue;
874 /* We need to compute the DECL_MAX_LOCALS. We need to take
875 the wide types into account too. */
876 for (arg = TYPE_ARG_TYPES (TREE_TYPE (method)), decl_max_locals = 0;
877 arg != end_params_node;
878 arg = TREE_CHAIN (arg), decl_max_locals += 1)
880 if (TREE_VALUE (arg) && TYPE_IS_WIDE (TREE_VALUE (arg)))
881 decl_max_locals += 1;
883 DECL_MAX_LOCALS (method) = decl_max_locals;
884 start_java_method (method);
885 give_name_to_locals (jcf);
886 *get_stmts () = build_jni_stub (method);
887 end_java_method ();
888 continue;
891 if (DECL_CODE_OFFSET (method) == 0)
893 current_function_decl = method;
894 error ("missing Code attribute");
895 continue;
898 input_location = file_start_location;
899 if (DECL_LINENUMBERS_OFFSET (method))
901 int i;
902 int min_line = 0;
903 unsigned char *ptr;
904 JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method));
905 linenumber_count = i = JCF_readu2 (jcf);
906 linenumber_table = ptr = jcf->read_ptr;
908 for (ptr += 2; --i >= 0; ptr += 4)
910 int line = GET_u2 (ptr);
911 /* Set initial input_line to smallest linenumber.
912 * Needs to be set before init_function_start. */
913 if (min_line == 0 || line < min_line)
914 min_line = line;
916 #ifdef USE_MAPPED_LOCATION
917 if (min_line != 0)
918 input_location = linemap_line_start (&line_table, min_line, 1);
919 #else
920 if (min_line != 0)
921 input_line = min_line;
922 #endif
924 else
926 linenumber_table = NULL;
927 linenumber_count = 0;
930 start_java_method (method);
932 note_instructions (jcf, method);
934 give_name_to_locals (jcf);
936 /* Bump up start_label_pc_this_method so we get a unique label number
937 and reset highest_label_pc_this_method. */
938 if (highest_label_pc_this_method >= 0)
940 /* We adjust to the next multiple of 1000. This is just a frill
941 so the last 3 digits of the label number match the bytecode
942 offset, which might make debugging marginally more convenient. */
943 start_label_pc_this_method
944 = ((((start_label_pc_this_method + highest_label_pc_this_method)
945 / 1000)
946 + 1)
947 * 1000);
948 highest_label_pc_this_method = -1;
951 /* Convert bytecode to trees. */
952 expand_byte_code (jcf, method);
954 end_java_method ();
957 if (flag_emit_class_files)
958 write_classfile (current_class);
960 finish_class ();
962 (*debug_hooks->end_source_file) (LOCATION_LINE (save_location));
963 input_location = save_location;
966 /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */
968 static void
969 parse_source_file_1 (tree real_file, const char *filename, FILE *finput)
971 int save_error_count = java_error_count;
973 /* Mark the file as parsed. */
974 HAS_BEEN_ALREADY_PARSED_P (real_file) = 1;
976 lang_init_source (1); /* Error msgs have no method prototypes */
978 /* There's no point in trying to find the current encoding unless we
979 are going to do something intelligent with it -- hence the test
980 for iconv. */
981 #if defined (HAVE_LOCALE_H) && defined (HAVE_ICONV) && defined (HAVE_LANGINFO_CODESET)
982 setlocale (LC_CTYPE, "");
983 if (current_encoding == NULL)
984 current_encoding = nl_langinfo (CODESET);
985 #endif
986 if (current_encoding == NULL || *current_encoding == '\0')
987 current_encoding = DEFAULT_ENCODING;
989 #ifdef USE_MAPPED_LOCATION
990 linemap_add (&line_table, LC_ENTER, false, filename, 0);
991 input_location = linemap_line_start (&line_table, 0, 125);
992 #else
993 input_filename = filename;
994 input_line = 0;
995 #endif
996 ctxp->file_start_location = input_location;
997 ctxp->filename = filename;
999 jcf_dependency_add_file (input_filename, 0);
1001 /* Initialize the parser */
1002 java_init_lex (finput, current_encoding);
1003 java_parse_abort_on_error ();
1005 java_parse (); /* Parse and build partial tree nodes. */
1006 java_parse_abort_on_error ();
1009 /* Process a parsed source file, resolving names etc. */
1011 static void
1012 parse_source_file_2 (void)
1014 int save_error_count = java_error_count;
1015 flag_verify_invocations = true;
1016 java_complete_class (); /* Parse unsatisfied class decl. */
1017 java_parse_abort_on_error ();
1020 static void
1021 parse_source_file_3 (void)
1023 int save_error_count = java_error_count;
1024 java_check_circular_reference (); /* Check on circular references */
1025 java_parse_abort_on_error ();
1026 java_fix_constructors (); /* Fix the constructors */
1027 java_parse_abort_on_error ();
1028 java_reorder_fields (); /* Reorder the fields */
1031 void
1032 add_predefined_file (tree name)
1034 predef_filenames = tree_cons (NULL_TREE, name, predef_filenames);
1038 predefined_filename_p (tree node)
1040 tree iter;
1042 for (iter = predef_filenames; iter != NULL_TREE; iter = TREE_CHAIN (iter))
1044 if (TREE_VALUE (iter) == node)
1045 return 1;
1047 return 0;
1050 /* Generate a function that does all static initialization for this
1051 translation unit. */
1053 static void
1054 java_emit_static_constructor (void)
1056 tree body = NULL;
1058 emit_register_classes (&body);
1059 write_resource_constructor (&body);
1061 if (body)
1062 cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
1065 void
1066 java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
1068 int filename_count = 0;
1069 location_t save_location = input_location;
1070 char *file_list = NULL, *list, *next;
1071 tree node;
1072 FILE *finput = NULL;
1073 int in_quotes = 0;
1075 if (flag_filelist_file)
1077 int avail = 2000;
1078 finput = fopen (main_input_filename, "r");
1079 if (finput == NULL)
1080 fatal_error ("can't open %s: %m", input_filename);
1081 list = xmalloc(avail);
1082 next = list;
1083 for (;;)
1085 int count;
1086 if (avail < 500)
1088 count = next - list;
1089 avail = 2 * (count + avail);
1090 list = xrealloc (list, avail);
1091 next = list + count;
1092 avail = avail - count;
1094 /* Subtract to to guarantee space for final '\0'. */
1095 count = fread (next, 1, avail - 1, finput);
1096 if (count == 0)
1098 if (! feof (finput))
1099 fatal_error ("error closing %s: %m", input_filename);
1100 *next = '\0';
1101 break;
1103 avail -= count;
1104 next += count;
1106 fclose (finput);
1107 finput = NULL;
1108 file_list = list;
1110 else
1111 list = (char *) main_input_filename;
1113 while (list)
1115 for (next = list; ; )
1117 char ch = *next;
1118 if (flag_filelist_file && ! in_quotes
1119 && (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' '
1120 || ch == '&') /* FIXME */)
1122 if (next == list)
1124 next++;
1125 list = next;
1126 continue;
1128 else
1130 *next++ = '\0';
1131 break;
1134 if (flag_filelist_file && ch == '"')
1136 in_quotes = ! in_quotes;
1137 *next++ = '\0';
1138 if (in_quotes)
1139 list = next;
1140 else
1141 break;
1143 if (ch == '\0')
1145 next = NULL;
1146 break;
1148 next++;
1151 if (list[0])
1153 node = get_identifier (list);
1155 filename_count++;
1157 /* Exclude file that we see twice on the command line. */
1159 if (IS_A_COMMAND_LINE_FILENAME_P (node))
1160 duplicate_class_warning (IDENTIFIER_POINTER (node));
1161 else
1163 tree file_decl = build_decl (TRANSLATION_UNIT_DECL, node, NULL);
1164 TREE_CHAIN (file_decl) = current_file_list;
1165 current_file_list = file_decl;
1166 IS_A_COMMAND_LINE_FILENAME_P (node) = 1;
1169 list = next;
1172 if (file_list != NULL)
1173 free (file_list);
1175 if (filename_count == 0)
1176 warning (0, "no input file specified");
1178 if (resource_name)
1180 const char *resource_filename;
1182 /* Only one resource file may be compiled at a time. */
1183 assert (TREE_CHAIN (current_file_list) == NULL);
1185 resource_filename = IDENTIFIER_POINTER (DECL_NAME (current_file_list));
1186 compile_resource_file (resource_name, resource_filename);
1188 goto finish;
1191 current_jcf = main_jcf;
1192 current_file_list = nreverse (current_file_list);
1193 for (node = current_file_list; node; node = TREE_CHAIN (node))
1195 unsigned char magic_string[4];
1196 char *real_path;
1197 uint32 magic = 0;
1198 tree name = DECL_NAME (node);
1199 tree real_file;
1200 const char *filename = IDENTIFIER_POINTER (name);
1202 /* Skip already parsed files */
1203 real_path = lrealpath (filename);
1204 real_file = get_identifier (real_path);
1205 free (real_path);
1206 if (HAS_BEEN_ALREADY_PARSED_P (real_file))
1207 continue;
1209 /* Close previous descriptor, if any */
1210 if (finput && fclose (finput))
1211 fatal_error ("can't close input file %s: %m", main_input_filename);
1213 finput = fopen (filename, "rb");
1214 if (finput == NULL)
1215 fatal_error ("can't open %s: %m", filename);
1217 #ifdef IO_BUFFER_SIZE
1218 setvbuf (finput, xmalloc (IO_BUFFER_SIZE),
1219 _IOFBF, IO_BUFFER_SIZE);
1220 #endif
1222 /* Figure what kind of file we're dealing with */
1223 if (fread (magic_string, 1, 4, finput) == 4)
1225 fseek (finput, 0L, SEEK_SET);
1226 magic = GET_u4 (magic_string);
1228 if (magic == 0xcafebabe)
1230 CLASS_FILE_P (node) = 1;
1231 current_jcf = ggc_alloc (sizeof (JCF));
1232 JCF_ZERO (current_jcf);
1233 current_jcf->read_state = finput;
1234 current_jcf->filbuf = jcf_filbuf_from_stdio;
1235 jcf_parse (current_jcf);
1236 DECL_SOURCE_LOCATION (node) = file_start_location;
1237 TYPE_JCF (current_class) = current_jcf;
1238 if (CLASS_FROM_CURRENTLY_COMPILED_P (current_class))
1240 /* We've already compiled this class. */
1241 duplicate_class_warning (filename);
1242 continue;
1244 CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1245 TREE_TYPE (node) = current_class;
1247 else if (magic == (JCF_u4)ZIPMAGIC)
1249 main_jcf = ggc_alloc (sizeof (JCF));
1250 JCF_ZERO (main_jcf);
1251 main_jcf->read_state = finput;
1252 main_jcf->filbuf = jcf_filbuf_from_stdio;
1253 #ifdef USE_MAPPED_LOCATION
1254 linemap_add (&line_table, LC_ENTER, false, filename, 0);
1255 input_location = linemap_line_start (&line_table, 0, 1);
1256 #endif
1257 if (open_in_zip (main_jcf, filename, NULL, 0) < 0)
1258 fatal_error ("bad zip/jar file %s", filename);
1259 localToFile = SeenZipFiles;
1260 /* Register all the classes defined there. */
1261 process_zip_dir (main_jcf->read_state);
1262 #ifdef USE_MAPPED_LOCATION
1263 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1264 #endif
1265 parse_zip_file_entries ();
1267 else
1269 java_push_parser_context ();
1270 java_parser_context_save_global ();
1272 parse_source_file_1 (real_file, filename, finput);
1273 java_parser_context_restore_global ();
1274 java_pop_parser_context (1);
1275 #ifdef USE_MAPPED_LOCATION
1276 linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1277 #endif
1281 for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
1283 input_location = ctxp->file_start_location;
1284 parse_source_file_2 ();
1287 for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
1289 input_location = ctxp->file_start_location;
1290 parse_source_file_3 ();
1293 for (node = current_file_list; node; node = TREE_CHAIN (node))
1295 input_location = DECL_SOURCE_LOCATION (node);
1296 if (CLASS_FILE_P (node))
1298 /* FIXME: These two flags really should be independent. We
1299 should be able to compile fully binary compatible, but
1300 with flag_verify_invocations on. */
1301 flag_verify_invocations = ! flag_indirect_dispatch;
1302 output_class = current_class = TREE_TYPE (node);
1304 current_jcf = TYPE_JCF (current_class);
1305 layout_class (current_class);
1306 load_inner_classes (current_class);
1307 parse_class_file ();
1308 JCF_FINISH (current_jcf);
1311 input_location = save_location;
1313 java_expand_classes ();
1314 if (java_report_errors () || flag_syntax_only)
1315 return;
1317 /* Expand all classes compiled from source. */
1318 java_finish_classes ();
1320 finish:
1321 /* Arrange for any necessary initialization to happen. */
1322 java_emit_static_constructor ();
1324 /* Only finalize the compilation unit after we've told cgraph which
1325 functions have their addresses stored. */
1326 cgraph_finalize_compilation_unit ();
1327 cgraph_optimize ();
1331 /* Return the name of the class corresponding to the name of the file
1332 in this zip entry. The result is newly allocated using ALLOC. */
1333 static char *
1334 compute_class_name (struct ZipDirectory *zdir)
1336 char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1337 char *class_name;
1338 int i;
1339 int filename_length = zdir->filename_length;
1341 while (filename_length > 2 && strncmp (class_name_in_zip_dir, "./", 2) == 0)
1343 class_name_in_zip_dir += 2;
1344 filename_length -= 2;
1347 filename_length -= strlen (".class");
1348 class_name = ALLOC (filename_length + 1);
1349 memcpy (class_name, class_name_in_zip_dir, filename_length);
1350 class_name [filename_length] = '\0';
1352 for (i = 0; i < filename_length; i++)
1353 if (class_name[i] == '/')
1354 class_name[i] = '.';
1356 return class_name;
1359 /* Return 0 if we should skip this entry, 1 if it is a .class file, 2
1360 if it is a property file of some sort. */
1361 static int
1362 classify_zip_file (struct ZipDirectory *zdir)
1364 char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1366 if (zdir->filename_length > 6
1367 && !strncmp (&class_name_in_zip_dir[zdir->filename_length - 6],
1368 ".class", 6))
1369 return 1;
1371 /* For now we drop the manifest, but not other information. */
1372 if (zdir->filename_length == 20
1373 && !strncmp (class_name_in_zip_dir, "META-INF/MANIFEST.MF", 20))
1374 return 0;
1376 /* Drop directory entries. */
1377 if (zdir->filename_length > 0
1378 && class_name_in_zip_dir[zdir->filename_length - 1] == '/')
1379 return 0;
1381 return 2;
1384 /* Process all class entries found in the zip file. */
1385 static void
1386 parse_zip_file_entries (void)
1388 struct ZipDirectory *zdir;
1389 int i;
1391 for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1392 i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1394 tree class;
1396 switch (classify_zip_file (zdir))
1398 case 0:
1399 continue;
1401 case 1:
1403 char *class_name = compute_class_name (zdir);
1404 class = lookup_class (get_identifier (class_name));
1405 FREE (class_name);
1406 current_jcf = TYPE_JCF (class);
1407 output_class = current_class = class;
1409 if (CLASS_FROM_CURRENTLY_COMPILED_P (current_class))
1411 /* We've already compiled this class. */
1412 duplicate_class_warning (current_jcf->filename);
1413 break;
1416 CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1418 if (TYPE_DUMMY (class))
1420 /* This is a dummy class, and now we're compiling it
1421 for real. */
1422 abort ();
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 = ALLOC (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 = ALLOC (sizeof (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 = ALLOC (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 abort ();
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 = ALLOC (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"