/* Parser for Java(TM) .class files.
- Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
extern struct obstack temporary_obstack;
extern struct obstack permanent_obstack;
-/* This is true if the user specified a `.java' file on the command
- line. Otherwise it is 0. FIXME: this is temporary, until our
- .java parser is fully working. */
-int saw_java_source = 0;
+/* Set to non-zero value in order to emit class initilization code
+ before static field references. */
+extern int always_initialize_class_p;
/* The class we are currently processing. */
tree current_class = NULL_TREE;
static struct JCF main_jcf[1];
/* Declarations of some functions used here. */
-static tree give_name_to_class PROTO ((JCF *jcf, int index));
-static void parse_zip_file_entries PROTO ((void));
-static void process_zip_dir PROTO ((void));
-static void parse_source_file PROTO ((tree));
-static void jcf_parse_source PROTO ((void));
-static int jcf_figure_file_type PROTO ((JCF *));
-static int find_in_current_zip PROTO ((const char *, struct JCF **));
-static void parse_class_file PROTO ((void));
-static void set_source_filename PROTO ((JCF *, int));
-static int predefined_filename_p PROTO ((tree));
+static tree give_name_to_class PARAMS ((JCF *jcf, int index));
+static void parse_zip_file_entries PARAMS ((void));
+static void process_zip_dir PARAMS ((void));
+static void parse_source_file PARAMS ((tree));
+static void jcf_parse_source PARAMS ((void));
+static int jcf_figure_file_type PARAMS ((JCF *));
+static int find_in_current_zip PARAMS ((const char *, struct JCF **));
+static void parse_class_file PARAMS ((void));
+static void set_source_filename PARAMS ((JCF *, int));
+static int predefined_filename_p PARAMS ((tree));
/* Handle "SourceFile" attribute. */
DECL_FUNCTION_THROWS (current_method) = nreverse (list); \
}
+/* Link seen inner classes to their outer context and register the
+ inner class to its outer context. They will be later loaded. */
+#define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
+{ \
+ int c = (count); \
+ while (c--) \
+ { \
+ tree class = get_class_constant (jcf, JCF_readu2 (jcf)); \
+ if (!CLASS_COMPLETE_P (class)) \
+ { \
+ tree outer = TYPE_NAME (get_class_constant (jcf, \
+ JCF_readu2 (jcf))); \
+ tree alias = get_name_constant (jcf, JCF_readu2 (jcf)); \
+ tree decl = TYPE_NAME (class); \
+ JCF_SKIP (jcf, 2); \
+ IDENTIFIER_GLOBAL_VALUE (alias) = decl; \
+ DECL_CONTEXT (decl) = outer; \
+ DECL_INNER_CLASS_LIST (outer) = \
+ tree_cons (decl, alias, DECL_INNER_CLASS_LIST (outer)); \
+ CLASS_COMPLETE_P (class) = 1; \
+ } \
+ else \
+ JCF_SKIP (jcf, 6); \
+ } \
+}
+
#include "jcf-reader.c"
static int yydebug;
return type;
}
-void
-DEFUN(jcf_out_of_synch, (jcf),
- JCF *jcf)
-{
- char *source = xstrdup (jcf->filename);
- int i = strlen (source);
-
- while (source[i] != '.')
- i--;
-
- source [i] = '\0';
- warning ("Class file `%s' out of synch with `%s.java'",
- jcf->filename, source);
- free (source);
-}
-
/* Read a class with the fully qualified-name NAME.
Return 1 iff we read the requested file.
(It is still possible we failed if the file did not
/* Search in current zip first. */
if (find_in_current_zip (IDENTIFIER_POINTER (name), &jcf) == 0)
- /* FIXME: until the `.java' parser is fully working, we only
- look for a .java file when one was mentioned on the
- command line. This lets us test the .java parser fairly
- easily, without compromising our ability to use the
- .class parser without fear. */
- if (find_class (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name),
- &this_jcf, saw_java_source) == 0)
- {
- pop_obstacks (); /* FIXME: one pop_obstack() per function */
- return 0;
- }
- else
- {
- this_jcf.seen_in_zip = 0;
- current_jcf = &this_jcf;
- if (this_jcf.outofsynch)
- jcf_out_of_synch (current_jcf);
- }
+ {
+ if (find_class (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name),
+ &this_jcf, 1) == 0)
+ {
+ pop_obstacks (); /* FIXME: one pop_obstack() per function */
+ return 0;
+ }
+ else
+ {
+ this_jcf.seen_in_zip = 0;
+ current_jcf = &this_jcf;
+ }
+ }
else
current_jcf = jcf;
name = DECL_NAME (TYPE_NAME (class_or_name));
if (read_class (name) == 0 && verbose)
- {
- error ("Cannot find file for class %s.",
- IDENTIFIER_POINTER (name));
- if (TREE_CODE (class_or_name) == RECORD_TYPE)
- TYPE_SIZE (class_or_name) = error_mark_node;
-#if 0
- /* FIXME: what to do here? */
- if (!strcmp (classpath, DEFAULT_CLASS_PATH))
- fatal ("giving up");
-#endif
- return;
- }
+ fatal ("Cannot find file for class %s.", IDENTIFIER_POINTER (name));
}
/* Parse a source file when JCF refers to a source file. */
JCF* jcf;
{
int i, code;
+ tree current;
if (jcf_parse_preamble (jcf) != 0)
fatal ("Not a valid Java .class file.\n");
else
all_class_list = tree_cons (NULL_TREE,
TYPE_NAME (current_class), all_class_list );
+
+ /* And if we came accross inner classes, load them now. */
+ for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (current_class)); current;
+ current = TREE_CHAIN (current))
+ load_class (DECL_NAME (TREE_PURPOSE (current)), 1);
+
pop_obstacks ();
}
void
init_outgoing_cpool ()
{
- current_constant_pool_data_ref = NULL_TREE;
- if (outgoing_cpool == NULL)
- {
- static CPool outgoing_cpool_buffer;
- outgoing_cpool = &outgoing_cpool_buffer;
- CPOOL_INIT(outgoing_cpool);
- }
- else
- {
- CPOOL_REINIT(outgoing_cpool);
- }
+ current_constant_pool_data_ref = NULL_TREE;
+ outgoing_cpool = (struct CPool *)xmalloc (sizeof (struct CPool));
+ bzero (outgoing_cpool, sizeof (struct CPool));
}
static void
debug_start_source_file (input_filename);
init_outgoing_cpool ();
+ /* Currently we always have to emit calls to _Jv_InitClass when
+ compiling from class files. */
+ always_initialize_class_p = 1;
+
for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class));
method != NULL_TREE; method = TREE_CHAIN (method))
{
java_parse_abort_on_error ();
java_check_circular_reference (); /* Check on circular references */
java_parse_abort_on_error ();
+ java_fix_constructors (); /* Fix the constructors */
+ java_parse_abort_on_error ();
+ java_reorder_fields (); /* Reorder the fields */
}
static int
int twice = 0;
int len = strlen (list);
- /* FIXME: this test is only needed until our .java parser is
- fully capable. */
- if (len > 5 && ! strcmp (&list[len - 5], ".java"))
- saw_java_source = 1;
if (*list != '/' && several_files)
obstack_grow (&temporary_obstack, "./", 2);
{
char *saved_input_filename = input_filename;
input_filename = value;
- warning ("source file seen twice on command line and will be "
- "compiled only once.");
+ warning ("source file seen twice on command line and will be compiled only once.");
input_filename = saved_input_filename;
}
else
continue;
class = lookup_class (get_identifier (ZIPDIR_FILENAME (zdir)));
- current_jcf = TYPE_LANG_SPECIFIC (class)->jcf;
+ current_jcf = TYPE_JCF (class);
current_class = class;
if ( !CLASS_LOADED_P (class))
jcf->classname = class_name;
jcf->filename = file_name;
- TYPE_LANG_SPECIFIC (class) =
- (struct lang_type *) perm_calloc (1, sizeof (struct lang_type));
- TYPE_LANG_SPECIFIC (class)->jcf = jcf;
+ TYPE_JCF (class) = jcf;
}
}
class = TREE_TYPE (icv);
/* Doesn't have jcf specific info ? It's not ours */
- if (!TYPE_LANG_SPECIFIC (class) || !TYPE_LANG_SPECIFIC (class)->jcf)
+ if (!TYPE_JCF (class))
return 0;
- *jcf = local_jcf = TYPE_LANG_SPECIFIC (class)->jcf;
+ *jcf = local_jcf = TYPE_JCF (class);
fseek (local_jcf->read_state, local_jcf->zip_offset, SEEK_SET);
return 1;
}