OSDN Git Service

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