OSDN Git Service

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