X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjava%2Fjcf-parse.c;h=09991eb818ed86a8d5f597462b8cdd665d00d9fd;hb=4654e794323c05fcfabee95cb2bf334fb30a3873;hp=ad0b80763d3fefe43624450447d0f4bcb207918d;hpb=ab8838f3d0dd5d5e0f47d337bfadb1ac5cb1498d;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index ad0b80763d3..09991eb818e 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -1,5 +1,5 @@ /* 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. @@ -33,12 +33,13 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "input.h" #include "java-tree.h" #include "toplev.h" +#include "parse.h" /* A CONSTANT_Utf8 element is converted to an IDENTIFIER_NODE at parse time. */ #define JPOOL_UTF(JCF, INDEX) CPOOL_UTF(&(JCF)->cpool, INDEX) #define JPOOL_UTF_LENGTH(JCF, INDEX) IDENTIFIER_LENGTH (JPOOL_UTF (JCF, INDEX)) #define JPOOL_UTF_DATA(JCF, INDEX) \ - ((unsigned char*) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX))) + ((const unsigned char *) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX))) #define HANDLE_CONSTANT_Utf8(JCF, INDEX, LENGTH) \ do { \ unsigned char save; unsigned char *text; \ @@ -56,10 +57,9 @@ extern struct obstack *saveable_obstack; 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; @@ -76,16 +76,24 @@ static tree current_field = NULL_TREE; /* The METHOD_DECL for the current method. */ static tree current_method = NULL_TREE; +/* The Java .class file that provides main_class; the main input file. */ +static struct JCF main_jcf[1]; + /* Declarations of some functions used here. */ -static tree give_name_to_class PROTO ((JCF *jcf, int index)); -void parse_zip_file_entries PROTO (()); -void process_zip_dir PROTO (()); -static void parse_source_file PROTO ((tree)); -static void jcf_parse_source PROTO ((JCF *)); +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. */ -void +static void set_source_filename (jcf, index) JCF *jcf; int index; @@ -177,6 +185,32 @@ set_source_filename (jcf, index) 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; @@ -296,10 +330,10 @@ get_constant (jcf, index) { extern struct obstack *expression_obstack; tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); - char *utf8_ptr = IDENTIFIER_POINTER (name); + const char *utf8_ptr = IDENTIFIER_POINTER (name); unsigned char *str_ptr; int utf8_len = IDENTIFIER_LENGTH (name); - unsigned char *str = (unsigned char*)utf8_ptr; + const unsigned char *str = (const unsigned char *)utf8_ptr; int i = utf8_len; int str_len; @@ -320,7 +354,7 @@ get_constant (jcf, index) TREE_STRING_POINTER (value) = obstack_alloc (expression_obstack, 2 * str_len); str_ptr = (unsigned char *) TREE_STRING_POINTER (value); - str = (unsigned char*)utf8_ptr; + str = (const unsigned char *)utf8_ptr; for (i = 0; i < str_len; i++) { int char_value; @@ -419,7 +453,7 @@ get_class_constant (JCF *jcf , int i) { int name_index = JPOOL_USHORT1 (jcf, i); /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */ - char *name = JPOOL_UTF_DATA (jcf, name_index); + const char *name = JPOOL_UTF_DATA (jcf, name_index); int nlength = JPOOL_UTF_LENGTH (jcf, name_index); if (name[0] == '[') /* Handle array "classes". */ type = TREE_TYPE (parse_signature_string (name, nlength)); @@ -436,22 +470,6 @@ get_class_constant (JCF *jcf , int i) return type; } -void -DEFUN(jcf_out_of_synch, (jcf), - JCF *jcf) -{ - char *source = strdup (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 @@ -465,38 +483,32 @@ read_class (name) tree save_current_class = current_class; char *save_input_filename = input_filename; JCF *save_current_jcf = current_jcf; - long saved_pos; + long saved_pos = 0; if (current_jcf->read_state) saved_pos = ftell (current_jcf->read_state); push_obstacks (&permanent_obstack, &permanent_obstack); /* Search in current zip first. */ - if (find_in_current_zip (IDENTIFIER_POINTER (name), - IDENTIFIER_LENGTH (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_in_current_zip (IDENTIFIER_POINTER (name), &jcf) == 0) + { + 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; if (current_jcf->java_source) - jcf_parse_source (current_jcf); + jcf_parse_source (); else { java_parser_context_save_global (); java_push_parser_context (); @@ -544,25 +556,13 @@ load_class (class_or_name, verbose) 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. */ -void -jcf_parse_source (jcf) - JCF *jcf; +static void +jcf_parse_source () { tree file; @@ -591,6 +591,7 @@ jcf_parse (jcf) JCF* jcf; { int i, code; + tree current; if (jcf_parse_preamble (jcf) != 0) fatal ("Not a valid Java .class file.\n"); @@ -605,7 +606,8 @@ jcf_parse (jcf) if (main_class == NULL_TREE) main_class = current_class; if (! quiet_flag && TYPE_NAME (current_class)) - fprintf (stderr, " class %s", + fprintf (stderr, " %s %s", + (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)))); if (CLASS_LOADED_P (current_class)) return; @@ -642,26 +644,24 @@ jcf_parse (jcf) 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)); } -void +static void parse_class_file () { tree method; @@ -675,6 +675,10 @@ parse_class_file () 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)) { @@ -726,7 +730,7 @@ parse_class_file () if (flag_emit_class_files) write_classfile (current_class); - finish_class (current_class); + finish_class (); debug_end_source_file (save_lineno); input_filename = save_input_filename; @@ -743,6 +747,8 @@ parse_source_file (file) /* Mark the file as parsed */ HAS_BEEN_ALREADY_PARSED_P (file) = 1; + jcf_dependency_add_file (input_filename, 0); + lang_init_source (1); /* Error msgs have no method prototypes */ java_init_lex (); /* Initialize the parser */ @@ -754,13 +760,27 @@ parse_source_file (file) 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 +predefined_filename_p (node) + tree node; +{ + int i; + for (i = 0; i < predef_filenames_size; i++) + if (predef_filenames [i] == node) + return 1; + return 0; } int yyparse () { int several_files = 0; - char *list = strdup (input_filename), *next; + char *list = xstrdup (input_filename), *next; tree node, current_file_list = NULL_TREE; do @@ -775,21 +795,51 @@ yyparse () if (list[0]) { char *value; + tree id; + 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); obstack_grow0 (&temporary_obstack, list, len); value = obstack_finish (&temporary_obstack); - node = get_identifier (value); - IS_A_COMMAND_LINE_FILENAME_P (node) = 1; - current_file_list = tree_cons (NULL_TREE, node, current_file_list); + + /* Exclude file that we see twice on the command line. For + all files except {Class,Error,Object,RuntimeException,String, + Throwable}.java we can rely on maybe_get_identifier. For + these files, we need to do a linear search of + current_file_list. This search happens only for these + files, presumably only when we're recompiling libgcj. */ + + if ((id = maybe_get_identifier (value))) + { + if (predefined_filename_p (id)) + { + tree c; + for (c = current_file_list; c; c = TREE_CHAIN (c)) + if (TREE_VALUE (c) == id) + twice = 1; + } + else + twice = 1; + } + + if (twice) + { + char *saved_input_filename = input_filename; + input_filename = value; + warning ("source file seen twice on command line and will be compiled only once."); + input_filename = saved_input_filename; + } + else + { + node = get_identifier (value); + IS_A_COMMAND_LINE_FILENAME_P (node) = 1; + current_file_list = tree_cons (NULL_TREE, node, + current_file_list); + } } list = next; } @@ -853,7 +903,7 @@ yyparse () static struct ZipFileCache *localToFile; /* Process all class entries found in the zip file. */ -void +static void parse_zip_file_entries (void) { struct ZipDirectory *zdir; @@ -869,7 +919,7 @@ parse_zip_file_entries (void) 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)) @@ -894,7 +944,7 @@ parse_zip_file_entries (void) /* Read all the entries of the zip file, creates a class and a JCF. Sets the jcf up for further processing and link it to the created class. */ -void process_zip_dir() +static void process_zip_dir() { int i; ZipDirectory *zdir; @@ -946,17 +996,15 @@ void process_zip_dir() 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; } } /* Lookup class NAME and figure whether is a class already found in the current zip file. */ -int +static int DEFUN(find_in_current_zip, (name, length, jcf), - char *name AND int length AND JCF **jcf) + const char *name AND JCF **jcf) { JCF *local_jcf; tree class_name = maybe_get_identifier (name), class, icv; @@ -970,16 +1018,16 @@ DEFUN(find_in_current_zip, (name, length, 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; } /* Figure what kind of file we're dealing with */ -int +static int DEFUN(jcf_figure_file_type, (jcf), JCF *jcf) { @@ -1000,7 +1048,7 @@ DEFUN(jcf_figure_file_type, (jcf), && !open_in_zip (jcf, input_filename, NULL, 0)) { localToFile = ALLOC (sizeof (struct ZipFileCache)); - bcopy (SeenZipFiles, localToFile, sizeof (struct ZipFileCache)); + bcopy ((PTR) SeenZipFiles, (PTR) localToFile, sizeof (struct ZipFileCache)); process_zip_dir (); /* Register all the class defined there */ return JCF_ZIP; }