OSDN Git Service

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