OSDN Git Service

* diagnostic.c (warning): Accept parameter to classify warning option.
[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       /* Convert bytecode to trees.  */
933       expand_byte_code (jcf, method);
934
935       end_java_method ();
936     }
937
938   if (flag_emit_class_files)
939     write_classfile (current_class);
940
941   finish_class ();
942
943   (*debug_hooks->end_source_file) (LOCATION_LINE (save_location));
944   input_location = save_location;
945 }
946
947 /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */
948
949 static void
950 parse_source_file_1 (tree real_file, const char *filename, FILE *finput)
951 {
952   int save_error_count = java_error_count;
953
954   /* Mark the file as parsed.  */
955   HAS_BEEN_ALREADY_PARSED_P (real_file) = 1;
956
957   lang_init_source (1);             /* Error msgs have no method prototypes */
958
959   /* There's no point in trying to find the current encoding unless we
960      are going to do something intelligent with it -- hence the test
961      for iconv.  */
962 #if defined (HAVE_LOCALE_H) && defined (HAVE_ICONV) && defined (HAVE_LANGINFO_CODESET)
963   setlocale (LC_CTYPE, "");
964   if (current_encoding == NULL)
965     current_encoding = nl_langinfo (CODESET);
966 #endif 
967   if (current_encoding == NULL || *current_encoding == '\0')
968     current_encoding = DEFAULT_ENCODING;
969
970 #ifdef USE_MAPPED_LOCATION
971   linemap_add (&line_table, LC_ENTER, false, filename, 0);
972   input_location = linemap_line_start (&line_table, 0, 125);
973 #else
974   input_filename = filename;
975   input_line = 0;
976 #endif
977   ctxp->file_start_location = input_location;
978   ctxp->filename = filename;
979
980   jcf_dependency_add_file (input_filename, 0);
981
982   /* Initialize the parser */
983   java_init_lex (finput, current_encoding);
984   java_parse_abort_on_error ();
985
986   java_parse ();                    /* Parse and build partial tree nodes. */
987   java_parse_abort_on_error ();
988 }
989
990 /* Process a parsed source file, resolving names etc. */
991
992 static void
993 parse_source_file_2 (void)
994 {
995   int save_error_count = java_error_count;
996   flag_verify_invocations = true;
997   java_complete_class ();           /* Parse unsatisfied class decl. */
998   java_parse_abort_on_error ();
999 }
1000
1001 static void
1002 parse_source_file_3 (void)
1003 {
1004   int save_error_count = java_error_count;
1005   java_check_circular_reference (); /* Check on circular references */
1006   java_parse_abort_on_error ();
1007   java_fix_constructors ();         /* Fix the constructors */
1008   java_parse_abort_on_error ();
1009   java_reorder_fields ();           /* Reorder the fields */
1010 }
1011
1012 void
1013 add_predefined_file (tree name)
1014 {
1015   predef_filenames = tree_cons (NULL_TREE, name, predef_filenames);
1016 }
1017
1018 int
1019 predefined_filename_p (tree node)
1020 {
1021   tree iter;
1022
1023   for (iter = predef_filenames; iter != NULL_TREE; iter = TREE_CHAIN (iter))
1024     {
1025       if (TREE_VALUE (iter) == node)
1026         return 1;
1027     }
1028   return 0;
1029 }
1030
1031 /* Generate a function that does all static initialization for this 
1032    translation unit.  */
1033
1034 static void
1035 java_emit_static_constructor (void)
1036 {
1037   tree body = NULL;
1038
1039   emit_register_classes (&body);
1040   write_resource_constructor (&body);
1041
1042   if (body)
1043     cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
1044 }
1045
1046 void
1047 java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
1048 {
1049   int filename_count = 0;
1050   location_t save_location = input_location;
1051   char *file_list = NULL, *list, *next;
1052   tree node;
1053   FILE *finput = NULL;
1054   int in_quotes = 0;
1055  
1056   if (flag_filelist_file)
1057     {
1058       int avail = 2000;
1059       finput = fopen (main_input_filename, "r");
1060       if (finput == NULL)
1061         fatal_error ("can't open %s: %m", input_filename);
1062       list = xmalloc(avail);
1063       next = list;
1064       for (;;)
1065         {
1066           int count;
1067           if (avail < 500)
1068             {
1069               count = next - list;
1070               avail = 2 * (count + avail);
1071               list = xrealloc (list, avail);
1072               next = list + count;
1073               avail = avail - count;
1074             }
1075           /* Subtract to to guarantee space for final '\0'. */
1076           count = fread (next, 1, avail - 1, finput);
1077           if (count == 0)
1078             {
1079               if (! feof (finput))
1080                 fatal_error ("error closing %s: %m", input_filename);
1081               *next = '\0';
1082               break;
1083             }
1084           avail -= count;
1085           next += count;
1086         }
1087       fclose (finput);
1088       finput = NULL;
1089       file_list = list;
1090     }
1091   else
1092     list = (char *) main_input_filename;
1093
1094   while (list)
1095     {
1096       for (next = list; ; )
1097         {
1098           char ch = *next;
1099           if (flag_filelist_file && ! in_quotes
1100               && (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' '
1101                   || ch == '&') /* FIXME */)
1102             {
1103               if (next == list)
1104                 {
1105                   next++;
1106                   list = next;
1107                   continue;
1108                 }
1109               else
1110                 {
1111                   *next++ = '\0';
1112                   break;
1113                 }
1114             }
1115           if (flag_filelist_file && ch == '"')
1116             {
1117               in_quotes = ! in_quotes;
1118               *next++ = '\0';
1119               if (in_quotes) 
1120                 list = next;
1121               else 
1122                 break;
1123             }
1124           if (ch == '\0')
1125             {
1126               next = NULL;
1127               break;
1128             }
1129           next++;
1130         }
1131
1132       if (list[0]) 
1133         {
1134           node = get_identifier (list);
1135
1136           filename_count++;
1137
1138           /* Exclude file that we see twice on the command line. */
1139              
1140           if (IS_A_COMMAND_LINE_FILENAME_P (node))
1141             duplicate_class_warning (IDENTIFIER_POINTER (node));
1142           else
1143             {
1144               tree file_decl = build_decl (TRANSLATION_UNIT_DECL, node, NULL);
1145               TREE_CHAIN (file_decl) = current_file_list;
1146               current_file_list = file_decl;
1147               IS_A_COMMAND_LINE_FILENAME_P (node) = 1;
1148             }
1149         }
1150       list = next;
1151     }
1152
1153   if (file_list != NULL)
1154     free (file_list);
1155
1156   if (filename_count == 0)
1157     warning (0, "no input file specified");
1158
1159   if (resource_name)
1160     {
1161       const char *resource_filename;
1162       
1163       /* Only one resource file may be compiled at a time.  */
1164       assert (TREE_CHAIN (current_file_list) == NULL);
1165
1166       resource_filename = IDENTIFIER_POINTER (DECL_NAME (current_file_list));
1167       compile_resource_file (resource_name, resource_filename);
1168
1169       goto finish;
1170     }
1171
1172   current_jcf = main_jcf;
1173   current_file_list = nreverse (current_file_list);
1174   for (node = current_file_list; node; node = TREE_CHAIN (node))
1175     {
1176       unsigned char magic_string[4];
1177       char *real_path;
1178       uint32 magic = 0;
1179       tree name = DECL_NAME (node);
1180       tree real_file;
1181       const char *filename = IDENTIFIER_POINTER (name);
1182
1183       /* Skip already parsed files */
1184       real_path = lrealpath (filename);
1185       real_file = get_identifier (real_path);
1186       free (real_path);
1187       if (HAS_BEEN_ALREADY_PARSED_P (real_file))
1188         continue;
1189
1190       /* Close previous descriptor, if any */
1191       if (finput && fclose (finput))
1192         fatal_error ("can't close input file %s: %m", main_input_filename);
1193       
1194       finput = fopen (filename, "rb");
1195       if (finput == NULL)
1196         fatal_error ("can't open %s: %m", filename);
1197
1198 #ifdef IO_BUFFER_SIZE
1199       setvbuf (finput, xmalloc (IO_BUFFER_SIZE),
1200                _IOFBF, IO_BUFFER_SIZE);
1201 #endif
1202
1203       /* Figure what kind of file we're dealing with */
1204       if (fread (magic_string, 1, 4, finput) == 4)
1205         {
1206           fseek (finput, 0L, SEEK_SET);
1207           magic = GET_u4 (magic_string);
1208         }
1209       if (magic == 0xcafebabe)
1210         {
1211           CLASS_FILE_P (node) = 1;
1212           current_jcf = ggc_alloc (sizeof (JCF));
1213           JCF_ZERO (current_jcf);
1214           current_jcf->read_state = finput;
1215           current_jcf->filbuf = jcf_filbuf_from_stdio;
1216           jcf_parse (current_jcf);
1217           DECL_SOURCE_LOCATION (node) = file_start_location;
1218           TYPE_JCF (current_class) = current_jcf;
1219           if (CLASS_FROM_CURRENTLY_COMPILED_P (current_class))
1220             {
1221               /* We've already compiled this class.  */
1222               duplicate_class_warning (filename);
1223               continue;
1224             }
1225           CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1226           TREE_TYPE (node) = current_class;
1227         }
1228       else if (magic == (JCF_u4)ZIPMAGIC)
1229         {
1230           main_jcf = ggc_alloc (sizeof (JCF));
1231           JCF_ZERO (main_jcf);
1232           main_jcf->read_state = finput;
1233           main_jcf->filbuf = jcf_filbuf_from_stdio;
1234 #ifdef USE_MAPPED_LOCATION
1235           linemap_add (&line_table, LC_ENTER, false, filename, 0);
1236           input_location = linemap_line_start (&line_table, 0, 1);
1237 #endif
1238           if (open_in_zip (main_jcf, filename, NULL, 0) <  0)
1239             fatal_error ("bad zip/jar file %s", filename);
1240           localToFile = SeenZipFiles;
1241           /* Register all the classes defined there.  */
1242           process_zip_dir (main_jcf->read_state);
1243 #ifdef USE_MAPPED_LOCATION
1244           linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1245 #endif
1246           parse_zip_file_entries ();
1247         }
1248       else
1249         {
1250           java_push_parser_context ();
1251           java_parser_context_save_global ();
1252
1253           parse_source_file_1 (real_file, filename, finput);
1254           java_parser_context_restore_global ();
1255           java_pop_parser_context (1);
1256 #ifdef USE_MAPPED_LOCATION
1257           linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
1258 #endif
1259         }
1260     }
1261
1262   for (ctxp = ctxp_for_generation;  ctxp;  ctxp = ctxp->next)
1263     {
1264       input_location = ctxp->file_start_location;
1265       parse_source_file_2 ();
1266     }
1267
1268   for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
1269     {
1270       input_location = ctxp->file_start_location;
1271       parse_source_file_3 ();
1272     }
1273
1274   for (node = current_file_list; node; node = TREE_CHAIN (node))
1275     {
1276       input_location = DECL_SOURCE_LOCATION (node);
1277       if (CLASS_FILE_P (node))
1278         {
1279           /* FIXME: These two flags really should be independent.  We
1280              should be able to compile fully binary compatible, but
1281              with flag_verify_invocations on.  */
1282           flag_verify_invocations = ! flag_indirect_dispatch;
1283           output_class = current_class = TREE_TYPE (node);
1284
1285           current_jcf = TYPE_JCF (current_class);
1286           layout_class (current_class);
1287           load_inner_classes (current_class);
1288           parse_class_file ();
1289           JCF_FINISH (current_jcf);
1290         }
1291     }
1292   input_location = save_location;
1293
1294   java_expand_classes ();
1295   if (java_report_errors () || flag_syntax_only)
1296     return;
1297     
1298   /* Expand all classes compiled from source.  */
1299   java_finish_classes ();
1300
1301  finish:
1302   /* Arrange for any necessary initialization to happen.  */
1303   java_emit_static_constructor ();
1304
1305   /* Only finalize the compilation unit after we've told cgraph which
1306      functions have their addresses stored.  */
1307   cgraph_finalize_compilation_unit ();
1308   cgraph_optimize ();
1309 }
1310
1311
1312 /* Return the name of the class corresponding to the name of the file
1313    in this zip entry.  The result is newly allocated using ALLOC.  */
1314 static char *
1315 compute_class_name (struct ZipDirectory *zdir)
1316 {
1317   char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1318   char *class_name;
1319   int i;
1320   int filename_length = zdir->filename_length;
1321
1322   while (filename_length > 2 && strncmp (class_name_in_zip_dir, "./", 2) == 0)
1323     {
1324       class_name_in_zip_dir += 2;
1325       filename_length -= 2;
1326     }
1327
1328   filename_length -= strlen (".class");
1329   class_name = ALLOC (filename_length + 1);
1330   memcpy (class_name, class_name_in_zip_dir, filename_length);
1331   class_name [filename_length] = '\0';
1332
1333   for (i = 0; i < filename_length; i++)
1334     if (class_name[i] == '/')
1335       class_name[i] = '.';
1336
1337   return class_name;
1338 }
1339
1340 /* Return 0 if we should skip this entry, 1 if it is a .class file, 2
1341    if it is a property file of some sort.  */
1342 static int
1343 classify_zip_file (struct ZipDirectory *zdir)
1344 {
1345   char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1346
1347   if (zdir->filename_length > 6
1348       && !strncmp (&class_name_in_zip_dir[zdir->filename_length - 6],
1349                    ".class", 6))
1350     return 1;
1351
1352   /* For now we drop the manifest, but not other information.  */
1353   if (zdir->filename_length == 20
1354       && !strncmp (class_name_in_zip_dir, "META-INF/MANIFEST.MF", 20))
1355     return 0;
1356
1357   /* Drop directory entries.  */
1358   if (zdir->filename_length > 0
1359       && class_name_in_zip_dir[zdir->filename_length - 1] == '/')
1360     return 0;
1361
1362   return 2;
1363 }
1364
1365 /* Process all class entries found in the zip file.  */
1366 static void
1367 parse_zip_file_entries (void)
1368 {
1369   struct ZipDirectory *zdir;
1370   int i;
1371
1372   for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1373        i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1374     {
1375       tree class;
1376
1377       switch (classify_zip_file (zdir))
1378         {
1379         case 0:
1380           continue;
1381
1382         case 1:
1383           {
1384             char *class_name = compute_class_name (zdir);
1385             class = lookup_class (get_identifier (class_name));
1386             FREE (class_name);
1387             current_jcf = TYPE_JCF (class);
1388             output_class = current_class = class;
1389
1390             if (CLASS_FROM_CURRENTLY_COMPILED_P (current_class))
1391               {
1392                 /* We've already compiled this class.  */
1393                 duplicate_class_warning (current_jcf->filename);
1394                 break;
1395               }
1396             
1397             CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1398
1399             if (TYPE_DUMMY (class))
1400               {
1401                 /* This is a dummy class, and now we're compiling it
1402                    for real.  */
1403                 abort ();
1404               }
1405
1406             /* This is for a corner case where we have a superclass
1407                but no superclass fields.  
1408
1409                This can happen if we earlier failed to lay out this
1410                class because its superclass was still in the process
1411                of being laid out; this occurs when we have recursive
1412                class dependencies via inner classes.  Setting
1413                TYPE_SIZE to null here causes CLASS_LOADED_P to return
1414                false, so layout_class() will be called again.  */
1415             if (TYPE_SIZE (class) && CLASSTYPE_SUPER (class)
1416                 && integer_zerop (TYPE_SIZE (class)))
1417               TYPE_SIZE (class) = NULL_TREE;
1418
1419             if (! CLASS_LOADED_P (class))
1420               {
1421                 if (! CLASS_PARSED_P (class))
1422                   {
1423                     read_zip_member (current_jcf, zdir, localToFile);
1424                     jcf_parse (current_jcf);
1425                   }
1426                 layout_class (current_class);
1427                 load_inner_classes (current_class);
1428               }
1429
1430             if (TYPE_SIZE (current_class) != error_mark_node)
1431               {
1432                 parse_class_file ();
1433                 FREE (current_jcf->buffer); /* No longer necessary */
1434                 /* Note: there is a way to free this buffer right after a
1435                    class seen in a zip file has been parsed. The idea is the
1436                    set its jcf in such a way that buffer will be reallocated
1437                    the time the code for the class will be generated. FIXME. */
1438               }
1439           }
1440           break;
1441
1442         case 2:
1443           {
1444             char *file_name, *class_name_in_zip_dir, *buffer;
1445             JCF *jcf;
1446             file_name = ALLOC (zdir->filename_length + 1);
1447             class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1448             strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
1449             file_name[zdir->filename_length] = '\0';
1450             jcf = ALLOC (sizeof (JCF));
1451             JCF_ZERO (jcf);
1452             jcf->read_state  = finput;
1453             jcf->filbuf      = jcf_filbuf_from_stdio;
1454             jcf->java_source = 0;
1455             jcf->classname   = NULL;
1456             jcf->filename    = file_name;
1457             jcf->zipd        = zdir;
1458
1459             if (read_zip_member (jcf, zdir, localToFile) < 0)
1460               fatal_error ("error while reading %s from zip file", file_name);
1461
1462             buffer = ALLOC (zdir->filename_length + 1 +
1463                             (jcf->buffer_end - jcf->buffer));
1464             strcpy (buffer, file_name);
1465             /* This is not a typo: we overwrite the trailing \0 of the
1466                file name; this is just how the data is laid out.  */
1467             memcpy (buffer + zdir->filename_length,
1468                     jcf->buffer, jcf->buffer_end - jcf->buffer);
1469
1470             compile_resource_data (file_name, buffer,
1471                                    jcf->buffer_end - jcf->buffer);
1472             JCF_FINISH (jcf);
1473             FREE (jcf);
1474             FREE (buffer);
1475           }
1476           break;
1477
1478         default:
1479           abort ();
1480         }
1481     }
1482 }
1483
1484 /* Read all the entries of the zip file, creates a class and a JCF. Sets the
1485    jcf up for further processing and link it to the created class.  */
1486
1487 static void
1488 process_zip_dir (FILE *finput)
1489 {
1490   int i;
1491   ZipDirectory *zdir;
1492
1493   for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
1494        i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
1495     {
1496       char *class_name, *file_name, *class_name_in_zip_dir;
1497       tree class;
1498       JCF  *jcf;
1499
1500       class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
1501
1502       /* Here we skip non-class files; we handle them later.  */
1503       if (classify_zip_file (zdir) != 1)
1504         continue;
1505
1506       class_name = compute_class_name (zdir);
1507       file_name  = ALLOC (zdir->filename_length+1);
1508       jcf = ggc_alloc (sizeof (JCF));
1509       JCF_ZERO (jcf);
1510
1511       strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
1512       file_name [zdir->filename_length] = '\0';
1513
1514       class = lookup_class (get_identifier (class_name));
1515
1516       jcf->read_state  = finput;
1517       jcf->filbuf      = jcf_filbuf_from_stdio;
1518       jcf->java_source = 0;
1519       jcf->classname   = class_name;
1520       jcf->filename    = file_name;
1521       jcf->zipd        = zdir;
1522
1523       TYPE_JCF (class) = jcf;
1524     }
1525 }
1526
1527 /* Initialization.  */
1528
1529 void
1530 init_jcf_parse (void)
1531 {
1532   init_src_parse ();
1533 }
1534
1535 #include "gt-java-jcf-parse.h"