OSDN Git Service

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