OSDN Git Service

2004-11-26 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-parse.c
1 /* Parser for Java(TM) .class files.
2    Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3    Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
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.
11
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.
16
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.
21
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.  */
25
26 /* Written by Per Bothner <bothner@cygnus.com> */
27
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"
46
47 #ifdef HAVE_LOCALE_H
48 #include <locale.h>
49 #endif
50
51 #ifdef HAVE_LANGINFO_CODESET
52 #include <langinfo.h>
53 #endif
54
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)
70
71 #include "jcf.h"
72
73 extern struct obstack temporary_obstack;
74
75 static GTY(()) tree parse_roots[3];
76
77 /* The FIELD_DECL for the current field.  */
78 #define current_field parse_roots[0]
79
80 /* The METHOD_DECL for the current method.  */
81 #define current_method parse_roots[1]
82
83 /* A list of TRANSLATION_UNIT_DECLs for the files to be compiled.  */
84 #define current_file_list parse_roots[2]
85
86 /* Line 0 in current file, if compiling from bytecode. */
87 static location_t file_start_location;
88
89 /* The Java archive that provides main_class;  the main input file. */
90 static GTY(()) struct JCF * main_jcf;
91
92 static struct ZipFile *localToFile;
93
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);
109
110 /* Handle "Deprecated" attribute.  */
111 static void
112 handle_deprecated (void)
113 {
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
121     {
122       /* Shouldn't happen.  */
123       abort ();
124     }
125 }
126
127 /* Handle "SourceFile" attribute. */
128
129 static void
130 set_source_filename (JCF *jcf, int index)
131 {
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)
137     {
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;
146     }
147   if (strchr (sfname, '/') == NULL && strchr (sfname, '\\') == NULL)
148     {
149       const char *class_name
150         = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
151       char *dot = strrchr (class_name, '.');
152       if (dot != NULL)
153         {
154           int i = dot - class_name + 1;
155           /* Concatenate current package prefix with new sfname. */
156           char *buf = xmalloc (i+new_len+3);
157           memcpy (buf, class_name, i);
158           strcpy (buf + i, sfname);
159           /* Replace '.' by DIR_SEPARATOR. */
160           for (; i >= 0;  i--)
161             {
162               if (buf[i] == '.')
163                 buf[i] = DIR_SEPARATOR;
164             }
165           sfname_id = get_identifier (buf);
166           sfname = IDENTIFIER_POINTER (sfname_id);
167         }
168     }
169       
170 #ifdef USE_MAPPED_LOCATION
171   line_table.maps[line_table.used-1].to_file = sfname;
172 #else
173   input_filename = sfname;
174   DECL_SOURCE_LOCATION (TYPE_NAME (current_class)) = input_location;
175   file_start_location = input_location;
176 #endif
177   if (current_class == main_class) main_input_filename = sfname;
178 }
179
180 #define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)
181
182 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
183 { tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
184   output_class = current_class = give_name_to_class (jcf, THIS); \
185   set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
186
187 #define HANDLE_CLASS_INTERFACE(INDEX) \
188   add_interface (current_class, get_class_constant (jcf, INDEX))
189
190 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
191 { int sig_index = SIGNATURE; \
192   current_field = add_field (current_class, get_name_constant (jcf, NAME), \
193                              parse_signature (jcf, sig_index), ACCESS_FLAGS); \
194  set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); \
195  if ((ACCESS_FLAGS) & ACC_FINAL) \
196    MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (current_field); \
197 }
198
199 #define HANDLE_END_FIELDS() \
200   (current_field = NULL_TREE)
201
202 #define HANDLE_CONSTANTVALUE(INDEX) \
203 { tree constant;  int index = INDEX; \
204   if (! flag_emit_class_files && JPOOL_TAG (jcf, index) == CONSTANT_String) { \
205     tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \
206     constant = build_utf8_ref (name); \
207   } \
208   else \
209     constant = get_constant (jcf, index); \
210   set_constant_value (current_field, constant); }
211
212 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
213  (current_method = add_method (current_class, ACCESS_FLAGS, \
214                                get_name_constant (jcf, NAME), \
215                                get_name_constant (jcf, SIGNATURE)), \
216   DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \
217   DECL_LINENUMBERS_OFFSET (current_method) = 0)
218
219 #define HANDLE_END_METHODS() \
220 { current_method = NULL_TREE; }
221
222 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
223 { DECL_MAX_STACK (current_method) = (MAX_STACK); \
224   DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \
225   DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \
226   DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); }
227
228 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
229 { int n = (COUNT); \
230   DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
231   JCF_SKIP (jcf, n * 10); }
232
233 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
234 { int n = (COUNT); \
235   DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
236   JCF_SKIP (jcf, n * 4); }
237
238 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
239 { \
240   int n = COUNT; \
241   tree list = DECL_FUNCTION_THROWS (current_method); \
242   while (--n >= 0) \
243     { \
244       tree thrown_class = get_class_constant (jcf, JCF_readu2 (jcf)); \
245       list = tree_cons (NULL_TREE, thrown_class, list); \
246     } \
247   DECL_FUNCTION_THROWS (current_method) = nreverse (list); \
248 }
249
250 #define HANDLE_DEPRECATED_ATTRIBUTE()  handle_deprecated ()
251
252 /* Link seen inner classes to their outer context and register the
253    inner class to its outer context. They will be later loaded.  */
254 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
255   handle_innerclass_attribute (COUNT, jcf)
256
257 #define HANDLE_SYNTHETIC_ATTRIBUTE()                                    \
258 {                                                                       \
259   /* Irrelevant decls should have been nullified by the END macros.     \
260      We only handle the `Synthetic' attribute on method DECLs.          \
261      DECL_ARTIFICIAL on fields is used for something else (See          \
262      PUSH_FIELD in java-tree.h) */                                      \
263   if (current_method)                                                   \
264     DECL_ARTIFICIAL (current_method) = 1;                               \
265 }
266
267 #define HANDLE_GCJCOMPILED_ATTRIBUTE()          \
268 {                                               \
269   if (current_class == object_type_node)        \
270     jcf->right_zip = 1;                         \
271 }
272
273 #include "jcf-reader.c"
274
275 tree
276 parse_signature (JCF *jcf, int sig_index)
277 {
278   if (sig_index <= 0 || sig_index >= JPOOL_SIZE (jcf)
279       || JPOOL_TAG (jcf, sig_index) != CONSTANT_Utf8)
280     abort ();
281   else
282     return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index),
283                                    JPOOL_UTF_LENGTH (jcf, sig_index));
284 }
285
286 tree
287 get_constant (JCF *jcf, int index)
288 {
289   tree value;
290   int tag;
291   if (index <= 0 || index >= JPOOL_SIZE(jcf))
292     goto bad;
293   tag = JPOOL_TAG (jcf, index);
294   if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
295     return jcf->cpool.data[index].t;
296   switch (tag)
297     {
298     case CONSTANT_Integer:
299       {
300         jint num = JPOOL_INT(jcf, index);
301         value = build_int_cst (int_type_node, num);
302         break;
303       }
304     case CONSTANT_Long:
305       {
306         unsigned HOST_WIDE_INT num = JPOOL_UINT (jcf, index);
307         unsigned HOST_WIDE_INT lo;
308         HOST_WIDE_INT hi;
309         
310         lshift_double (num, 0, 32, 64, &lo, &hi, 0);
311         num = JPOOL_UINT (jcf, index+1);
312         add_double (lo, hi, num, 0, &lo, &hi);
313         value = build_int_cst_wide (long_type_node, lo, hi);
314         value = force_fit_type (value, 0, false, false);
315         break;
316       }
317
318     case CONSTANT_Float:
319       {
320         jint num = JPOOL_INT(jcf, index);
321         long buf = num;
322         REAL_VALUE_TYPE d;
323
324         real_from_target_fmt (&d, &buf, &ieee_single_format);
325         value = build_real (float_type_node, d);
326         break;
327       }
328
329     case CONSTANT_Double:
330       {
331         long buf[2], lo, hi;
332         REAL_VALUE_TYPE d;
333
334         hi = JPOOL_UINT (jcf, index);
335         lo = JPOOL_UINT (jcf, index+1);
336
337         if (FLOAT_WORDS_BIG_ENDIAN)
338           buf[0] = hi, buf[1] = lo;
339         else
340           buf[0] = lo, buf[1] = hi;
341
342         real_from_target_fmt (&d, buf, &ieee_double_format);
343         value = build_real (double_type_node, d);
344         break;
345       }
346
347     case CONSTANT_String:
348       {
349         tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
350         const char *utf8_ptr = IDENTIFIER_POINTER (name);
351         int utf8_len = IDENTIFIER_LENGTH (name);
352         const unsigned char *utf8;
353         int i;
354
355         /* Check for a malformed Utf8 string.  */
356         utf8 = (const unsigned char *) utf8_ptr;
357         i = utf8_len;
358         while (i > 0)
359           {
360             int char_len = UT8_CHAR_LENGTH (*utf8);
361             if (char_len < 0 || char_len > 3 || char_len > i)
362               fatal_error ("bad string constant");
363
364             utf8 += char_len;
365             i -= char_len;
366           }
367
368         /* Allocate a new string value.  */
369         value = build_string (utf8_len, utf8_ptr);
370         TREE_TYPE (value) = build_pointer_type (string_type_node);
371       }
372       break;
373     default:
374       goto bad;
375     }
376   JPOOL_TAG (jcf, index) = tag | CONSTANT_ResolvedFlag;
377   jcf->cpool.data[index].t = value;
378   return value;
379  bad:
380   internal_error ("bad value constant type %d, index %d", 
381                   JPOOL_TAG (jcf, index), index);
382 }
383
384 tree
385 get_name_constant (JCF *jcf, int index)
386 {
387   tree name = get_constant (jcf, index);
388
389   if (TREE_CODE (name) != IDENTIFIER_NODE)
390     abort ();
391
392   return name;
393 }
394
395 /* Handle reading innerclass attributes. If a nonzero entry (denoting
396    a non anonymous entry) is found, We augment the inner class list of
397    the outer context with the newly resolved innerclass.  */
398
399 static void
400 handle_innerclass_attribute (int count, JCF *jcf)
401 {
402   int c = (count);
403   while (c--)
404     {
405       /* Read inner_class_info_index. This may be 0 */
406       int icii = JCF_readu2 (jcf);
407       /* Read outer_class_info_index. If the innerclasses attribute
408          entry isn't a member (like an inner class) the value is 0. */
409       int ocii = JCF_readu2 (jcf);
410       /* Read inner_name_index. If the class we're dealing with is
411          an anonymous class, it must be 0. */
412       int ini = JCF_readu2 (jcf);
413       /* Read the access flag. */
414       int acc = JCF_readu2 (jcf);
415       /* If icii is 0, don't try to read the class. */
416       if (icii >= 0)
417         {
418           tree class = get_class_constant (jcf, icii);
419           tree decl = TYPE_NAME (class);
420           /* Skip reading further if ocii is null */
421           if (DECL_P (decl) && !CLASS_COMPLETE_P (decl) && ocii)
422             {
423               tree outer = TYPE_NAME (get_class_constant (jcf, ocii));
424               tree alias = (ini ? get_name_constant (jcf, ini) : NULL_TREE);
425               set_class_decl_access_flags (acc, decl);
426               DECL_CONTEXT (decl) = outer;
427               DECL_INNER_CLASS_LIST (outer) =
428                 tree_cons (decl, alias, DECL_INNER_CLASS_LIST (outer));
429               CLASS_COMPLETE_P (decl) = 1;
430             }
431         }
432     }
433 }
434
435 static tree
436 give_name_to_class (JCF *jcf, int i)
437 {
438   if (i <= 0 || i >= JPOOL_SIZE (jcf)
439       || JPOOL_TAG (jcf, i) != CONSTANT_Class)
440     abort ();
441   else
442     {
443       tree this_class;
444       int j = JPOOL_USHORT1 (jcf, i);
445       /* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */
446       tree class_name = unmangle_classname ((const char *) JPOOL_UTF_DATA (jcf, j),
447                                             JPOOL_UTF_LENGTH (jcf, j));
448       this_class = lookup_class (class_name);
449 #ifdef USE_MAPPED_LOCATION
450       {
451       tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
452       const char *sfname = IDENTIFIER_POINTER (source_name);
453       linemap_add (&line_table, LC_ENTER, false, sfname, 0);
454       input_location = linemap_line_start (&line_table, 0, 1);
455       file_start_location = input_location;
456       DECL_SOURCE_LOCATION (TYPE_NAME (this_class)) = input_location;
457       if (main_input_filename == NULL && jcf == main_jcf)
458         main_input_filename = sfname;
459       }
460 #else
461       input_location = DECL_SOURCE_LOCATION (TYPE_NAME (this_class));
462       if (main_input_filename == NULL && jcf == main_jcf)
463         main_input_filename = input_filename;
464 #endif
465
466       jcf->cpool.data[i].t = this_class;
467       JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
468       return this_class;
469     }
470 }
471
472 /* Get the class of the CONSTANT_Class whose constant pool index is I. */
473
474 tree
475 get_class_constant (JCF *jcf, int i)
476 {
477   tree type;
478   if (i <= 0 || i >= JPOOL_SIZE (jcf)
479       || (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) != CONSTANT_Class)
480     abort ();
481
482   if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)
483     {
484       int name_index = JPOOL_USHORT1 (jcf, i);
485       /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */
486       const char *name = (const char *) JPOOL_UTF_DATA (jcf, name_index);
487       int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
488
489       if (name[0] == '[')  /* Handle array "classes". */
490           type = TREE_TYPE (parse_signature_string ((const unsigned char *) name, nlength));
491       else
492         { 
493           tree cname = unmangle_classname (name, nlength);
494           type = lookup_class (cname);
495         }
496       jcf->cpool.data[i].t = type;
497       JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
498     }
499   else
500     type = jcf->cpool.data[i].t;
501   return type;
502 }
503
504 /* Read a class with the fully qualified-name NAME.
505    Return 1 iff we read the requested file.
506    (It is still possible we failed if the file did not
507    define the class it is supposed to.) */
508
509 int
510 read_class (tree name)
511 {
512   JCF this_jcf, *jcf;
513   tree icv, class = NULL_TREE;
514   tree save_current_class = current_class;
515   tree save_output_class = output_class;
516   location_t save_location = input_location;
517   JCF *save_current_jcf = current_jcf;
518
519   if ((icv = IDENTIFIER_CLASS_VALUE (name)) != NULL_TREE)
520     {
521       class = TREE_TYPE (icv);
522       jcf = TYPE_JCF (class);
523     }
524   else
525     jcf = NULL;
526
527   if (jcf == NULL)
528     {
529       this_jcf.zipd = NULL;
530       jcf = &this_jcf;
531       if (find_class (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name),
532                       &this_jcf, 1) == 0)
533         return 0;
534     }
535
536   current_jcf = jcf;
537
538   if (current_jcf->java_source)
539     {
540       const char *filename = current_jcf->filename;
541       tree given_file, real_file;
542       FILE *finput;
543       int generate;
544
545       java_parser_context_save_global ();
546       java_push_parser_context ();
547
548       given_file = get_identifier (filename);
549       filename = IDENTIFIER_POINTER (given_file);
550       real_file = get_identifier (lrealpath (filename));
551
552       generate = IS_A_COMMAND_LINE_FILENAME_P (given_file);
553       output_class = current_class = NULL_TREE;
554       current_function_decl = NULL_TREE;
555
556       if (! HAS_BEEN_ALREADY_PARSED_P (real_file))
557         {
558           if (! (finput = fopen (filename, "r")))
559             fatal_error ("can't reopen %s: %m", filename);
560
561           parse_source_file_1 (real_file, filename, finput);
562           parse_source_file_2 ();
563           parse_source_file_3 ();
564
565           if (fclose (finput))
566             fatal_error ("can't close %s: %m", input_filename);
567 #ifdef USE_MAPPED_LOCATION
568           linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
569 #endif
570         }
571       JCF_FINISH (current_jcf);
572       java_pop_parser_context (generate);
573       java_parser_context_restore_global ();
574     }
575   else
576     {
577       if (class == NULL_TREE || ! CLASS_PARSED_P (class))
578         {
579           java_parser_context_save_global ();
580           java_push_parser_context ();
581           output_class = current_class = class;
582           ctxp->save_location = input_location;
583           if (JCF_SEEN_IN_ZIP (current_jcf))
584             read_zip_member(current_jcf,
585                             current_jcf->zipd, current_jcf->zipd->zipf);
586           jcf_parse (current_jcf);
587           /* Parsing might change the class, in which case we have to
588              put it back where we found it.  */
589           if (current_class != class && icv != NULL_TREE)
590             TREE_TYPE (icv) = current_class;
591           class = current_class;
592           java_pop_parser_context (0);
593           java_parser_context_restore_global ();
594         }
595       layout_class (class);
596       load_inner_classes (class);
597     }
598
599   output_class = save_output_class;
600   current_class = save_current_class;
601   input_location = save_location;
602   current_jcf = save_current_jcf;
603   return 1;
604 }
605
606 /* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if
607    called from the parser, otherwise it's a RECORD_TYPE node. If
608    VERBOSE is 1, print error message on failure to load a class. */
609 void
610 load_class (tree class_or_name, int verbose)
611 {
612   tree name, saved;
613   int class_loaded = 0;
614   tree class_decl = NULL_TREE;
615   bool is_compiled_class = false;
616
617   /* We've already failed, don't try again.  */
618   if (TREE_CODE (class_or_name) == RECORD_TYPE
619       && TYPE_DUMMY (class_or_name))
620     return;
621
622   /* class_or_name can be the name of the class we want to load */
623   if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
624     name = class_or_name;
625   /* In some cases, it's a dependency that we process earlier that
626      we though */
627   else if (TREE_CODE (class_or_name) == TREE_LIST)
628     name = TYPE_NAME (TREE_PURPOSE (class_or_name));
629   /* Or it's a type in the making */
630   else
631     name = DECL_NAME (TYPE_NAME (class_or_name));
632
633   class_decl = IDENTIFIER_CLASS_VALUE (name);
634   if (class_decl != NULL_TREE)
635     {
636       tree type = TREE_TYPE (class_decl);
637       is_compiled_class
638         = ((TYPE_JCF (type) && JCF_SEEN_IN_ZIP (TYPE_JCF (type)))
639            || CLASS_FROM_CURRENTLY_COMPILED_P (type));
640     }
641
642   /* If the class is from source code, then it must already be loaded.  */
643   class_decl = IDENTIFIER_CLASS_VALUE (name);
644   if (class_decl && CLASS_FROM_SOURCE_P (TREE_TYPE (class_decl)))
645     return;
646
647   saved = name;
648   
649   /* If flag_verify_invocations is unset, we don't try to load a class
650      unless we're looking for Object (which is fixed by the ABI) or
651      it's a class that we're going to compile.  */
652   if (flag_verify_invocations
653       || class_or_name == object_type_node
654       || is_compiled_class
655       || TREE_CODE (class_or_name) == IDENTIFIER_NODE)
656     {
657       while (1)
658         {
659           char *separator;
660
661           /* We've already loaded it.  */
662           if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE)
663             {
664               tree tmp_decl = IDENTIFIER_CLASS_VALUE (name);
665               if (CLASS_PARSED_P (TREE_TYPE (tmp_decl)))
666                 break;
667             }
668         
669           if (read_class (name))
670             break;
671
672           /* We failed loading name. Now consider that we might be looking
673              for a inner class. */
674           if ((separator = strrchr (IDENTIFIER_POINTER (name), '$'))
675               || (separator = strrchr (IDENTIFIER_POINTER (name), '.')))
676             {
677               int c = *separator;
678               *separator = '\0';
679               name = get_identifier (IDENTIFIER_POINTER (name));
680               *separator = c;
681
682               /* Otherwise we might get infinite recursion, if say we
683                  have String.class but not
684                  String$CaseInsensitiveComparator.class. */
685               if (current_jcf && current_jcf->java_source == 0)
686                 break;
687             }
688           /* Otherwise, we failed, we bail. */
689           else
690             break;
691         }
692
693       {
694         /* have we found the class we're looking for?  */
695         tree type_decl = IDENTIFIER_CLASS_VALUE (saved);
696         tree type = type_decl ? TREE_TYPE (type_decl) : NULL;
697         class_loaded = type && CLASS_PARSED_P (type);
698       }       
699     }
700   
701   if (!class_loaded)
702     {
703       if (flag_verify_invocations || ! flag_indirect_dispatch
704           || flag_emit_class_files)
705         {
706           if (verbose)
707             error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
708         }
709       else if (verbose)
710         {
711           /* This is just a diagnostic during testing, not a real problem.  */
712           if (!quiet_flag)
713             warning("cannot find file for class %s", 
714                     IDENTIFIER_POINTER (saved));
715           
716           /* Fake it.  */
717           if (TREE_CODE (class_or_name) == RECORD_TYPE)
718             {
719               set_super_info (0, class_or_name, object_type_node, 0);
720               TYPE_DUMMY (class_or_name) = 1;
721               /* We won't be able to output any debug info for this class.  */
722               DECL_IGNORED_P (TYPE_NAME (class_or_name)) = 1;
723             }
724         }
725     }
726 }
727
728 /* Parse the .class file JCF. */
729
730 static void
731 jcf_parse (JCF* jcf)
732 {
733   int i, code;
734
735   if (jcf_parse_preamble (jcf) != 0)
736     fatal_error ("not a valid Java .class file");
737   code = jcf_parse_constant_pool (jcf);
738   if (code != 0)
739     fatal_error ("error while parsing constant pool");
740   code = verify_constant_pool (jcf);
741   if (code > 0)
742     fatal_error ("error in constant pool entry #%d\n", code);
743
744   jcf_parse_class (jcf);
745   if (main_class == NULL_TREE)
746     main_class = current_class;
747   if (! quiet_flag && TYPE_NAME (current_class))
748     fprintf (stderr, " %s %s",
749              (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class", 
750              IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
751   if (CLASS_PARSED_P (current_class))
752     {
753       /* FIXME - where was first time */
754       fatal_error ("reading class %s for the second time from %s",
755                    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))),
756                    jcf->filename);
757     }
758   CLASS_PARSED_P (current_class) = 1;
759
760   for (i = 1; i < JPOOL_SIZE(jcf); i++)
761     {
762       switch (JPOOL_TAG (jcf, i))
763         {
764         case CONSTANT_Class:
765           get_class_constant (jcf, i);
766           break;
767         }
768     }
769   
770   code = jcf_parse_fields (jcf);
771   if (code != 0)
772     fatal_error ("error while parsing fields");
773   code = jcf_parse_methods (jcf);
774   if (code != 0)
775     fatal_error ("error while parsing methods");
776   code = jcf_parse_final_attributes (jcf);
777   if (code != 0)
778     fatal_error ("error while parsing final attributes");
779 #ifdef USE_MAPPED_LOCATION
780   linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
781 #endif
782
783   /* The fields of class_type_node are already in correct order. */
784   if (current_class != class_type_node && current_class != object_type_node)
785     TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));
786
787   if (current_class == object_type_node)
788     {
789       layout_class_methods (object_type_node);
790       /* If we don't have the right archive, emit a verbose warning.
791          If we're generating bytecode, emit the warning only if
792          -fforce-classes-archive-check was specified. */
793       if (!jcf->right_zip
794           && (!flag_emit_class_files || flag_force_classes_archive_check))
795         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);
796     }
797   else
798     all_class_list = tree_cons (NULL_TREE,
799                                 TYPE_NAME (current_class), all_class_list );
800 }
801
802 /* If we came across inner classes, load them now. */
803 static void
804 load_inner_classes (tree cur_class)
805 {
806   tree current;
807   for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (cur_class)); current;
808        current = TREE_CHAIN (current))
809     {
810       tree name = DECL_NAME (TREE_PURPOSE (current));
811       tree decl = IDENTIFIER_GLOBAL_VALUE (name);
812       if (decl && ! CLASS_LOADED_P (TREE_TYPE (decl))
813           && !CLASS_BEING_LAIDOUT (TREE_TYPE (decl)))
814         load_class (name, 1);
815     }
816 }
817
818 static void
819 parse_class_file (void)
820 {
821   tree method;
822   location_t save_location = input_location;
823
824   java_layout_seen_class_methods ();
825
826   input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class));
827   file_start_location = input_location;
828   (*debug_hooks->start_source_file) (input_line, input_filename);
829
830   gen_indirect_dispatch_tables (current_class);
831
832   java_mark_class_local (current_class);
833
834   for (method = TYPE_METHODS (current_class);
835        method != NULL_TREE; method = TREE_CHAIN (method))
836     {
837       JCF *jcf = current_jcf;
838
839       if (METHOD_ABSTRACT (method) || METHOD_DUMMY (method))
840         continue;
841
842       if (METHOD_NATIVE (method))
843         {
844           tree arg;
845           int  decl_max_locals;
846
847           if (! flag_jni)
848             continue;
849           /* We need to compute the DECL_MAX_LOCALS. We need to take
850              the wide types into account too. */
851           for (arg = TYPE_ARG_TYPES (TREE_TYPE (method)), decl_max_locals = 0; 
852                arg != end_params_node;
853                arg = TREE_CHAIN (arg), decl_max_locals += 1)
854             {
855               if (TREE_VALUE (arg) && TYPE_IS_WIDE (TREE_VALUE (arg)))
856                 decl_max_locals += 1;
857             }
858           DECL_MAX_LOCALS (method) = decl_max_locals;
859           start_java_method (method);
860           give_name_to_locals (jcf);
861           *get_stmts () = build_jni_stub (method);
862           end_java_method ();
863           continue;
864         }
865
866       if (DECL_CODE_OFFSET (method) == 0)
867         {
868           current_function_decl = method;
869           error ("missing Code attribute");
870           continue;
871         }
872
873       input_location = file_start_location;
874       if (DECL_LINENUMBERS_OFFSET (method))
875         {
876           int i;
877           int min_line = 0;
878           unsigned char *ptr;
879           JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method));
880           linenumber_count = i = JCF_readu2 (jcf);
881           linenumber_table = ptr = jcf->read_ptr;
882
883           for (ptr += 2; --i >= 0; ptr += 4)
884             {
885               int line = GET_u2 (ptr);
886               /* Set initial input_line to smallest linenumber.
887                * Needs to be set before init_function_start. */
888               if (min_line == 0 || line < min_line)
889                 min_line = line;
890             }
891 #ifdef USE_MAPPED_LOCATION
892           if (min_line != 0)
893             input_location = linemap_line_start (&line_table, min_line, 1);
894 #else
895           if (min_line != 0)
896             input_line = min_line;
897 #endif
898         }
899       else
900         {
901           linenumber_table = NULL;
902           linenumber_count = 0;
903         }
904
905       start_java_method (method);
906
907       note_instructions (jcf, method);
908
909       give_name_to_locals (jcf);
910
911       /* Convert bytecode to trees.  */
912       expand_byte_code (jcf, method);
913
914       end_java_method ();
915     }
916
917   if (flag_emit_class_files)
918     write_classfile (current_class);
919
920   finish_class ();
921
922   (*debug_hooks->end_source_file) (LOCATION_LINE (save_location));
923   input_location = save_location;
924 }
925
926 /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */
927
928 static void
929 parse_source_file_1 (tree real_file, const char *filename, FILE *finput)
930 {
931   int save_error_count = java_error_count;
932
933   /* Mark the file as parsed.  */
934   HAS_BEEN_ALREADY_PARSED_P (real_file) = 1;
935
936   lang_init_source (1);             /* Error msgs have no method prototypes */
937
938   /* There's no point in trying to find the current encoding unless we
939      are going to do something intelligent with it -- hence the test
940      for iconv.  */
941 #if defined (HAVE_LOCALE_H) && defined (HAVE_ICONV) && defined (HAVE_LANGINFO_CODESET)
942   setlocale (LC_CTYPE, "");
943   if (current_encoding == NULL)
944     current_encoding = nl_langinfo (CODESET);
945 #endif 
946   if (current_encoding == NULL || *current_encoding == '\0')
947     current_encoding = DEFAULT_ENCODING;
948
949 #ifdef USE_MAPPED_LOCATION
950   linemap_add (&line_table, LC_ENTER, false, filename, 0);
951   input_location = linemap_line_start (&line_table, 0, 125);
952 #else
953   input_filename = filename;
954   input_line = 0;
955 #endif
956   ctxp->file_start_location = input_location;
957   ctxp->filename = filename;
958
959   jcf_dependency_add_file (input_filename, 0);
960
961   /* Initialize the parser */
962   java_init_lex (finput, current_encoding);
963   java_parse_abort_on_error ();
964
965   java_parse ();                    /* Parse and build partial tree nodes. */
966   java_parse_abort_on_error ();
967 }
968
969 /* Process a parsed source file, resolving names etc. */
970
971 static void
972 parse_source_file_2 (void)
973 {
974   int save_error_count = java_error_count;
975   flag_verify_invocations = true;
976   java_complete_class ();           /* Parse unsatisfied class decl. */
977   java_parse_abort_on_error ();
978 }
979
980 static void
981 parse_source_file_3 (void)
982 {
983   int save_error_count = java_error_count;
984   java_check_circular_reference (); /* Check on circular references */
985   java_parse_abort_on_error ();
986   java_fix_constructors ();         /* Fix the constructors */
987   java_parse_abort_on_error ();
988   java_reorder_fields ();           /* Reorder the fields */
989 }
990
991 void
992 add_predefined_file (tree name)
993 {
994   predef_filenames = tree_cons (NULL_TREE, name, predef_filenames);
995 }
996
997 int
998 predefined_filename_p (tree node)
999 {
1000   tree iter;
1001
1002   for (iter = predef_filenames; iter != NULL_TREE; iter = TREE_CHAIN (iter))
1003     {
1004       if (TREE_VALUE (iter) == node)
1005         return 1;
1006     }
1007   return 0;
1008 }
1009
1010 /* Generate a function that does all static initialization for this 
1011    translation unit.  */
1012
1013 static void
1014 java_emit_static_constructor (void)
1015 {
1016   tree body = NULL;
1017
1018   emit_register_classes (&body);
1019   write_resource_constructor (&body);
1020
1021   if (body)
1022     cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
1023 }
1024
1025 void
1026 java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
1027 {
1028   int filename_count = 0;
1029   location_t save_location = input_location;
1030   char *list, *next;
1031   tree node;
1032   FILE *finput = NULL;
1033   int in_quotes = 0;
1034  
1035   if (flag_filelist_file)
1036     {
1037       int avail = 2000;
1038       finput = fopen (main_input_filename, "r");
1039       if (finput == NULL)
1040         fatal_error ("can't open %s: %m", input_filename);
1041       list = xmalloc(avail);
1042       next = list;
1043       for (;;)
1044         {
1045           int count;
1046           if (avail < 500)
1047             {
1048               count = next - list;
1049               avail = 2 * (count + avail);
1050               list = xrealloc (list, avail);
1051               next = list + count;
1052               avail = avail - count;
1053             }
1054           /* Subtract to to guarantee space for final '\0'. */
1055           count = fread (next, 1, avail - 1, finput);
1056           if (count == 0)
1057             {
1058               if (! feof (finput))
1059                 fatal_error ("error closing %s: %m", input_filename);
1060               *next = '\0';
1061               break;
1062             }
1063           avail -= count;
1064           next += count;
1065         }
1066       fclose (finput);
1067       finput = NULL;
1068     }
1069   else
1070     list = (char *) main_input_filename;
1071
1072   while (list)
1073     {
1074       for (next = list; ; )
1075         {
1076           char ch = *next;
1077           if (flag_filelist_file && ! in_quotes
1078               && (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' '
1079                   || ch == '&') /* FIXME */)
1080             {
1081               if (next == list)
1082                 {
1083                   next++;
1084                   list = next;
1085                   continue;
1086                 }
1087               else
1088                 {
1089                   *next++ = '\0';
1090                   break;
1091                 }
1092             }
1093           if (flag_filelist_file && ch == '"')
1094             {
1095               in_quotes = ! in_quotes;
1096               *next++ = '\0';
1097               if (in_quotes) 
1098                 list = next;
1099               else 
1100                 break;
1101             }
1102           if (ch == '\0')
1103             {
1104               next = NULL;
1105               break;
1106             }
1107           next++;
1108         }
1109
1110       if (list[0]) 
1111         {
1112           node = get_identifier (list);
1113
1114           filename_count++;
1115
1116           /* Exclude file that we see twice on the command line. */
1117              
1118           if (IS_A_COMMAND_LINE_FILENAME_P (node))
1119             {
1120               location_t warn_loc;
1121 #ifdef USE_MAPPED_LOCATION
1122               linemap_add (&line_table, LC_RENAME, 0,
1123                            IDENTIFIER_POINTER (node), 0);
1124               warn_loc = linemap_line_start (&line_table, 0, 1);
1125 #else
1126               warn_loc.file = IDENTIFIER_POINTER (node);
1127               warn_loc.line = 0;
1128 #endif
1129               warning ("%Hsource file seen twice on command line and "
1130                        "will be compiled only once", &warn_loc);
1131             }
1132           else
1133             {
1134               tree file_decl = build_decl (TRANSLATION_UNIT_DECL, node, NULL);
1135               TREE_CHAIN (file_decl) = current_file_list;
1136               current_file_list = file_decl;
1137               IS_A_COMMAND_LINE_FILENAME_P (node) = 1;
1138             }
1139         }
1140       list = next;
1141     }
1142
1143   if (filename_count == 0)
1144     warning ("no input file specified");
1145
1146   if (resource_name)
1147     {
1148       const char *resource_filename;
1149       
1150       /* Only one resource file may be compiled at a time.  */
1151       assert (TREE_CHAIN (current_file_list) == NULL);
1152
1153       resource_filename = IDENTIFIER_POINTER (DECL_NAME (current_file_list));
1154       compile_resource_file (resource_name, resource_filename);
1155
1156       goto finish;
1157     }
1158
1159   current_jcf = main_jcf;
1160   current_file_list = nreverse (current_file_list);
1161   for (node = current_file_list; node; node = TREE_CHAIN (node))
1162     {
1163       unsigned char magic_string[4];
1164       uint32 magic = 0;
1165       tree name = DECL_NAME (node);
1166       tree real_file;
1167       const char *filename = IDENTIFIER_POINTER (name);
1168
1169       /* Skip already parsed files */
1170       real_file = get_identifier (lrealpath (filename));
1171       if (HAS_BEEN_ALREADY_PARSED_P (real_file))
1172         continue;
1173
1174       /* Close previous descriptor, if any */
1175       if (finput && fclose (finput))
1176         fatal_error ("can't close input file %s: %m", main_input_filename);
1177       
1178       finput = fopen (filename, "rb");
1179       if (finput == NULL)
1180         fatal_error ("can't open %s: %m", filename);
1181
1182 #ifdef IO_BUFFER_SIZE
1183       setvbuf (finput, xmalloc (IO_BUFFER_SIZE),
1184                _IOFBF, IO_BUFFER_SIZE);
1185 #endif
1186
1187       /* Figure what kind of file we're dealing with */
1188       if (fread (magic_string, 1, 4, finput) == 4)
1189         {
1190           fseek (finput, 0L, SEEK_SET);
1191           magic = GET_u4 (magic_string);
1192         }
1193       if (magic == 0xcafebabe)
1194         {
1195           CLASS_FILE_P (node) = 1;
1196           current_jcf = ggc_alloc (sizeof (JCF));
1197           JCF_ZERO (current_jcf);
1198           current_jcf->read_state = finput;
1199           current_jcf->filbuf = jcf_filbuf_from_stdio;
1200           jcf_parse (current_jcf);
1201           DECL_SOURCE_LOCATION (node) = file_start_location;
1202           TYPE_JCF (current_class) = current_jcf;
1203           CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1204           TREE_TYPE (node) = current_class;
1205         }
1206       else if (magic == (JCF_u4)ZIPMAGIC)
1207         {
1208           main_jcf = ggc_alloc (sizeof (JCF));
1209           JCF_ZERO (main_jcf);
1210           main_jcf->read_state = finput;
1211           main_jcf->filbuf = jcf_filbuf_from_stdio;
1212 #ifdef USE_MAPPED_LOCATION
1213           linemap_add (&line_table, LC_ENTER, false, filename, 0);
1214           input_location = linemap_line_start (&line_table, 0, 1);
1215 #endif
1216           if (open_in_zip (main_jcf, filename, NULL, 0) <  0)
1217             fatal_error ("bad zip/jar file %s", filename);
1218           localToFile = SeenZipFiles;
1219           /* Register all the classes defined there.  */
1220           process_zip_dir (main_jcf->read_state);
1221 #ifdef USE_MAPPED_LOCATION
1222           linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1223 #endif
1224           parse_zip_file_entries ();
1225           /*
1226           for (each entry)
1227             CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1228           */
1229         }
1230       else
1231         {
1232           java_push_parser_context ();
1233           java_parser_context_save_global ();
1234
1235           parse_source_file_1 (real_file, filename, finput);
1236           java_parser_context_restore_global ();
1237           java_pop_parser_context (1);
1238 #ifdef USE_MAPPED_LOCATION
1239           linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1240 #endif
1241         }
1242     }
1243
1244   for (ctxp = ctxp_for_generation;  ctxp;  ctxp = ctxp->next)
1245     {
1246       input_location = ctxp->file_start_location;
1247       parse_source_file_2 ();
1248     }
1249
1250   for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
1251     {
1252       input_location = ctxp->file_start_location;
1253       parse_source_file_3 ();
1254     }
1255
1256   for (node = current_file_list; node; node = TREE_CHAIN (node))
1257     {
1258       input_location = DECL_SOURCE_LOCATION (node);
1259       if (CLASS_FILE_P (node))
1260         {
1261           /* FIXME: These two flags really should be independent.  We
1262              should be able to compile fully binary compatible, but
1263              with flag_verify_invocations on.  */
1264           flag_verify_invocations = ! flag_indirect_dispatch;
1265           output_class = current_class = TREE_TYPE (node);
1266
1267           current_jcf = TYPE_JCF (current_class);
1268           layout_class (current_class);
1269           load_inner_classes (current_class);
1270           parse_class_file ();
1271           JCF_FINISH (current_jcf);
1272         }
1273     }
1274   input_location = save_location;
1275
1276   java_expand_classes ();
1277   if (java_report_errors () || flag_syntax_only)
1278     return;
1279     
1280   /* Expand all classes compiled from source.  */
1281   java_finish_classes ();
1282
1283  finish:
1284   /* Arrange for any necessary initialization to happen.  */
1285   java_emit_static_constructor ();
1286
1287   /* Only finalize the compilation unit after we've told cgraph which
1288      functions have their addresses stored.  */
1289   cgraph_finalize_compilation_unit ();
1290   cgraph_optimize ();
1291 }
1292
1293
1294 /* Return the name of the class corresponding to the name of the file
1295    in this zip entry.  The result is newly allocated using ALLOC.  */
1296 static char *
1297 compute_class_name (struct ZipDirectory *zdir)
1298 {
1299   char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1300   char *class_name;
1301   int i;
1302   int filename_length = zdir->filename_length;
1303
1304   while (filename_length > 2 && strncmp (class_name_in_zip_dir, "./", 2) == 0)
1305     {
1306       class_name_in_zip_dir += 2;
1307       filename_length -= 2;
1308     }
1309
1310   filename_length -= strlen (".class");
1311   class_name = ALLOC (filename_length + 1);
1312   memcpy (class_name, class_name_in_zip_dir, filename_length);
1313   class_name [filename_length] = '\0';
1314
1315   for (i = 0; i < filename_length; i++)
1316     if (class_name[i] == '/')
1317       class_name[i] = '.';
1318
1319   return class_name;
1320 }
1321
1322 /* Return 0 if we should skip this entry, 1 if it is a .class file, 2
1323    if it is a property file of some sort.  */
1324 static int
1325 classify_zip_file (struct ZipDirectory *zdir)
1326 {
1327   char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1328
1329   if (zdir->filename_length > 6
1330       && !strncmp (&class_name_in_zip_dir[zdir->filename_length - 6],
1331                    ".class", 6))
1332     return 1;
1333
1334   /* For now we drop the manifest, but not other information.  */
1335   if (zdir->filename_length == 20
1336       && !strncmp (class_name_in_zip_dir, "META-INF/MANIFEST.MF", 20))
1337     return 0;
1338
1339   /* Drop directory entries.  */
1340   if (zdir->filename_length > 0
1341       && class_name_in_zip_dir[zdir->filename_length - 1] == '/')
1342     return 0;
1343
1344   return 2;
1345 }
1346
1347 /* Process all class entries found in the zip file.  */
1348 static void
1349 parse_zip_file_entries (void)
1350 {
1351   struct ZipDirectory *zdir;
1352   int i;
1353
1354   for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1355        i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1356     {
1357       tree class;
1358
1359       switch (classify_zip_file (zdir))
1360         {
1361         case 0:
1362           continue;
1363
1364         case 1:
1365           {
1366             char *class_name = compute_class_name (zdir);
1367             class = lookup_class (get_identifier (class_name));
1368             FREE (class_name);
1369             current_jcf = TYPE_JCF (class);
1370             output_class = current_class = class;
1371
1372             if (TYPE_DUMMY (class))
1373               {
1374                 /* This is a dummy class, and now we're compiling it
1375                    for real.  */
1376                 abort ();
1377               }
1378
1379             /* This is for a corner case where we have a superclass
1380                but no superclass fields.  
1381
1382                This can happen if we earlier failed to lay out this
1383                class because its superclass was still in the process
1384                of being laid out; this occurs when we have recursive
1385                class dependencies via inner classes.  Setting
1386                TYPE_SIZE to null here causes CLASS_LOADED_P to return
1387                false, so layout_class() will be called again.  */
1388             if (TYPE_SIZE (class) && CLASSTYPE_SUPER (class)
1389                 && integer_zerop (TYPE_SIZE (class)))
1390               TYPE_SIZE (class) = NULL_TREE;
1391
1392             if (! CLASS_LOADED_P (class))
1393               {
1394                 if (! CLASS_PARSED_P (class))
1395                   {
1396                     read_zip_member (current_jcf, zdir, localToFile);
1397                     jcf_parse (current_jcf);
1398                   }
1399                 layout_class (current_class);
1400                 load_inner_classes (current_class);
1401               }
1402
1403             if (TYPE_SIZE (current_class) != error_mark_node)
1404               {
1405                 parse_class_file ();
1406                 FREE (current_jcf->buffer); /* No longer necessary */
1407                 /* Note: there is a way to free this buffer right after a
1408                    class seen in a zip file has been parsed. The idea is the
1409                    set its jcf in such a way that buffer will be reallocated
1410                    the time the code for the class will be generated. FIXME. */
1411               }
1412           }
1413           break;
1414
1415         case 2:
1416           {
1417             char *file_name, *class_name_in_zip_dir, *buffer;
1418             JCF *jcf;
1419             file_name = ALLOC (zdir->filename_length + 1);
1420             class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1421             strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
1422             file_name[zdir->filename_length] = '\0';
1423             jcf = ALLOC (sizeof (JCF));
1424             JCF_ZERO (jcf);
1425             jcf->read_state  = finput;
1426             jcf->filbuf      = jcf_filbuf_from_stdio;
1427             jcf->java_source = 0;
1428             jcf->classname   = NULL;
1429             jcf->filename    = file_name;
1430             jcf->zipd        = zdir;
1431
1432             if (read_zip_member (jcf, zdir, localToFile) < 0)
1433               fatal_error ("error while reading %s from zip file", file_name);
1434
1435             buffer = ALLOC (zdir->filename_length + 1 +
1436                             (jcf->buffer_end - jcf->buffer));
1437             strcpy (buffer, file_name);
1438             /* This is not a typo: we overwrite the trailing \0 of the
1439                file name; this is just how the data is laid out.  */
1440             memcpy (buffer + zdir->filename_length,
1441                     jcf->buffer, jcf->buffer_end - jcf->buffer);
1442
1443             compile_resource_data (file_name, buffer,
1444                                    jcf->buffer_end - jcf->buffer);
1445             JCF_FINISH (jcf);
1446             FREE (jcf);
1447             FREE (buffer);
1448           }
1449           break;
1450
1451         default:
1452           abort ();
1453         }
1454     }
1455 }
1456
1457 /* Read all the entries of the zip file, creates a class and a JCF. Sets the
1458    jcf up for further processing and link it to the created class.  */
1459
1460 static void
1461 process_zip_dir (FILE *finput)
1462 {
1463   int i;
1464   ZipDirectory *zdir;
1465
1466   for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1467        i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1468     {
1469       char *class_name, *file_name, *class_name_in_zip_dir;
1470       tree class;
1471       JCF  *jcf;
1472
1473       class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1474
1475       /* Here we skip non-class files; we handle them later.  */
1476       if (classify_zip_file (zdir) != 1)
1477         continue;
1478
1479       class_name = compute_class_name (zdir);
1480       file_name  = ALLOC (zdir->filename_length+1);
1481       jcf = ggc_alloc (sizeof (JCF));
1482       JCF_ZERO (jcf);
1483
1484       strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
1485       file_name [zdir->filename_length] = '\0';
1486
1487       class = lookup_class (get_identifier (class_name));
1488
1489       jcf->read_state  = finput;
1490       jcf->filbuf      = jcf_filbuf_from_stdio;
1491       jcf->java_source = 0;
1492       jcf->classname   = class_name;
1493       jcf->filename    = file_name;
1494       jcf->zipd        = zdir;
1495
1496       TYPE_JCF (class) = jcf;
1497     }
1498 }
1499
1500 /* Initialization.  */
1501
1502 void
1503 init_jcf_parse (void)
1504 {
1505   init_src_parse ();
1506 }
1507
1508 #include "gt-java-jcf-parse.h"