OSDN Git Service

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