+2001-02-16 Per Bothner <per@bothner.com>
+
+ 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 <kenner@vlsi1.ultra.nyu.edu>
* decl.c (set_block): Set NAMES and BLOCKS from BLOCK.
extern int flag_emit_class_files;
+extern int flag_filelist_file;
+
/* When non zero, assume all native functions are implemented with
JNI, not CNI. */
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));
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));
{
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);
}
/* 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;
{
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 */
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])
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
}
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))
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 ();
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 ();
}
#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 *));
/* 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 \
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;
/* 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
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;
/* Saw `-lgcj' on command line. */
int saw_libgcj ATTRIBUTE_UNUSED = 0;
+#endif
/* Saw -C or -o option, respectively. */
int saw_C = 0;
{
saw_C = 1;
want_spec_file = 0;
-#if COMBINE_INPUTS
- combine_inputs = 1;
-#endif
if (library != 0)
added -= 2;
library = 0;
}
else
{
-#if COMBINE_INPUTS
int len;
-#endif
if (saw_speclang)
{
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)
{
class_files_length += len;
last_input_index = i;
}
-#endif
}
}
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)
{
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
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)
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)
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)
{ "-fno-assume-compiled", "" },
{ "-femit-class-file", "" },
{ "-femit-class-files", "Dump class files to <name>.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" },
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. */
{
{"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},
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));
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
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
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
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;
}
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;
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 */
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;
{
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;
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));
}
}
}
- 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 */
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);
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);
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));
+}