From fea2d5da9c4a43852594336efa2ff45283f5595b Mon Sep 17 00:00:00 2001 From: Per Bothner Date: Fri, 23 Feb 2001 19:28:39 -0800 Subject: [PATCH] Handle compiling multiple input files at once, and @FILE syntax. See ChangeLog. From-SVN: r40024 --- gcc/java/ChangeLog | 28 +++++++++++ gcc/java/java-tree.h | 3 ++ gcc/java/jcf-parse.c | 99 ++++++++++++++++++++++++++++++++---- gcc/java/jvspec.c | 108 +++++++++++++++++++++------------------- gcc/java/lang-options.h | 1 + gcc/java/lang.c | 5 ++ gcc/java/lex.c | 2 +- gcc/java/parse.y | 48 ++++++++++-------- 8 files changed, 208 insertions(+), 86 deletions(-) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 3dd8de4ebab..56cd3cce1de 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,31 @@ +2001-02-16 Per Bothner + + Handle compiling multiple input files at once, and @FILE syntax. + * java-tree.h (flag_filelist_file, init_src_parse): New declarations. + * jcf-parse.c (parse_source_file): Split into ... + (parse_source_file_1): New function - and: + (parse_source_file_2): New function. + (yyparse): On -ffilelist-file, open and scan named file. + On first pass over files, only do parse_source_file_1. + A new second pass calls parse_source_file_2 for each file to compile. + (init_jcf_parse): Call init_src_parse. + * jvspec.c (INDIRECT_FILE_ARG): New flag. + (lang_specific_driver): Support @FILELIST-FILE syntax, as well + as multiple input file combined in one compilation. + * lang-options.h: Add -ffilelist-file + * lang.c (flag_filelist_file): New flag variable. + (lang_f_options): Handle -ffilelist-file. + * lex.c (java_init_lex): Don't clear ctxp->incomplete_class. + * parse.h (struct parse_ctxt): Remove fields incomplete_class and + gclass_list - use global fields of src_parse_roots instead. + * parse.y (src_parse_roots): New array. + (incomplete_class_list, gclass_list): New macros. + (push_parser_context, java_pop_parser_context, + java_parser_context_resume): Don't fiddle with deleted fields. + (various): Use incomplete_class gclass_list and global macros + instead of parse_ctxt fields - the lists are global. + (init_src_parse): New function. + Fri Feb 23 15:28:39 2001 Richard Kenner * decl.c (set_block): Set NAMES and BLOCKS from BLOCK. diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 30b9d874928..cadd5523a07 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -138,6 +138,8 @@ extern int flag_assume_compiled; extern int flag_emit_class_files; +extern int flag_filelist_file; + /* When non zero, assume all native functions are implemented with JNI, not CNI. */ @@ -1111,6 +1113,7 @@ extern boolean java_hash_compare_tree_node PARAMS ((hash_table_key, hash_table_key)); extern void java_check_methods PARAMS ((tree)); extern void init_jcf_parse PARAMS((void)); +extern void init_src_parse PARAMS((void)); extern int cxx_keyword_p PARAMS ((const char *, int)); extern tree java_mangle_decl PARAMS ((struct obstack *, tree)); diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index e8eacc5dee7..6ace7e8134d 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -89,7 +89,8 @@ static void handle_innerclass_attribute PARAMS ((int count, 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 ((FILE *)); -static void parse_source_file PARAMS ((tree, FILE *)); +static void parse_source_file_1 PARAMS ((tree, FILE *)); +static void parse_source_file_2 PARAMS ((void)); static void jcf_parse_source PARAMS ((void)); static int jcf_figure_file_type PARAMS ((JCF *)); static void parse_class_file PARAMS ((void)); @@ -641,7 +642,8 @@ jcf_parse_source () { if (!(finput = fopen (input_filename, "r"))) fatal_io_error ("can't reopen %s", input_filename); - parse_source_file (file, finput); + parse_source_file_1 (file, finput); + parse_source_file_2 (); if (fclose (finput)) fatal_io_error ("can't close %s", input_filename); } @@ -822,7 +824,7 @@ parse_class_file () /* Parse a source file, as pointed by the current value of INPUT_FILENAME. */ static void -parse_source_file (file, finput) +parse_source_file_1 (file, finput) tree file; FILE *finput; { @@ -853,6 +855,14 @@ parse_source_file (file, finput) java_parse (); /* Parse and build partial tree nodes. */ java_parse_abort_on_error (); +} + +/* Process a parsed source file, resolving names etc. */ + +static void +parse_source_file_2 () +{ + int save_error_count = java_error_count; java_complete_class (); /* Parse unsatisfied class decl. */ java_parse_abort_on_error (); java_check_circular_reference (); /* Check on circular references */ @@ -876,18 +886,73 @@ predefined_filename_p (node) int yyparse () { - int several_files = 0; - char *list = xstrdup (input_filename), *next; + int filename_count = 0; + char *list, *next; tree node; FILE *finput; + if (flag_filelist_file) + { + int avail = 2000; + finput = fopen (input_filename, "r"); + if (finput == NULL) + fatal_io_error ("can't open %s", input_filename); + list = xmalloc(avail); + next = list; + for (;;) + { + int count; + if (avail < 500) + { + count = next - list; + avail = 2 * (count + avail); + list = xrealloc (list, avail); + next = list + count; + avail = avail - count; + } + /* Subtract to to guarantee space for final '\0'. */ + count = fread (next, 1, avail - 1, finput); + if (count == 0) + { + if (! feof (finput)) + fatal_io_error ("error closing %s", input_filename); + *next = '\0'; + break; + } + avail -= count; + next += count; + } + fclose (finput); + } + else + list = xstrdup (input_filename); + do { - next = strchr (list, '&'); - if (next) + for (next = list; ; ) { - *next++ = '\0'; - several_files = 1; + char *ch = *next; + if (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ' + || ch == '&' /* FIXME */) + { + if (next == list) + { + next++; + list = next; + continue; + } + else + { + *next++ = '\0'; + break; + } + } + if (ch == '\0') + { + next = NULL; + break; + } + next++; } if (list[0]) @@ -898,12 +963,14 @@ yyparse () int len = strlen (list); - if (*list != '/' && several_files) + if (*list != '/' && filename_count > 0) obstack_grow (&temporary_obstack, "./", 2); obstack_grow0 (&temporary_obstack, list, len); value = obstack_finish (&temporary_obstack); + filename_count++; + /* 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 @@ -943,6 +1010,9 @@ yyparse () } while (next); + if (filename_count == 0) + warning ("no input file specified"); + current_jcf = main_jcf; current_file_list = nreverse (current_file_list); for (node = current_file_list; node; node = TREE_CHAIN (node)) @@ -985,13 +1055,18 @@ yyparse () case JCF_SOURCE: java_push_parser_context (); java_parser_context_save_global (); - parse_source_file (name, finput); + parse_source_file_1 (name, finput); java_parser_context_restore_global (); java_pop_parser_context (1); break; } } + for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next) + { + parse_source_file_2 (); + } + java_expand_classes (); if (!java_report_errors () && !flag_syntax_only) emit_register_classes (); @@ -1137,4 +1212,6 @@ init_jcf_parse () ggc_add_tree_root (parse_roots, sizeof (parse_roots) / sizeof(tree)); ggc_add_root (¤t_jcf, 1, sizeof (JCF), (void (*)(void *))ggc_mark_jcf); + + init_src_parse (); } diff --git a/gcc/java/jvspec.c b/gcc/java/jvspec.c index 749fd133b0b..684811ac5ee 100644 --- a/gcc/java/jvspec.c +++ b/gcc/java/jvspec.c @@ -38,6 +38,8 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #define JAVA_FILE_ARG (1<<3) /* True if this arg is a .class input file name. */ #define CLASS_FILE_ARG (1<<4) +/* True if this arg is @FILE - where FILE contains a list of filenames. */ +#define INDIRECT_FILE_ARG (1<<5) static char *find_spec_file PARAMS ((const char *)); @@ -47,11 +49,6 @@ int lang_specific_extra_outfiles = 0; /* True if we should add -shared-libgcc to the command-line. */ int shared_libgcc = 1; -/* Once we have the proper support in jc1 (and gcc.c) working, - set COMBINE_INPUTS to one. This enables combining multiple *.java - and *.class input files to be passed to a single jc1 invocation. */ -#define COMBINE_INPUTS 0 - const char jvgenmain_spec[] = "jvgenmain %{D*} %i %{!pipe:%umain.i} |\n\ cc1 %{!pipe:%Umain.i} %1 \ @@ -108,7 +105,6 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) link in libgcj. */ int library = 1; -#if COMBINE_INPUTS /* This will be 1 if multiple input files (.class and/or .java) should be passed to a single jc1 invocation. */ int combine_inputs = 0; @@ -116,21 +112,20 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) /* Index of last .java or .class argument. */ int last_input_index; - /* A buffer containing the concatenation of the inputs files - (e.g. "foo.java&bar.class&baz.class"). if combine_inputs. */ - char* combined_inputs_buffer; - - /* Next available location in combined_inputs_buffer. */ - int combined_inputs_pos; - /* Number of .java and .class source file arguments seen. */ int java_files_count = 0; int class_files_count = 0; + /* Number of '@FILES' arguments seen. */ + int indirect_files_count = 0; /* Cumulative length of the .java and .class source file names. */ int java_files_length = 0; int class_files_length = 0; -#endif + + /* Name of file containing list of files to compile. */ + char *filelist_filename; + + FILE *filelist_file; /* The number of arguments being added to what's in argv, other than libraries. We use this to track the number of times we've inserted @@ -149,6 +144,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) already gave a language for the file. */ int saw_speclang = 0; +#if 0 /* "-lm" or "-lmath" if it appears on the command line. */ const char *saw_math ATTRIBUTE_UNUSED = 0; @@ -163,6 +159,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) /* Saw `-lgcj' on command line. */ int saw_libgcj ATTRIBUTE_UNUSED = 0; +#endif /* Saw -C or -o option, respectively. */ int saw_C = 0; @@ -251,9 +248,6 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) { saw_C = 1; want_spec_file = 0; -#if COMBINE_INPUTS - combine_inputs = 1; -#endif if (library != 0) added -= 2; library = 0; @@ -317,9 +311,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) } else { -#if COMBINE_INPUTS int len; -#endif if (saw_speclang) { @@ -327,7 +319,12 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) continue; } -#if COMBINE_INPUTS + if (argv[i][0] == '@') + { + args[i] |= INDIRECT_FILE_ARG; + indirect_files_count++; + } + len = strlen (argv[i]); if (len > 5 && strcmp (argv[i] + len - 5, ".java") == 0) { @@ -343,7 +340,6 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) class_files_length += len; last_input_index = i; } -#endif } } @@ -357,33 +353,34 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) if (saw_C) { num_args += 3; -#if COMBINE_INPUTS - class_files_length = 0; - num_args -= class_files_count; + if (class_files_count > 0) + { + error ("Warning: already-compiled .class files ignored with -C"); + class_files_count = 0; + num_args -= class_files_count; + } num_args += 2; /* For -o NONE. */ -#endif if (saw_o) fatal ("cannot specify both -C and -o"); } -#if COMBINE_INPUTS if (saw_o && java_files_count + (saw_C ? 0 : class_files_count) > 1) combine_inputs = 1; + if (class_files_count > 1) + combine_inputs = 1; if (combine_inputs) { - int len = java_files_length + java_files_count - 1; - num_args -= java_files_count; + filelist_filename = make_temp_file ("jx"); + if (filelist_filename == NULL) + fatal ("cannot create temporary file"); + record_temp_file (filelist_filename, 1, 0); + filelist_file = fopen (filelist_filename, "w"); + if (filelist_file == NULL) + pfatal_with_name (filelist_filename); + num_args -= java_files_count + class_files_count; num_args++; /* Add one for the combined arg. */ - if (class_files_length > 0) - { - len += class_files_length + class_files_count - 1; - num_args -= class_files_count; - } - combined_inputs_buffer = (char*) xmalloc (len); - combined_inputs_pos = 0; } /* If we know we don't have to do anything, bail now. */ -#endif #if 0 if (! added && ! library && main_class_name == NULL && ! saw_C) { @@ -400,6 +397,11 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) num_args++; num_args++; + if (combine_inputs || indirect_files_count > 0) + num_args += 2; + if (combine_inputs && indirect_files_count > 0) + fatal("using both @FILE with multiple files not implemented"); + /* There's no point adding -shared-libgcc if we don't have a shared libgcc. */ #ifndef ENABLE_SHARED_LIBGCC @@ -409,9 +411,16 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) num_args += shared_libgcc; arglist = (const char **) xmalloc ((num_args + 1) * sizeof (char *)); + j = 0; - for (i = 0, j = 0; i < argc; i++, j++) + for (i = 0; i < argc; i++, j++) { + if (i == 1 && (combine_inputs || indirect_files_count > 0)) + { + arglist[j++] = "-ffilelist-file"; + arglist[j++] = "-xjava"; + } + arglist[j] = argv[i]; if ((args[i] & PARAM_ARG) || i == 0) @@ -449,35 +458,32 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) continue; } + if ((args[i] & INDIRECT_FILE_ARG) != 0) + { + arglist[j] = argv[i]+1; /* Drop '@'. */ + } + if ((args[i] & CLASS_FILE_ARG) && saw_C) { --j; continue; } -#if COMBINE_INPUTS if (combine_inputs && (args[i] & (CLASS_FILE_ARG|JAVA_FILE_ARG)) != 0) { - if (combined_inputs_pos > 0) - combined_inputs_buffer[combined_inputs_pos++] = '&'; - strcpy (&combined_inputs_buffer[combined_inputs_pos], argv[i]); - combined_inputs_pos += strlen (argv[i]); + fputs (argv[i], filelist_file); + fputc ('\n', filelist_file); --j; continue; } -#endif } -#if COMBINE_INPUTS if (combine_inputs) { - combined_inputs_buffer[combined_inputs_pos] = '\0'; -#if 0 - if (! saw_C) -#endif - arglist[j++] = combined_inputs_buffer; + if (fclose (filelist_file)) + pfatal_with_name (filelist_filename); + arglist[j++] = filelist_filename; } -#endif /* If we saw no -O or -g option, default to -g1, for javac compatibility. */ if (saw_g + saw_O == 0) @@ -494,10 +500,8 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries) arglist[j++] = "-fsyntax-only"; arglist[j++] = "-femit-class-files"; arglist[j++] = "-S"; -#if COMBINE_INPUTS arglist[j++] = "-o"; arglist[j++] = "NONE"; -#endif } if (shared_libgcc) diff --git a/gcc/java/lang-options.h b/gcc/java/lang-options.h index ce6289cd4d7..776b432a712 100644 --- a/gcc/java/lang-options.h +++ b/gcc/java/lang-options.h @@ -33,6 +33,7 @@ DEFINE_LANG_NAME ("Java") { "-fno-assume-compiled", "" }, { "-femit-class-file", "" }, { "-femit-class-files", "Dump class files to .class" }, + { "-ffilelist-file", "input file is list of file names to compile" }, { "-fuse-boehm-gc", "Generate code for Boehm GC" }, { "-fhash-synchronization", "Don't put synchronization structure in each object" }, { "-fjni", "Assume native functions are implemented using JNI" }, diff --git a/gcc/java/lang.c b/gcc/java/lang.c index e69151a2a3c..1680d99d2ae 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -105,6 +105,10 @@ int flag_assume_compiled = 1; int flag_emit_class_files = 0; +/* Nonzero if input file is a file with a list of filenames to compile. */ + +int flag_filelist_file = 0; + /* When non zero, we emit xref strings. Values of the flag for xref backends are defined in xref_flag_table, xref.c. */ @@ -156,6 +160,7 @@ lang_f_options[] = { {"emit-class-file", &flag_emit_class_files, 1}, {"emit-class-files", &flag_emit_class_files, 1}, + {"filelist-file", &flag_filelist_file, 1}, {"use-divide-subroutine", &flag_use_divide_subroutine, 1}, {"use-boehm-gc", &flag_use_boehm_gc, 1}, {"hash-synchronization", &flag_hash_synchronization, 1}, diff --git a/gcc/java/lex.c b/gcc/java/lex.c index 20e37d8183e..3b43fa0ac5f 100644 --- a/gcc/java/lex.c +++ b/gcc/java/lex.c @@ -120,7 +120,7 @@ java_init_lex (finput, encoding) wfl_to_string = build_expr_wfl (get_identifier ("toString"), NULL, 0, 0); CPC_INITIALIZER_LIST (ctxp) = CPC_STATIC_INITIALIZER_LIST (ctxp) = - CPC_INSTANCE_INITIALIZER_LIST (ctxp) = ctxp->incomplete_class = NULL_TREE; + CPC_INSTANCE_INITIALIZER_LIST (ctxp) = NULL_TREE; memset ((PTR) ctxp->modifier_ctx, 0, 11*sizeof (ctxp->modifier_ctx[0])); memset ((PTR) current_jcf, 0, sizeof (JCF)); diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 6cfaf650611..ad87bc64d48 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -348,7 +348,7 @@ static int in_instance_initializer; struct parser_ctxt *ctxp; /* List of things that were analyzed for which code will be generated */ -static struct parser_ctxt *ctxp_for_generation = NULL; +struct parser_ctxt *ctxp_for_generation = NULL; /* binop_lookup maps token to tree_code. It is used where binary operations are involved and required by the parser. RDIV_EXPR @@ -411,6 +411,14 @@ static tree current_this; the list of the catch clauses of the currently analysed try block. */ static tree currently_caught_type_list; +static tree src_parse_roots[2] = { NULL_TREE, NULL_TREE }; + +/* All classes seen from source code */ +#define gclass_list src_parse_roots[0] + +/* List of non-complete classes */ +#define incomplete_class_list src_parse_roots[1] + /* Check modifiers. If one doesn't fit, retrieve it in its declaration line and point it out. */ /* Should point out the one that don't fit. ASCII/unicode, going @@ -2640,11 +2648,6 @@ void java_push_parser_context () { create_new_parser_context (0); - if (ctxp->next) - { - ctxp->incomplete_class = ctxp->next->incomplete_class; - ctxp->gclass_list = ctxp->next->gclass_list; - } } void @@ -2661,8 +2664,6 @@ java_pop_parser_context (generate) next = ctxp->next; if (next) { - next->incomplete_class = ctxp->incomplete_class; - next->gclass_list = ctxp->gclass_list; lineno = ctxp->lineno; current_class = ctxp->class_type; } @@ -2776,8 +2777,6 @@ java_parser_context_resume () struct parser_ctxt *restored = saver->next; /* This one is the old current */ /* We need to inherit the list of classes to complete/generate */ - restored->incomplete_class = old->incomplete_class; - restored->gclass_list = old->gclass_list; restored->classd_list = old->classd_list; restored->class_list = old->class_list; @@ -3652,7 +3651,7 @@ maybe_create_class_interface_decl (decl, raw_name, qualified_name, cl) ctxp->class_list = decl; /* Create a new nodes in the global lists */ - ctxp->gclass_list = tree_cons (NULL_TREE, decl, ctxp->gclass_list); + gclass_list = tree_cons (NULL_TREE, decl, gclass_list); all_class_list = tree_cons (NULL_TREE, decl, all_class_list); /* Install a new dependency list element */ @@ -4991,7 +4990,7 @@ obtain_incomplete_type (type_name) else abort (); - for (ptr = ctxp->incomplete_class; ptr; ptr = TREE_CHAIN (ptr)) + for (ptr = incomplete_class_list; ptr; ptr = TREE_CHAIN (ptr)) if (TYPE_NAME (ptr) == name) break; @@ -4999,8 +4998,8 @@ obtain_incomplete_type (type_name) { BUILD_PTR_FROM_NAME (ptr, name); layout_type (ptr); - TREE_CHAIN (ptr) = ctxp->incomplete_class; - ctxp->incomplete_class = ptr; + TREE_CHAIN (ptr) = incomplete_class_list; + incomplete_class_list = ptr; } return ptr; @@ -7285,7 +7284,7 @@ java_reorder_fields () initialized_p = 1; } - for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current)) + for (current = gclass_list; current; current = TREE_CHAIN (current)) { current_class = TREE_TYPE (TREE_VALUE (current)); @@ -7315,11 +7314,11 @@ java_reorder_fields () } } } - stop_reordering = TREE_TYPE (TREE_VALUE (ctxp->gclass_list)); + stop_reordering = TREE_TYPE (TREE_VALUE (gclass_list)); } -/* Layout the methods of all classes loaded in one way on an - other. Check methods of source parsed classes. Then reorder the +/* Layout the methods of all classes loaded in one way or another. + Check methods of source parsed classes. Then reorder the fields and layout the classes or the type of all source parsed classes */ @@ -7335,12 +7334,12 @@ java_layout_classes () all_class_list = NULL_TREE; /* Then check the methods of all parsed classes */ - for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current)) + for (current = gclass_list; current; current = TREE_CHAIN (current)) if (CLASS_FROM_SOURCE_P (TREE_TYPE (TREE_VALUE (current)))) java_check_methods (TREE_VALUE (current)); java_parse_abort_on_error (); - for (current = ctxp->gclass_list; current; current = TREE_CHAIN (current)) + for (current = gclass_list; current; current = TREE_CHAIN (current)) { current_class = TREE_TYPE (TREE_VALUE (current)); layout_class (current_class); @@ -15688,8 +15687,6 @@ mark_parser_ctxt (p) ggc_mark_tree (pc->class_type); ggc_mark_tree (pc->function_decl); ggc_mark_tree (pc->package); - ggc_mark_tree (pc->incomplete_class); - ggc_mark_tree (pc->gclass_list); ggc_mark_tree (pc->class_list); ggc_mark_tree (pc->current_parsed_class); ggc_mark_tree (pc->current_parsed_class_un); @@ -15705,3 +15702,10 @@ mark_parser_ctxt (p) if (pc->next) mark_parser_ctxt (&pc->next); } + +void +init_src_parse () +{ + /* Register roots with the garbage collector. */ + ggc_add_tree_root (src_parse_roots, sizeof (src_parse_roots) / sizeof(tree)); +} -- 2.30.2