OSDN Git Service

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