OSDN Git Service

1999-12-14 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-parse.c
1 /* Parser for Java(TM) .class files.
2    Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
24
25 /* Written by Per Bothner <bothner@cygnus.com> */
26
27 #include "config.h"
28 #include "system.h"
29 #include "tree.h"
30 #include "obstack.h"
31 #include "flags.h"
32 #include "java-except.h"
33 #include "input.h"
34 #include "java-tree.h"
35 #include "toplev.h"
36 #include "parse.h"
37
38 /* A CONSTANT_Utf8 element is converted to an IDENTIFIER_NODE at parse time. */
39 #define JPOOL_UTF(JCF, INDEX) CPOOL_UTF(&(JCF)->cpool, INDEX)
40 #define JPOOL_UTF_LENGTH(JCF, INDEX) IDENTIFIER_LENGTH (JPOOL_UTF (JCF, INDEX))
41 #define JPOOL_UTF_DATA(JCF, INDEX) \
42   ((const unsigned char *) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX)))
43 #define HANDLE_CONSTANT_Utf8(JCF, INDEX, LENGTH) \
44   do { \
45     unsigned char save;  unsigned char *text; \
46     JCF_FILL (JCF, (LENGTH)+1); /* Make sure we read 1 byte beyond string. */ \
47     text = (JCF)->read_ptr; \
48     save = text[LENGTH]; \
49     text[LENGTH] = 0; \
50     (JCF)->cpool.data[INDEX] = (jword) get_identifier (text); \
51     text[LENGTH] = save; \
52     JCF_SKIP (JCF, LENGTH); } while (0)
53
54 #include "jcf.h"
55
56 extern struct obstack *saveable_obstack;
57 extern struct obstack temporary_obstack;
58 extern struct obstack permanent_obstack;
59
60 /* The class we are currently processing. */
61 tree current_class = NULL_TREE;
62
63 /* The class we started with. */
64 tree main_class = NULL_TREE;
65
66 /* List of all class DECL seen so far.  */
67 tree all_class_list = NULL_TREE;
68
69 /* The FIELD_DECL for the current field.  */
70 static tree current_field = NULL_TREE;
71
72 /* The METHOD_DECL for the current method.  */
73 static tree current_method = NULL_TREE;
74
75 /* The Java .class file that provides main_class;  the main input file. */
76 static struct JCF main_jcf[1];
77
78 /* Declarations of some functions used here.  */
79 static tree give_name_to_class PROTO ((JCF *jcf, int index));
80 static void parse_zip_file_entries PROTO ((void));
81 static void process_zip_dir PROTO ((void));
82 static void parse_source_file PROTO ((tree));
83 static void jcf_parse_source PROTO ((void));
84 static int jcf_figure_file_type PROTO ((JCF *));
85 static int find_in_current_zip PROTO ((const char *, struct JCF **));
86 static void parse_class_file PROTO ((void));
87 static void set_source_filename PROTO ((JCF *, int));
88 static int predefined_filename_p PROTO ((tree));
89
90 /* Handle "SourceFile" attribute. */
91
92 static void
93 set_source_filename (jcf, index)
94      JCF *jcf;
95      int index;
96 {
97   tree sfname_id = get_name_constant (jcf, index);
98   char *sfname = IDENTIFIER_POINTER (sfname_id);
99   if (input_filename != NULL)
100     {
101       int old_len = strlen (input_filename);
102       int new_len = IDENTIFIER_LENGTH (sfname_id);
103       /* Use the current input_filename (derived from the class name)
104          if it has a directory prefix, but otherwise matches sfname. */
105       if (old_len > new_len
106           && strcmp (sfname, input_filename + old_len - new_len) == 0
107           && (input_filename[old_len - new_len - 1] == '/'
108               || input_filename[old_len - new_len - 1] == '\\'))
109         return;
110     }
111   input_filename = sfname;
112   DECL_SOURCE_FILE (TYPE_NAME (current_class)) = sfname;
113   if (current_class == main_class) main_input_filename = input_filename;
114 }
115
116 #define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)
117
118 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
119 { tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
120   current_class = give_name_to_class (jcf, THIS); \
121   set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
122
123 #define HANDLE_CLASS_INTERFACE(INDEX) \
124   add_interface (current_class, get_class_constant (jcf, INDEX))
125
126 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
127 { int sig_index = SIGNATURE; \
128   current_field = add_field (current_class, get_name_constant (jcf, NAME), \
129                              parse_signature (jcf, sig_index), ACCESS_FLAGS); \
130  set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); }
131
132 #define HANDLE_END_FIELDS() \
133   (current_field = NULL_TREE)
134
135 #define HANDLE_CONSTANTVALUE(INDEX) \
136 { tree constant;  int index = INDEX; \
137   if (! flag_emit_class_files && JPOOL_TAG (jcf, index) == CONSTANT_String) { \
138     tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \
139     constant = build_utf8_ref (name); \
140   } \
141   else \
142     constant = get_constant (jcf, index); \
143   set_constant_value (current_field, constant); }
144
145 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
146  (current_method = add_method (current_class, ACCESS_FLAGS, \
147                                get_name_constant (jcf, NAME), \
148                                get_name_constant (jcf, SIGNATURE)), \
149   DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \
150   DECL_LINENUMBERS_OFFSET (current_method) = 0)
151
152 #define HANDLE_END_METHODS() \
153 { tree handle_type = CLASS_TO_HANDLE_TYPE (current_class); \
154   if (handle_type != current_class) layout_type (handle_type); }
155
156 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
157 { DECL_MAX_STACK (current_method) = (MAX_STACK); \
158   DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \
159   DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \
160   DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); }
161
162 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
163 { int n = (COUNT); \
164   DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
165   JCF_SKIP (jcf, n * 10); }
166
167 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
168 { int n = (COUNT); \
169   DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
170   JCF_SKIP (jcf, n * 4); }
171
172 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
173 { \
174   int n = COUNT; \
175   tree list = DECL_FUNCTION_THROWS (current_method); \
176   while (--n >= 0) \
177     { \
178       tree thrown_class = get_class_constant (jcf, JCF_readu2 (jcf)); \
179       list = tree_cons (NULL_TREE, thrown_class, list); \
180     } \
181   DECL_FUNCTION_THROWS (current_method) = nreverse (list); \
182 }
183
184 #include "jcf-reader.c"
185
186 static int yydebug;
187
188 tree
189 parse_signature (jcf, sig_index)
190      JCF *jcf;
191      int sig_index;
192 {
193   if (sig_index <= 0 || sig_index >= JPOOL_SIZE(jcf)
194       || JPOOL_TAG (jcf, sig_index) != CONSTANT_Utf8)
195     fatal ("invalid field/method signature");
196   else
197     {
198       return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index),
199                                      JPOOL_UTF_LENGTH (jcf, sig_index));
200     }
201 }
202
203 void
204 init_lex ()
205 {
206   /* Make identifier nodes long enough for the language-specific slots.  */
207   set_identifier_size (sizeof (struct lang_identifier));
208 }
209
210 void
211 set_yydebug (value)
212      int value;
213 {
214   yydebug = value;
215 }
216
217 tree
218 get_constant (jcf, index)
219   JCF *jcf;
220   int index;
221 {
222   tree value;
223   int tag;
224   if (index <= 0 || index >= JPOOL_SIZE(jcf))
225     goto bad;
226   tag = JPOOL_TAG (jcf, index);
227   if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
228     return (tree) jcf->cpool.data[index];
229   push_obstacks (&permanent_obstack, &permanent_obstack);
230   switch (tag)
231     {
232     case CONSTANT_Integer:
233       {
234         jint num = JPOOL_INT(jcf, index);
235         value = build_int_2 (num, num < 0 ? -1 : 0);
236         TREE_TYPE (value) = int_type_node;
237         break;
238       }
239     case CONSTANT_Long:
240       {
241         jint num = JPOOL_INT (jcf, index);
242         HOST_WIDE_INT lo, hi;
243         lshift_double (num, 0, 32, 64, &lo, &hi, 0);
244         num = JPOOL_INT (jcf, index+1);
245         add_double (lo, hi, num, 0, &lo, &hi);
246         value = build_int_2 (lo, hi);
247         TREE_TYPE (value) = long_type_node;
248         force_fit_type (value, 0);
249         break;
250       }
251 #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
252     case CONSTANT_Float:
253       {
254         jint num = JPOOL_INT(jcf, index);
255         REAL_VALUE_TYPE d;
256 #ifdef REAL_ARITHMETIC
257         d = REAL_VALUE_FROM_TARGET_SINGLE (num);
258 #else
259         union { float f;  jint i; } u;
260         u.i = num;
261         d = u.f;
262 #endif
263         value = build_real (float_type_node, d);
264         break;
265       }
266     case CONSTANT_Double:
267       {
268         HOST_WIDE_INT num[2];
269         REAL_VALUE_TYPE d;
270         HOST_WIDE_INT lo, hi;
271         num[0] = JPOOL_INT (jcf, index);
272         lshift_double (num[0], 0, 32, 64, &lo, &hi, 0);
273         num[0] = JPOOL_INT (jcf, index+1);
274         add_double (lo, hi, num[0], 0, &lo, &hi);
275         if (FLOAT_WORDS_BIG_ENDIAN)
276           {
277             num[0] = hi;
278             num[1] = lo;
279           }
280         else
281           {
282             num[0] = lo;
283             num[1] = hi;
284           }
285 #ifdef REAL_ARITHMETIC
286         d = REAL_VALUE_FROM_TARGET_DOUBLE (num);
287 #else
288         {
289           union { double d;  jint i[2]; } u;
290           u.i[0] = (jint) num[0];
291           u.i[1] = (jint) num[1];
292           d = u.d;
293         }
294 #endif
295         value = build_real (double_type_node, d);
296         break;
297       }
298 #endif /* TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT */
299     case CONSTANT_String:
300       {
301         extern struct obstack *expression_obstack;
302         tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
303         const char *utf8_ptr = IDENTIFIER_POINTER (name);
304         unsigned char *str_ptr;
305         int utf8_len = IDENTIFIER_LENGTH (name);
306         const unsigned char *str = (const unsigned char *)utf8_ptr;
307         int i = utf8_len;
308         int str_len;
309
310         /* Count the number of Unicode characters in the string,
311            while checking for a malformed Utf8 string. */
312         for (str_len = 0; i > 0; str_len++)
313           {
314             int char_len = UT8_CHAR_LENGTH (*str);
315             if (char_len < 0 || char_len > 2 || char_len > i)
316               fatal ("bad string constant");
317             str += char_len;
318             i -= char_len;
319           }
320
321         value = make_node (STRING_CST);
322         TREE_TYPE (value) = build_pointer_type (string_type_node);
323         TREE_STRING_LENGTH (value) = 2 * str_len;
324         TREE_STRING_POINTER (value)
325           = obstack_alloc (expression_obstack, 2 * str_len);
326         str_ptr = (unsigned char *) TREE_STRING_POINTER (value);
327         str = (const unsigned char *)utf8_ptr;
328         for (i = 0; i < str_len; i++)
329           {
330             int char_value;
331             int char_len = UT8_CHAR_LENGTH (*str);
332             switch (char_len)
333               {
334               case 1:
335                 char_value = *str++;
336                 break;
337               case 2:
338                 char_value = *str++ & 0x1F;
339                 char_value = (char_value << 6) | (*str++ & 0x3F);
340                 break;
341               case 3:
342                 char_value = *str_ptr++ & 0x0F;
343                 char_value = (char_value << 6) | (*str++ & 0x3F);
344                 char_value = (char_value << 6) | (*str++ & 0x3F);
345                 break;
346               default:
347                 goto bad;
348               }
349             if (BYTES_BIG_ENDIAN)
350               {
351                 *str_ptr++ = char_value >> 8;
352                 *str_ptr++ = char_value & 0xFF;
353               }
354             else
355               {
356                 *str_ptr++ = char_value & 0xFF;
357                 *str_ptr++ = char_value >> 8;
358               }
359           }
360       }
361       break;
362     default:
363       goto bad;
364     }
365   pop_obstacks ();
366   JPOOL_TAG(jcf, index) = tag | CONSTANT_ResolvedFlag;
367   jcf->cpool.data [index] = (jword) value;
368   return value;
369  bad:
370   fatal ("bad value constant type %d, index %d", 
371          JPOOL_TAG( jcf, index ), index);
372 }
373
374 tree
375 get_name_constant (jcf, index)
376   JCF *jcf;
377   int index;
378 {
379   tree name = get_constant (jcf, index);
380   if (TREE_CODE (name) != IDENTIFIER_NODE)
381     fatal ("bad nameandtype index %d", index);
382   return name;
383 }
384
385 static tree
386 give_name_to_class (jcf, i)
387      JCF *jcf;
388      int i;
389 {
390   if (i <= 0 || i >= JPOOL_SIZE(jcf)
391       || JPOOL_TAG (jcf, i) != CONSTANT_Class)
392     fatal ("bad class index %d", i);
393   else
394     {
395       tree this_class;
396       int j = JPOOL_USHORT1 (jcf, i);
397       /* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */
398       tree class_name = unmangle_classname (JPOOL_UTF_DATA (jcf, j),
399                                             JPOOL_UTF_LENGTH (jcf, j));
400       this_class = lookup_class (class_name);
401       input_filename = DECL_SOURCE_FILE (TYPE_NAME (this_class));
402       lineno = 0;
403       if (main_input_filename == NULL && jcf == main_jcf)
404         main_input_filename = input_filename;
405
406       jcf->cpool.data[i] = (jword) this_class;
407       JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
408       return this_class;
409     }
410 }
411
412 /* Get the class of the CONSTANT_Class whose constant pool index is I. */
413
414 tree
415 get_class_constant (JCF *jcf , int i)
416 {
417   tree type;
418   if (i <= 0 || i >= JPOOL_SIZE(jcf)
419       || (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) != CONSTANT_Class)
420     fatal ("bad class index %d", i);
421
422   if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)
423     {
424       int name_index = JPOOL_USHORT1 (jcf, i);
425       /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */
426       const char *name = JPOOL_UTF_DATA (jcf, name_index);
427       int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
428       if (name[0] == '[')  /* Handle array "classes". */
429           type = TREE_TYPE (parse_signature_string (name, nlength));
430       else
431         { 
432           tree cname = unmangle_classname (name, nlength);
433           type = lookup_class (cname);
434         }
435       jcf->cpool.data[i] = (jword) type;
436       JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
437     }
438   else
439     type = (tree) jcf->cpool.data[i];
440   return type;
441 }
442
443 void
444 DEFUN(jcf_out_of_synch, (jcf),
445       JCF *jcf)
446 {
447   char *source = xstrdup (jcf->filename);
448   int i = strlen (source);
449
450   while (source[i] != '.')
451     i--;
452
453   source [i] = '\0';
454   warning ("Class file `%s' out of synch with `%s.java'", 
455            jcf->filename, source);
456   free (source);
457 }
458
459 /* Read a class with the fully qualified-name NAME.
460    Return 1 iff we read the requested file.
461    (It is still possible we failed if the file did not
462    define the class it is supposed to.) */
463
464 int
465 read_class (name)
466      tree name;
467 {
468   JCF this_jcf, *jcf;
469   tree save_current_class = current_class;
470   char *save_input_filename = input_filename;
471   JCF *save_current_jcf = current_jcf;
472   long saved_pos = 0;
473   if (current_jcf->read_state)
474     saved_pos = ftell (current_jcf->read_state);
475
476   push_obstacks (&permanent_obstack, &permanent_obstack);
477
478   /* Search in current zip first.  */
479   if (find_in_current_zip (IDENTIFIER_POINTER (name), &jcf) == 0)
480     {
481       if (find_class (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name),
482                       &this_jcf, 1) == 0)
483         {
484           pop_obstacks ();      /* FIXME: one pop_obstack() per function */
485           return 0;
486         }
487       else
488         {
489           this_jcf.seen_in_zip = 0;
490           current_jcf = &this_jcf;
491           if (this_jcf.outofsynch)
492             jcf_out_of_synch (current_jcf);
493         }
494     }
495   else
496     current_jcf = jcf;
497
498   if (current_jcf->java_source)
499     jcf_parse_source ();
500   else {
501     java_parser_context_save_global ();
502     java_push_parser_context ();
503     input_filename = current_jcf->filename;
504     jcf_parse (current_jcf);
505     java_pop_parser_context (0);
506     java_parser_context_restore_global ();
507   }
508
509   if (!current_jcf->seen_in_zip)
510     JCF_FINISH (current_jcf);
511   pop_obstacks ();
512
513   current_class = save_current_class;
514   input_filename = save_input_filename;
515   current_jcf = save_current_jcf;
516   if (current_jcf->read_state)
517     fseek (current_jcf->read_state, saved_pos, SEEK_SET);
518   return 1;
519 }
520
521 /* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if
522    called from the parser, otherwise it's a RECORD_TYPE node. If
523    VERBOSE is 1, print error message on failure to load a class. */
524
525 /* Replace calls to load_class by having callers call read_class directly
526    - and then perhaps rename read_class to load_class.  FIXME */
527
528 void
529 load_class (class_or_name, verbose)
530      tree class_or_name;
531      int verbose;
532 {
533   tree name;
534
535   /* class_or_name can be the name of the class we want to load */
536   if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
537     name = class_or_name;
538   /* In some cases, it's a dependency that we process earlier that
539      we though */
540   else if (TREE_CODE (class_or_name) == TREE_LIST)
541     name = TYPE_NAME (TREE_PURPOSE (class_or_name));
542   /* Or it's a type in the making */
543   else
544     name = DECL_NAME (TYPE_NAME (class_or_name));
545
546   if (read_class (name) == 0 && verbose)
547     {
548       error ("Cannot find file for class %s.",
549              IDENTIFIER_POINTER (name));
550       if (TREE_CODE (class_or_name) == RECORD_TYPE)
551         TYPE_SIZE (class_or_name) = error_mark_node;
552 #if 0
553       /* FIXME: what to do here?  */
554       if (!strcmp (classpath, DEFAULT_CLASS_PATH))
555         fatal ("giving up");
556 #endif
557       return;
558     }
559 }
560
561 /* Parse a source file when JCF refers to a source file.  */
562
563 static void
564 jcf_parse_source ()
565 {
566   tree file;
567
568   java_parser_context_save_global ();
569   java_push_parser_context ();
570   input_filename = current_jcf->filename;
571   file = get_identifier (input_filename);
572   if (!HAS_BEEN_ALREADY_PARSED_P (file))
573     {
574       if (!(finput = fopen (input_filename, "r")))
575         fatal ("input file `%s' just disappeared - jcf_parse_source",
576                input_filename);
577       parse_source_file (file);
578       if (fclose (finput))
579         fatal ("can't close input file `%s' stream - jcf_parse_source",
580                input_filename);
581     }
582   java_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file));
583   java_parser_context_restore_global ();
584 }
585
586 /* Parse the .class file JCF. */
587
588 void
589 jcf_parse (jcf)
590      JCF* jcf;
591 {
592   int i, code;
593
594   if (jcf_parse_preamble (jcf) != 0)
595     fatal ("Not a valid Java .class file.\n");
596   code = jcf_parse_constant_pool (jcf);
597   if (code != 0)
598     fatal ("error while parsing constant pool");
599   code = verify_constant_pool (jcf);
600   if (code > 0)
601     fatal ("error in constant pool entry #%d\n", code);
602
603   jcf_parse_class (jcf);
604   if (main_class == NULL_TREE)
605     main_class = current_class;
606   if (! quiet_flag && TYPE_NAME (current_class))
607     fprintf (stderr, " %s %s",
608              (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class", 
609              IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
610   if (CLASS_LOADED_P (current_class))
611     return;
612   CLASS_LOADED_P (current_class) = 1;
613
614   for (i = 1; i < JPOOL_SIZE(jcf); i++)
615     {
616       switch (JPOOL_TAG (jcf, i))
617         {
618         case CONSTANT_Class:
619           get_class_constant (jcf, i);
620           break;
621         }
622     }
623   
624   code = jcf_parse_fields (jcf);
625   if (code != 0)
626     fatal ("error while parsing fields");
627   code = jcf_parse_methods (jcf);
628   if (code != 0)
629     fatal ("error while parsing methods");
630   code = jcf_parse_final_attributes (jcf);
631   if (code != 0)
632     fatal ("error while parsing final attributes");
633
634   /* The fields of class_type_node are already in correct order. */
635   if (current_class != class_type_node && current_class != object_type_node)
636     TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));
637
638   push_obstacks (&permanent_obstack, &permanent_obstack);
639   layout_class (current_class);
640   if (current_class == object_type_node)
641     layout_class_methods (object_type_node);
642   else
643     all_class_list = tree_cons (NULL_TREE, 
644                                 TYPE_NAME (current_class), all_class_list );
645   pop_obstacks ();
646 }
647
648 void
649 init_outgoing_cpool ()
650 {
651   current_constant_pool_data_ref = NULL_TREE; 
652   if (outgoing_cpool == NULL)
653     {
654       static CPool outgoing_cpool_buffer;
655       outgoing_cpool = &outgoing_cpool_buffer;
656       CPOOL_INIT(outgoing_cpool);
657     }
658   else
659     {
660       CPOOL_REINIT(outgoing_cpool);
661     }
662 }
663
664 static void
665 parse_class_file ()
666 {
667   tree method;
668   char *save_input_filename = input_filename;
669   int save_lineno = lineno;
670
671   java_layout_seen_class_methods ();
672
673   input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class));
674   lineno = 0;
675   debug_start_source_file (input_filename);
676   init_outgoing_cpool ();
677
678   for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class));
679         method != NULL_TREE; method = TREE_CHAIN (method))
680     {
681       JCF *jcf = current_jcf;
682
683       if (METHOD_NATIVE (method) || METHOD_ABSTRACT (method))
684         continue;
685
686       if (DECL_CODE_OFFSET (method) == 0)
687         {
688           error ("missing Code attribute");
689           continue;
690         }
691
692       lineno = 0;
693       if (DECL_LINENUMBERS_OFFSET (method))
694         {
695           register int i;
696           register unsigned char *ptr;
697           JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method));
698           linenumber_count = i = JCF_readu2 (jcf);
699           linenumber_table = ptr = jcf->read_ptr;
700
701           for (ptr += 2; --i >= 0; ptr += 4)
702             {
703               int line = GET_u2 (ptr);
704               /* Set initial lineno lineno to smallest linenumber.
705                * Needs to be set before init_function_start. */
706               if (lineno == 0 || line < lineno)
707                 lineno = line;
708             }  
709         }
710       else
711         {
712           linenumber_table = NULL;
713           linenumber_count = 0;
714         }
715
716       start_java_method (method);
717
718       give_name_to_locals (jcf);
719
720       /* Actually generate code. */
721       expand_byte_code (jcf, method);
722
723       end_java_method ();
724     }
725
726   if (flag_emit_class_files)
727     write_classfile (current_class);
728
729   finish_class ();
730
731   debug_end_source_file (save_lineno);
732   input_filename = save_input_filename;
733   lineno = save_lineno;
734 }
735
736 /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */
737
738 static void
739 parse_source_file (file)
740      tree file;
741 {
742   int save_error_count = java_error_count;
743   /* Mark the file as parsed */
744   HAS_BEEN_ALREADY_PARSED_P (file) = 1;
745
746   jcf_dependency_add_file (input_filename, 0);
747
748   lang_init_source (1);             /* Error msgs have no method prototypes */
749
750   java_init_lex ();                 /* Initialize the parser */
751   java_parse_abort_on_error ();
752
753   java_parse ();                    /* Parse and build partial tree nodes. */
754   java_parse_abort_on_error ();
755   java_complete_class ();           /* Parse unsatisfied class decl. */
756   java_parse_abort_on_error ();
757   java_check_circular_reference (); /* Check on circular references */
758   java_parse_abort_on_error ();
759   java_fix_constructors ();         /* Fix the constructors */
760   java_parse_abort_on_error ();
761 }
762
763 static int
764 predefined_filename_p (node)
765      tree node;
766 {
767   int i;
768   for (i = 0; i < predef_filenames_size; i++)
769     if (predef_filenames [i] == node)
770       return 1;
771   return 0;
772 }
773
774 int
775 yyparse ()
776 {
777   int several_files = 0;
778   char *list = xstrdup (input_filename), *next;
779   tree node, current_file_list = NULL_TREE;
780
781   do 
782     {
783       next = strchr (list, '&');
784       if (next)
785         {
786           *next++ = '\0';
787           several_files = 1;
788         }
789
790       if (list[0]) 
791         {
792           char *value;
793           tree id;
794           int twice = 0;
795
796           int len = strlen (list);
797
798           if (*list != '/' && several_files)
799             obstack_grow (&temporary_obstack, "./", 2);
800
801           obstack_grow0 (&temporary_obstack, list, len);
802           value = obstack_finish (&temporary_obstack);
803
804           /* Exclude file that we see twice on the command line. For
805              all files except {Class,Error,Object,RuntimeException,String,
806              Throwable}.java we can rely on maybe_get_identifier. For
807              these files, we need to do a linear search of
808              current_file_list. This search happens only for these
809              files, presumably only when we're recompiling libgcj. */
810              
811           if ((id = maybe_get_identifier (value)))
812             {
813               if (predefined_filename_p (id))
814                 {
815                   tree c;
816                   for (c = current_file_list; c; c = TREE_CHAIN (c))
817                     if (TREE_VALUE (c) == id)
818                       twice = 1;
819                 }
820               else
821                 twice = 1;
822             }
823
824           if (twice)
825             {
826               char *saved_input_filename = input_filename;
827               input_filename = value;
828               warning ("source file seen twice on command line and will be "
829                        "compiled only once.");
830               input_filename = saved_input_filename;
831             }
832           else
833             {
834               node = get_identifier (value);
835               IS_A_COMMAND_LINE_FILENAME_P (node) = 1;
836               current_file_list = tree_cons (NULL_TREE, node, 
837                                              current_file_list);
838             }
839         }
840       list = next;
841     }
842   while (next);
843
844   current_jcf = main_jcf;
845   current_file_list = nreverse (current_file_list);
846   for (node = current_file_list; node; node = TREE_CHAIN (node))
847     {
848       tree name = TREE_VALUE (node);
849
850       /* Skip already parsed files */
851       if (HAS_BEEN_ALREADY_PARSED_P (name))
852         continue;
853       
854       /* Close previous descriptor, if any */
855       if (main_jcf->read_state && fclose (main_jcf->read_state))
856         fatal ("failed to close input file `%s' - yyparse",
857                (main_jcf->filename ? main_jcf->filename : "<unknown>"));
858       
859       /* Set jcf up and open a new file */
860       JCF_ZERO (main_jcf);
861       main_jcf->read_state = fopen (IDENTIFIER_POINTER (name), "rb");
862       if (main_jcf->read_state == NULL)
863         pfatal_with_name (IDENTIFIER_POINTER (name));
864       
865       /* Set new input_filename and finput */
866       finput = main_jcf->read_state;
867 #ifdef IO_BUFFER_SIZE
868       setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE),
869                _IOFBF, IO_BUFFER_SIZE);
870 #endif
871       input_filename = IDENTIFIER_POINTER (name);
872       main_jcf->filbuf = jcf_filbuf_from_stdio;
873
874       switch (jcf_figure_file_type (current_jcf))
875         {
876         case JCF_ZIP:
877           parse_zip_file_entries ();
878           break;
879         case JCF_CLASS:
880           jcf_parse (current_jcf);
881           parse_class_file ();
882           break;
883         case JCF_SOURCE:
884           java_push_parser_context ();
885           java_parser_context_save_global ();
886           parse_source_file (name);
887           java_parser_context_restore_global ();
888           java_pop_parser_context (1);
889           break;
890         }
891     }
892
893   java_expand_classes ();
894   if (!java_report_errors () && !flag_syntax_only)
895     emit_register_classes ();
896   return 0;
897 }
898
899 static struct ZipFileCache *localToFile;
900
901 /* Process all class entries found in the zip file.  */
902 static void
903 parse_zip_file_entries (void)
904 {
905   struct ZipDirectory *zdir;
906   int i;
907
908   for (i = 0, zdir = (ZipDirectory *)localToFile->z.central_directory;
909        i < localToFile->z.count; i++, zdir = ZIPDIR_NEXT (zdir))
910     {
911       tree class;
912       
913       /* We don't need to consider those files.  */
914       if (!zdir->size || !zdir->filename_offset)
915         continue;
916
917       class = lookup_class (get_identifier (ZIPDIR_FILENAME (zdir)));
918       current_jcf = TYPE_LANG_SPECIFIC (class)->jcf;
919       current_class = class;
920
921       if ( !CLASS_LOADED_P (class))
922         {
923           fseek (current_jcf->read_state, current_jcf->zip_offset, SEEK_SET);
924           jcf_parse (current_jcf);
925         }
926
927       if (TYPE_SIZE (current_class) != error_mark_node)
928         {
929           input_filename = current_jcf->filename;
930           parse_class_file ();
931           FREE (current_jcf->buffer); /* No longer necessary */
932           /* Note: there is a way to free this buffer right after a
933              class seen in a zip file has been parsed. The idea is the
934              set its jcf in such a way that buffer will be reallocated
935              the time the code for the class will be generated. FIXME. */
936         }
937     }
938 }
939
940 /* Read all the entries of the zip file, creates a class and a JCF. Sets the
941    jcf up for further processing and link it to the created class.  */
942
943 static void process_zip_dir()
944 {
945   int i;
946   ZipDirectory *zdir;
947
948   for (i = 0, zdir = (ZipDirectory *)localToFile->z.central_directory;
949        i < localToFile->z.count; i++, zdir = ZIPDIR_NEXT (zdir))
950     {
951       char *class_name, *file_name, *class_name_in_zip_dir;
952       tree class;
953       JCF  *jcf;
954       int   j;
955
956       class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
957
958       /* We choose to not to process entries with a zero size or entries
959          not bearing the .class extention.  */
960       if (!zdir->size || !zdir->filename_offset ||
961           strncmp (&class_name_in_zip_dir[zdir->filename_length-6], 
962                    ".class", 6))
963         {
964           /* So it will be skipped in parse_zip_file_entries  */
965           zdir->size = 0;  
966           continue;
967         }
968
969       class_name = ALLOC (zdir->filename_length+1-6);
970       file_name  = ALLOC (zdir->filename_length+1);
971       jcf = ALLOC (sizeof (JCF));
972       JCF_ZERO (jcf);
973
974       strncpy (class_name, class_name_in_zip_dir, zdir->filename_length-6);
975       class_name [zdir->filename_length-6] = '\0';
976       strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
977       file_name [zdir->filename_length] = '\0';
978
979       for (j=0; class_name[j]; j++)
980         class_name [j] = (class_name [j] == '/' ? '.' : class_name [j]);
981
982       /* Yes, we write back the true class name into the zip directory.  */
983       strcpy (class_name_in_zip_dir, class_name);
984       zdir->filename_length = j;
985       class = lookup_class (get_identifier (class_name));
986
987       jcf->read_state  = finput;
988       jcf->filbuf      = jcf_filbuf_from_stdio;
989       jcf->seen_in_zip = 1;
990       jcf->java_source = 0;
991       jcf->zip_offset  = zdir->filestart;
992       jcf->classname   = class_name;
993       jcf->filename    = file_name;
994
995       TYPE_LANG_SPECIFIC (class) = 
996         (struct lang_type *) perm_calloc (1, sizeof (struct lang_type));
997       TYPE_LANG_SPECIFIC (class)->jcf = jcf;
998     }
999 }
1000
1001 /* Lookup class NAME and figure whether is a class already found in the current
1002    zip file.  */
1003 static int
1004 DEFUN(find_in_current_zip, (name, length, jcf),
1005       const char *name AND JCF **jcf)
1006 {
1007   JCF *local_jcf;
1008   tree class_name = maybe_get_identifier (name), class, icv;
1009
1010   if (!class_name)
1011     return 0;
1012
1013   if (!(icv = IDENTIFIER_CLASS_VALUE (class_name)))
1014     return 0;
1015
1016   class = TREE_TYPE (icv);
1017
1018   /* Doesn't have jcf specific info ? It's not ours */
1019   if (!TYPE_LANG_SPECIFIC (class) || !TYPE_LANG_SPECIFIC (class)->jcf)
1020     return 0;
1021
1022   *jcf = local_jcf = TYPE_LANG_SPECIFIC (class)->jcf;
1023   fseek (local_jcf->read_state, local_jcf->zip_offset, SEEK_SET);
1024   return 1;
1025 }
1026
1027 /* Figure what kind of file we're dealing with */
1028 static int
1029 DEFUN(jcf_figure_file_type, (jcf),
1030       JCF *jcf)
1031 {
1032   unsigned char magic_string[4];
1033   uint32 magic;
1034
1035   if (fread (magic_string, 1, 4, jcf->read_state) != 4)
1036     jcf_unexpected_eof (jcf, 4);
1037
1038   fseek (jcf->read_state, 0L, SEEK_SET);
1039   magic = GET_u4 (magic_string);
1040
1041   if (magic == 0xcafebabe)
1042     return JCF_CLASS;
1043
1044   /* FIXME: is it a system file?  */
1045   if (magic ==  (JCF_u4)ZIPMAGIC
1046       && !open_in_zip (jcf, input_filename, NULL, 0))
1047     {
1048       localToFile = ALLOC (sizeof (struct ZipFileCache));
1049       bcopy ((PTR) SeenZipFiles, (PTR) localToFile, sizeof (struct ZipFileCache));
1050       process_zip_dir ();       /* Register all the class defined there */
1051       return JCF_ZIP;
1052     }
1053
1054   return JCF_SOURCE;
1055 }
1056