OSDN Git Service

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