aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2004-01-22 04:10:28 +0000
committerMike Stump <mrs@apple.com>2004-01-22 04:10:28 +0000
commit73f48101760ffe123b541c926bb05b5473cc3e05 (patch)
tree8dcaaaf47d9f534542c0a7f7f97b78fe049c66db
parent6d99c61ba100d4291b192fed6d4d5d29d77ab0a1 (diff)
Move options processing from server command line to client command
line, default server starting to on. * c-pch.c (c_common_read_pch): Allow options to initialized more than once. (c_common_no_more_pch): Don't unmap more than once, as other compilation units can reuse the PCH state as is. * c-opts.c (max_deferred): Add. (defer_opt): Add bounds check. (c_common_init_options): Allow options to initialized more than once. (c_common_post_options): Likewise. (reinit_copts): Likewise. (init_c_common_once): Likewise. (c_common_parse_file): Likewise. (c_common_parse_file): Moved pch-init to here. (finish_options): Allow options to initialized more than once. * c-objc-common.c (init_c_objc_common_once): Allow options to initialized more than once. * c-incpath.h (reinit_incpath): Add. * c-incpath.c (reinit_incpath): Add. * c-decl.c (init_c_decl_processing_eachsrc): Don't reset_cpp_hashnodes. (init_c_decl_processing_once): Allow options to initialized more than once. * c-common.h (synthetic_exit_fragment): Add. * c-common.c (create_builtins_fragment): Allow options to initialized more than once. (gather_fragment_statistics): Always output fragment stats, for now. (reset_cpp_hashnodes): Allow options to initialized more than once. (synthetic_exit_fragment): Add. (create_output_fragment): Only create output fragments when in sever mode 2. (end_output_fragment): Likewise. (create_output_fragment): Set the name of the fragment. (create_cmdline_fragment): Add. (end_cmdline_fragment): Add. (init_cmdline_fragment): Add. (activate_cmdline_fragment): Add. * toplev.c (wrapup_global_declarations): Call DECL_NEWEST_DUPLICATE on decl. (wrapup_global_declarations): Don't infinitely loop if the decl has been written out already. (lang_dependent_init): Move pch_init from here. (init_compile_once): Allow options to initialized more than once. (server_loop): Free asm_file_name and input filenames. (server_loop): Allow options to initialized more than once. (toplev_main): Allow options to initialized more than once. * opts.c (reinit_opts): Add. (decode_options): Allow options to initialized more than once. * objc/lang-specs.h: Simplify and allow -server to be the default. * Makefile.in (TEST_TARGET): Remove coverage.o, as it cannot be processed twice. (start-server): Remove unneeded arguments. * gcc.c: Default server to on. (write_input_request): Remove. (write_input_requests): Remove. (cpp_unique_options): Simplify and allow -server to be the default. (cc1_options): Likewise. (default_compilers): Likewise. (execute): Add code to allow -server to be the default. (start_server): Add. (waitforgo): Add. (get_server_socket): Add compile server starting. (write_switch_fds_request): Use waitforgo. (process_command): Don't -pipe, as it defeats snarf-n-barf of asm for fragments. (pexecute_server): Remove call to write_input_requests as we now handle them normally. * cpplib.h (cpp_notice_updates): Add. * cppinit.c (cpp_push_main_file): We start a new fragment for C++ for the main file. * cppfiles.c (struct _cpp_file_data): Add generation. (generation): Add. (file_modified): Add. (cpp_notice_updates): Add. (open_file): Notice when a file has been modified. (_cpp_find_file): Don't reuse a PCH file that has been read once. (_cpp_find_file): If we re-validate the PCH file, reuse the fd. (read_file_guts): Track the generation number of file that are read. (file_changed): Add. (read_file): Notice when a file has been modified. (_cpp_stack_file): Remove fragment starting code, as it is now redundant with normal fragment processing. (purge_fragments): Use delete_fragment. (_cpp_pop_file_buffer): Add code to allow C++ to reuse the main file. * config/darwin-c.c (reinit_frameworks): Add. (darwin_register_frameworks_real): Use reinit_frameworks to reinitialize framework processing. * c-common.c (reset_hashnode): Also clear NODE_DIAGNOSTIC. cp: * lex.c (lang_clear_identifier): Don't clear symbol table as we use a conditional symbol table. * lang-specs.h: Simplify and allow -server to be the default. * decl.c (init_cxx_decl_processing_once): Allow options to initialized more than once. (init_cxx_decl_processing_eachsrc): Likewise. * lex.c (init_cxx_once): Likewise. (init_cxx_eachsrc): Likewise. (extract_interface_info): Likewise. * cp-lang.c (LANG_HOOKS_FINISH_SERVER): Add. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/compile-server-branch@76336 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog124
-rw-r--r--gcc/Makefile.in18
-rw-r--r--gcc/c-common.c129
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/c-decl.c45
-rw-r--r--gcc/c-incpath.c10
-rw-r--r--gcc/c-incpath.h1
-rw-r--r--gcc/c-objc-common.c14
-rw-r--r--gcc/c-opts.c88
-rw-r--r--gcc/c-pch.c30
-rw-r--r--gcc/config/darwin-c.c14
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/cp-lang.c2
-rw-r--r--gcc/cp/decl.c54
-rw-r--r--gcc/cp/lang-specs.h4
-rw-r--r--gcc/cp/lex.c68
-rw-r--r--gcc/cppfiles.c117
-rw-r--r--gcc/cppinit.c9
-rw-r--r--gcc/cpplib.h1
-rw-r--r--gcc/gcc.c148
-rw-r--r--gcc/objc/lang-specs.h2
-rw-r--r--gcc/opts.c63
-rw-r--r--gcc/toplev.c83
23 files changed, 838 insertions, 203 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c0528d1400e..34d1b8459a2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,118 @@
+2004-01-21 Mike Stump <mrs@apple.com>
+
+ Move options processing from server command line to client command
+ line, default server starting to on.
+
+ * c-pch.c (c_common_read_pch): Allow options to initialized more
+ than once.
+ (c_common_no_more_pch): Don't unmap more than once, as other
+ compilation units can reuse the PCH state as is.
+
+ * c-opts.c (max_deferred): Add.
+ (defer_opt): Add bounds check.
+ (c_common_init_options): Allow options to initialized more than
+ once.
+ (c_common_post_options): Likewise.
+ (reinit_copts): Likewise.
+ (init_c_common_once): Likewise.
+ (c_common_parse_file): Likewise.
+ (c_common_parse_file): Moved pch-init to here.
+ (finish_options): Allow options to initialized more than once.
+
+ * c-objc-common.c (init_c_objc_common_once): Allow options to
+ initialized more than once.
+
+ * c-incpath.h (reinit_incpath): Add.
+
+ * c-incpath.c (reinit_incpath): Add.
+
+ * c-decl.c (init_c_decl_processing_eachsrc): Don't
+ reset_cpp_hashnodes.
+ (init_c_decl_processing_once): Allow options to initialized more
+ than once.
+
+ * c-common.h (synthetic_exit_fragment): Add.
+
+ * c-common.c (create_builtins_fragment): Allow options to
+ initialized more than once.
+ (gather_fragment_statistics): Always output fragment stats, for now.
+ (reset_cpp_hashnodes): Allow options to initialized more than
+ once.
+ (synthetic_exit_fragment): Add.
+ (create_output_fragment): Only create output fragments when in
+ sever mode 2.
+ (end_output_fragment): Likewise.
+ (create_output_fragment): Set the name of the fragment.
+ (create_cmdline_fragment): Add.
+ (end_cmdline_fragment): Add.
+ (init_cmdline_fragment): Add.
+ (activate_cmdline_fragment): Add.
+
+ * toplev.c (wrapup_global_declarations): Call
+ DECL_NEWEST_DUPLICATE on decl.
+ (wrapup_global_declarations): Don't infinitely loop if the decl
+ has been written out already.
+ (lang_dependent_init): Move pch_init from here.
+ (init_compile_once): Allow options to initialized more than once.
+ (server_loop): Free asm_file_name and input filenames.
+ (server_loop): Allow options to initialized more than once.
+ (toplev_main): Allow options to initialized more than once.
+
+ * opts.c (reinit_opts): Add.
+ (decode_options): Allow options to initialized more than once.
+
+ * objc/lang-specs.h: Simplify and allow -server to be the default.
+
+ * Makefile.in (TEST_TARGET): Remove coverage.o, as it cannot be
+ processed twice.
+ (start-server): Remove unneeded arguments.
+
+ * gcc.c: Default server to on.
+ (write_input_request): Remove.
+ (write_input_requests): Remove.
+ (cpp_unique_options): Simplify and allow -server to be the default.
+ (cc1_options): Likewise.
+ (default_compilers): Likewise.
+ (execute): Add code to allow -server to be the default.
+ (start_server): Add.
+ (waitforgo): Add.
+ (get_server_socket): Add compile server starting.
+ (write_switch_fds_request): Use waitforgo.
+
+ (process_command): Don't -pipe, as it defeats snarf-n-barf of asm
+ for fragments.
+
+ (pexecute_server): Remove call to write_input_requests as we now
+ handle them normally.
+
+ * cpplib.h (cpp_notice_updates): Add.
+
+ * cppinit.c (cpp_push_main_file): We start a new fragment for C++
+ for the main file.
+
+ * cppfiles.c (struct _cpp_file_data): Add generation.
+ (generation): Add.
+ (file_modified): Add.
+ (cpp_notice_updates): Add.
+ (open_file): Notice when a file has been modified.
+ (_cpp_find_file): Don't reuse a PCH file that has been read once.
+ (_cpp_find_file): If we re-validate the PCH file, reuse the fd.
+ (read_file_guts): Track the generation number of file that are
+ read.
+ (file_changed): Add.
+ (read_file): Notice when a file has been modified.
+ (_cpp_stack_file): Remove fragment starting code, as it is now
+ redundant with normal fragment processing.
+ (purge_fragments): Use delete_fragment.
+ (_cpp_pop_file_buffer): Add code to allow C++ to reuse the main
+ file.
+
+ * config/darwin-c.c (reinit_frameworks): Add.
+ (darwin_register_frameworks_real): Use reinit_frameworks to
+ reinitialize framework processing.
+
+ * c-common.c (reset_hashnode): Also clear NODE_DIAGNOSTIC.
+
2003-12-17 Per Bothner <pbothner@apple.com>
* c-decl.c (lang_clear_identifier): Clear the DECL_RTL of the id's
@@ -152,15 +267,6 @@
* c-objc-common.c (init_c_objc_common_eachsrc): Clear it.
* c-parse.in (program): Use it in checking for empty source file.
-2003-11-10 Mike Stump <mrs@apple.com>
-
- * c-pch.c (c_common_no_more_pch): Don't unmap more than once, as
- other compilation units can reuse the PCH state as is.
-
-2003-10-30 Mike Stump <mrs@apple.com>
-
- * c-common.c (reset_hashnode): Also clear NODE_DIAGNOSTIC.
-
2003-12-02 Mike Stump <mrs@apple.com>
* config/darwin-c.c: struct cpp_dir -> cpp_dir.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index ddb57501722..028ad9f51db 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3896,7 +3896,7 @@ TEST_TARGET = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \
alias.o bb-reorder.o builtins.o caller-save.o calls.o \
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \
- cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \
+ cfgrtl.o combine.o conflict.o convert.o cse.o cselib.o \
dbxout.o debug.o df.o diagnostic.o dojump.o doloop.o dominance.o \
dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o \
expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \
@@ -3912,14 +3912,24 @@ TEST_TARGET = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \
stor-layout.o stringpool.o timevar.o tracer.o tree.o tree-dump.o \
unroll.o varasm.o varray.o version.o xcoffout.o \
alloc-pool.o et-forest.o cfghooks.o bt-load.o pretty-print.o
-#bitmap.o insn-attrtab.o insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o rtl.o intl.o
-#vmsdbgout.o dwarfout.o
+# This one needs tighter lex syncing with fragment reuse
+# coverage.o
+# bitmap.o insn-attrtab.o insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o rtl.o intl.o
+# vmsdbgout.o dwarfout.o
+
+.PHONY: save-objs
+save-objs:
+ mkdir -p save-objs
+ mv $(TEST_TARGET) save-objs
+
+unsave-objs: test-clean
+ mv save-objs/* .
test-clean: source.list
rm -f $(TEST_TARGET) ./cc1-server
start-server:
- stage2/cc1 -fserver $(BOOT_CFLAGS) -Werror $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -isystem include -isystem stage2/include -quiet
+ stage2/cc1 -fserver
source.list: Makefile
rm -f source.list
diff --git a/gcc/c-common.c b/gcc/c-common.c
index e6ff6d4853c..f087b0c466f 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4308,23 +4308,18 @@ extern void register_fragment_dependency PARAMS ((struct c_include_fragment*));
void
create_builtins_fragment (void)
{
- struct c_include_fragment* st;
- cpp_fragment *fragment;
- fragment = xcalloc (1, sizeof (cpp_fragment));
- fragment->name = "<built-in>";
- parse_in->current_fragment = fragment;
- st = alloc_include_fragment ();
- C_FRAGMENT (fragment) = st;
- st->valid = 1;
- st->name = fragment->name;
- current_c_fragment = st;
- if (builtins_fragment)
+ if (builtins_fragment == 0)
{
- delete_fragment (builtins_fragment);
- builtins_fragment = 0;
+ builtins_fragment = xcalloc (1, sizeof (cpp_fragment));
+ builtins_fragment->name = "<built-in>";
+ builtins_c_fragment = alloc_include_fragment ();
+ C_FRAGMENT (builtins_fragment) = builtins_c_fragment;
+ builtins_c_fragment->valid = 1;
+ builtins_c_fragment->name = builtins_fragment->name;
}
- builtins_fragment = fragment;
- builtins_c_fragment = st;
+ parse_in->current_fragment = builtins_fragment;
+ current_c_fragment = builtins_c_fragment;
+
parse_in->do_note_macros = 1;
track_declarations = 1;
}
@@ -4415,7 +4410,7 @@ process_undo_buffer (void)
current fragment. At the end of the fragment, the data gets
copied into the fragment. (It would be cleaner to store this information
in the fragment directly, but that is less efficient because we don't
- know the buffer size needed until teh end of the fragment.) */
+ know the buffer size needed until the end of the fragment.) */
static GTY(()) tree fragment_bindings_stack;
/* The active size of fragment_bindings_stack. */
@@ -4518,7 +4513,7 @@ register_fragment_dependency (struct c_include_fragment* used)
}
#define warn_fragment_invalidation (! quiet_flag)
-#define gather_fragment_statistics (! quiet_flag)
+#define gather_fragment_statistics (! quiet_flag || 1)
int track_dependencies;
int track_declarations;
@@ -4531,7 +4526,7 @@ int currently_nested;
void
reset_hashnode (cpp_hashnode *node)
{
- node->flags &= ~ NODE_POISONED; /* ??? also clear NODE_DIAGNOSTIC? */
+ node->flags &= ~ (NODE_POISONED | NODE_DIAGNOSTIC);
if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
{
cpp_macro *macro = node->value.macro;
@@ -4551,10 +4546,13 @@ reset_cpp_hashnodes (void)
/* Reset cpplib's macros and start a new file. */
cpp_undef_all (parse_in);
#endif
- cpp_forall_identifiers (parse_in, lang_clear_identifier, NULL);
- cpp_restore_macros (parse_in, builtins_fragment);
- restore_fragment_bindings (builtins_c_fragment->bindings);
- /* parse_in->buffer = NULL;*/
+ if (builtins_fragment || lang_hooks.uses_conditional_symtab)
+ {
+ cpp_forall_identifiers (parse_in, lang_clear_identifier, NULL);
+ cpp_restore_macros (parse_in, builtins_fragment);
+ restore_fragment_bindings (builtins_c_fragment->bindings);
+ /* parse_in->buffer = NULL;*/
+ }
}
void
@@ -4820,12 +4818,37 @@ xfseek (FILE *fp, long offset, int whence) {
return r;
}
+/* Like a normal fragment end, except we do less processing. */
+
+void
+synthetic_exit_fragment (cpp_reader *reader, cpp_fragment *fragment ATTRIBUTE_UNUSED)
+{
+ /* This is a synthetic exit, as we don't really want to change anything about
+ the fragment. */
+ reader->do_note_macros = 0;
+ track_declarations = 0;
+ track_dependencies = 0;
+ if (reader->macro_notes_count)
+ {
+ warning ("defined macros in builtins not protected by cmdline fragment");
+ free (reader->macro_notes);
+ reader->macro_notes_count = 0;
+ }
+ current_c_fragment = NULL;
+ if (fragment_bindings_end)
+ {
+ warning ("declarations in builtins not protected by cmdline fragment");
+ save_fragment_bindings ();
+ }
+ current_fragment_deps_end = 0;
+}
+
/* Called by cpplib at the end of a fragment (though not if cb_enter_fragment
returned true). Save remembered bindings with the fragment for
future re-use. */
void
-cb_exit_fragment (cpp_reader *reader ATTRIBUTE_UNUSED,
+cb_exit_fragment (cpp_reader *reader,
cpp_fragment *fragment)
{
struct c_include_fragment* st = C_FRAGMENT (fragment);
@@ -4982,13 +5005,15 @@ create_output_fragment (void)
cpp_fragment *fragment;
if (!lang_hooks.uses_conditional_symtab)
return;
- /* FIXME check server_mode! */
+ if (server_mode != 2)
+ return;
fragment = xcalloc (1, sizeof (cpp_fragment));
fragment->name = "<built-in>";
parse_in->current_fragment = fragment;
st = alloc_include_fragment ();
C_FRAGMENT (fragment) = st;
st->valid = 1;
+ st->name = fragment->name;
st->include_timestamp = main_timestamp;
current_c_fragment = st;
output_fragment = fragment;
@@ -5003,6 +5028,8 @@ end_output_fragment (void)
{
if (!lang_hooks.uses_conditional_symtab)
return;
+ if (server_mode != 2)
+ return;
/* Fold these into cb_exit_fragment as well?! */
if (C_FRAGMENT (output_fragment) != current_c_fragment)
abort ();
@@ -5031,6 +5058,60 @@ activate_output_fragment (void)
output_c_fragment->include_timestamp = main_timestamp;
}
+static GTY(()) struct c_include_fragment *cmdline_c_fragment = 0;
+
+/* Create a fragment used for the cmdline declarations. */
+
+void
+create_cmdline_fragment (void)
+{
+ struct c_include_fragment* st;
+ cpp_fragment *fragment;
+ if (server_mode != 2)
+ return;
+ fragment = xcalloc (1, sizeof (cpp_fragment));
+ fragment->name = "<built-in>";
+ parse_in->current_fragment = fragment;
+ st = alloc_include_fragment ();
+ C_FRAGMENT (fragment) = st;
+ st->valid = 1;
+ st->name = fragment->name;
+ st->include_timestamp = main_timestamp;
+ current_c_fragment = st;
+ cmdline_c_fragment = st;
+ parse_in->do_note_macros = 1;
+ track_declarations = 1;
+}
+
+/* End the output fragment. */
+
+void
+end_cmdline_fragment (void)
+{
+ if (server_mode != 2)
+ return;
+ /* Fold these into cb_exit_fragment as well?! */
+ if (C_FRAGMENT (parse_in->current_fragment) != current_c_fragment)
+ abort ();
+ cb_exit_fragment (parse_in, parse_in->current_fragment);
+ parse_in->current_fragment = NULL;
+}
+
+void init_cmdline_fragment ()
+{
+ cmdline_c_fragment = 0;
+}
+
+/* Update the cmdline fragment timestamp so that it is valid for this
+ translation unit. */
+
+void
+activate_cmdline_fragment (void)
+{
+ if (cmdline_c_fragment != NULL)
+ cmdline_c_fragment->include_timestamp = main_timestamp;
+}
+
/* Handle extra debugging of C tree nodes. */
void
diff --git a/gcc/c-common.h b/gcc/c-common.h
index e95adab4fba..bd7bfb040f1 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -231,6 +231,7 @@ extern void process_undo_buffer (void);
extern tree save_fragment_bindings (void);
extern bool cb_enter_fragment (cpp_reader*, cpp_fragment*);
extern void cb_exit_fragment (cpp_reader*, cpp_fragment*);
+extern void synthetic_exit_fragment (cpp_reader *reader, cpp_fragment *fragment);
extern void cb_uses_fragment (cpp_reader*, cpp_fragment*);
extern bool cb_avoid_new_fragment (cpp_reader*);
extern void init_output_fragment (void);
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 577a59b1b7f..ac23fb25ec1 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -552,7 +552,12 @@ init_c_decl_processing_eachsrc (void)
{
global_scope->tags = NULL_TREE;
global_scope->names = NULL_TREE;
+#if 0
+ /* This is wrong, we've installed cmd line -D stuff and we
+ can't undo them, as they aren't builtin and those are the
+ only ones that survive. */
reset_cpp_hashnodes ();
+#endif
}
}
@@ -2436,9 +2441,13 @@ init_c_decl_processing_once (void)
tree endlink;
tree ptr_ftype_void, ptr_ftype_ptr;
location_t save_loc = input_location;
+ static int first = 1;
- /* Adds some ggc roots, and reserved words for c-parse.in. */
- c_parse_init ();
+ if (first)
+ {
+ /* Adds some ggc roots, and reserved words for c-parse.in. */
+ c_parse_init ();
+ }
scope_freelist = NULL;
@@ -2451,24 +2460,28 @@ init_c_decl_processing_once (void)
input_location.file = "<internal>";
input_location.line = 0;
- build_common_tree_nodes (flag_signed_char);
+ if (first)
+ {
+ build_common_tree_nodes (flag_signed_char);
- c_common_nodes_and_builtins ();
+ c_common_nodes_and_builtins ();
- /* In C, comparisons and TRUTH_* expressions have type int. */
- truthvalue_type_node = integer_type_node;
- truthvalue_true_node = integer_one_node;
- truthvalue_false_node = integer_zero_node;
+ /* In C, comparisons and TRUTH_* expressions have type int. */
+ truthvalue_type_node = integer_type_node;
+ truthvalue_true_node = integer_one_node;
+ truthvalue_false_node = integer_zero_node;
- /* Even in C99, which has a real boolean type. */
- pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
- boolean_type_node));
+ /* Even in C99, which has a real boolean type. */
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
+ boolean_type_node));
- endlink = void_list_node;
- ptr_ftype_void = build_function_type (ptr_type_node, endlink);
- ptr_ftype_ptr
- = build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node, endlink));
+ endlink = void_list_node;
+ ptr_ftype_void = build_function_type (ptr_type_node, endlink);
+ ptr_ftype_ptr
+ = build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node, endlink));
+ first = 0;
+ }
input_location = save_loc;
diff --git a/gcc/c-incpath.c b/gcc/c-incpath.c
index fe212fc03b0..77d7b913431 100644
--- a/gcc/c-incpath.c
+++ b/gcc/c-incpath.c
@@ -59,6 +59,16 @@ static struct cpp_dir *tails[4];
static bool quote_ignores_source_dir;
enum { REASON_QUIET = 0, REASON_NOENT, REASON_DUP, REASON_DUP_SYS };
+/* Reinitialize for next compile. */
+
+void
+reinit_incpath ()
+{
+ memset (heads, 0, sizeof (heads));
+ memset (tails, 0, sizeof (tails));
+ quote_ignores_source_dir = false;
+}
+
/* Free an element of the include chain, possibly giving a reason. */
static void
free_path (struct cpp_dir *path, int reason)
diff --git a/gcc/c-incpath.h b/gcc/c-incpath.h
index ab4b992703f..dc2cfeb8d4e 100644
--- a/gcc/c-incpath.h
+++ b/gcc/c-incpath.h
@@ -22,5 +22,6 @@ extern void register_include_chains (cpp_reader *, const char *,
const char *, int, int, int);
extern void add_system_path (struct cpp_dir *);
extern void add_bracket_path (struct cpp_dir *);
+extern void reinit_incpath (void);
enum { QUOTE = 0, BRACKET, SYSTEM, AFTER };
diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c
index c49b8abba55..188f95c0a48 100644
--- a/gcc/c-objc-common.c
+++ b/gcc/c-objc-common.c
@@ -163,7 +163,9 @@ init_c_objc_common_once (void)
INIT_STATEMENT_CODES (stmt_codes);
- if ((server_mode >= 0 && server_mode != 1)
+ reset_cpp_hashnodes ();
+
+ if (server_mode >= 2
/* In this case we must write #define and #undef debug information
into the assembler file. But that hasn't been opened yet. When
using the compile server, we have to write out the debug information
@@ -177,7 +179,15 @@ init_c_objc_common_once (void)
init_c_common_once ();
if (parse_in->do_note_macros)
{
- cb_exit_fragment (parse_in, builtins_fragment);
+ static int first = 1;
+ if (first)
+ {
+ cb_exit_fragment (parse_in, builtins_fragment);
+ first = 0;
+ }
+ else
+ synthetic_exit_fragment (parse_in, builtins_fragment);
+
/* This should be folded into cb_exit_fragment?! */
parse_in->current_fragment = NULL;
}
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index 12f602da49d..989a532eb12 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -108,6 +108,7 @@ static void add_prefixed_path (const char *, size_t);
static void push_command_line_include (void);
static void cb_file_change (cpp_reader *, const struct line_map *);
static bool finish_options (void);
+static void reinit_copts (void);
#ifndef STDC_0_IN_SYSTEM_HEADERS
#define STDC_0_IN_SYSTEM_HEADERS 0
@@ -121,6 +122,7 @@ static struct deferred_opt
enum opt_code code;
const char *arg;
} *deferred_opts;
+static size_t max_deferred = 0;
/* Complain that switch CODE expects an argument but none was
provided. OPT was the command-line option. Return FALSE to get
@@ -178,6 +180,8 @@ c_common_missing_argument (const char *opt, size_t code)
static void
defer_opt (enum opt_code code, const char *arg)
{
+ if (deferred_count >= max_deferred)
+ abort ();
deferred_opts[deferred_count].code = code;
deferred_opts[deferred_count].arg = arg;
deferred_count++;
@@ -189,6 +193,9 @@ c_common_init_options (unsigned int argc, const char **argv ATTRIBUTE_UNUSED)
{
static const unsigned int lang_flags[] = {CL_C, CL_ObjC, CL_CXX, CL_ObjCXX};
unsigned int result;
+ static int first = 1;
+
+ reinit_copts ();
#ifdef TARGET_C_INIT
TARGET_C_INIT;
@@ -206,12 +213,16 @@ c_common_init_options (unsigned int argc, const char **argv ATTRIBUTE_UNUSED)
diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
}
- parse_in = cpp_create_reader (c_dialect_cxx () ? CLK_GNUCXX: CLK_GNUC89,
- ident_hash);
+ if (first)
+ {
+ parse_in = cpp_create_reader (c_dialect_cxx () ? CLK_GNUCXX: CLK_GNUC89,
+ ident_hash);
- cpp_opts = cpp_get_options (parse_in);
- cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
- cpp_opts->objc = c_dialect_objc ();
+ cpp_opts = cpp_get_options (parse_in);
+ cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
+ cpp_opts->objc = c_dialect_objc ();
+ first = 0;
+ }
/* Reset to avoid warnings on internal definitions. We set it just
before passing on command-line options to cpplib. */
@@ -222,6 +233,7 @@ c_common_init_options (unsigned int argc, const char **argv ATTRIBUTE_UNUSED)
warn_pointer_arith = c_dialect_cxx ();
deferred_opts = xmalloc (argc * sizeof (struct deferred_opt));
+ max_deferred = argc;
result = lang_flags[c_language];
@@ -1112,12 +1124,10 @@ c_common_post_options (const char **pfilename ATTRIBUTE_UNUSED)
/* kludge - should be moved */
cpp_post_options (parse_in);
- cpp_find_main_file (parse_in, *pfilename);
+ finish_options ();
if (flag_preprocess_only)
{
- finish_options ();
-
preprocess_file (parse_in);
return true;
}
@@ -1132,10 +1142,30 @@ c_common_post_options (const char **pfilename ATTRIBUTE_UNUSED)
return false;
}
+/* Reinitialize for next compile. */
+
+static void
+reinit_copts ()
+{
+ verbose = false;
+
+ if (deferred_opts)
+ {
+ free (deferred_opts);
+ deferred_opts = 0;
+ deferred_count = 0;
+ include_cursor = 0;
+ max_deferred = 0;
+ }
+
+ reinit_incpath ();
+}
+
/* Front end initialization common to C, ObjC and C++. */
void
init_c_common_once (void)
{
+ static int first = 1;
/* Set up preprocessor arithmetic. Must be done after call to
c_common_nodes_and_builtins for type nodes to be good. */
cpp_opts->precision = TYPE_PRECISION (intmax_type_node);
@@ -1161,7 +1191,11 @@ init_c_common_once (void)
cpp_get_callbacks (parse_in)->avoid_new_fragment = cb_avoid_new_fragment;
}
- init_pragma ();
+ if (first)
+ {
+ init_pragma ();
+ first = 0;
+ }
if (cpp_opts->deps.style == DEPS_NONE)
check_deps_environment_vars ();
@@ -1208,11 +1242,21 @@ init_c_common_once (void)
if (warn_missing_format_attribute && !warn_format)
warning ("-Wmissing-format-attribute ignored without -Wformat");
+#if 0
+ /* This has to be done before the builtins are injected. */
+ reset_cpp_hashnodes ();
+#endif
+
if (!cpp_opts->preprocessed)
{
+ static int first = 1;
cpp_change_file (parse_in, LC_ENTER, _("<built-in>"));
- cpp_init_builtins (parse_in, flag_hosted);
- c_cpp_builtins (parse_in);
+ if (first)
+ {
+ cpp_init_builtins (parse_in, flag_hosted);
+ c_cpp_builtins (parse_in);
+ first = 0;
+ }
/* We're about to send user input to cpplib, so make it warn for
things that we previously (when we sent it internal definitions)
@@ -1241,7 +1285,10 @@ init_c_common_once (void)
bool
init_c_common_eachsrc (void)
{
+#if 0
+ /* This is new location of finish_options in Per's code. */
finish_options ();
+#endif
input_line = saved_lineno;
@@ -1259,8 +1306,20 @@ c_common_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
warning ("YYDEBUG not defined");
#endif
+ /* Per moved this one to init_c_common_eachsrc */
+#if 0
+ finish_options (input_filename);
+#endif
+
+#if 0
+ /* Not necessary, at end of finish_options */
+ push_command_line_include ();
+#endif
+
(*debug_hooks->start_source_file) (input_line, input_filename);
+ if (1 /* first file */)
+ pch_init ();
c_parse_file ();
free_parser_stacks ();
@@ -1431,6 +1490,7 @@ add_prefixed_path (const char *suffix, size_t chain)
static bool
finish_options (void)
{
+ const char *tif = input_filename;
#if 0
/* MERGE ? They moved this in here, can we move it back? */
this_input_filename = tif;
@@ -1476,6 +1536,10 @@ finish_options (void)
}
include_cursor = 0;
+#if 1
+ /* Was here, Per moved it. */
+ cpp_find_main_file (parse_in, tif);
+#endif
push_command_line_include ();
return true;
}
@@ -1515,8 +1579,10 @@ cb_file_change (cpp_reader *pfile ATTRIBUTE_UNUSED,
else
fe_file_change (new_map);
+#if 0
if (new_map == 0 || (new_map->reason == LC_LEAVE && MAIN_FILE_P (new_map)))
push_command_line_include ();
+#endif
}
/* Set the C 89 standard (with 1994 amendments if C94, without GNU
diff --git a/gcc/c-pch.c b/gcc/c-pch.c
index a30310226ff..a12af796f3f 100644
--- a/gcc/c-pch.c
+++ b/gcc/c-pch.c
@@ -380,8 +380,27 @@ c_common_read_pch (cpp_reader *pfile, const char *name,
cpp_prepare_state (pfile, &smd);
- gt_pch_restore (f);
-
+ {
+ static int first = 1;
+ static long pos;
+
+ if (first)
+ gt_pch_restore (f);
+ if (server_mode == 2)
+ {
+ if (first)
+ {
+ if (lang_hooks.uses_conditional_symtab)
+ first = 0;
+ pos = ftell (f);
+ if (pos == -1)
+ abort ();
+ }
+ else
+ if (fseek (f, pos, SEEK_SET) != 0)
+ abort ();
+ }
+ }
if (cpp_read_state (pfile, name, f, smd) != 0)
return;
@@ -395,7 +414,12 @@ c_common_no_more_pch (void)
{
if (cpp_get_callbacks (parse_in)->valid_pch)
{
+ static int first = 1;
cpp_get_callbacks (parse_in)->valid_pch = NULL;
- host_hooks.gt_pch_use_address (NULL, 0);
+ if (first)
+ {
+ host_hooks.gt_pch_use_address (NULL, 0);
+ first = 0;
+ }
}
}
diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c
index d82d6094c78..c24c63d0842 100644
--- a/gcc/config/darwin-c.c
+++ b/gcc/config/darwin-c.c
@@ -47,6 +47,7 @@ static void add_system_framework_path (char *);
static const char *find_subframework_header (cpp_reader *pfile, const char *header);
static void darwin_register_frameworks_real (int);
static void add_framework_path_real (char *path);
+static void reinit_frameworks (void);
typedef struct align_stack
{
@@ -405,9 +406,22 @@ static const char *framework_defaults [] =
};
+static void reinit_frameworks ()
+{
+ if (num_frameworks)
+ {
+ num_frameworks = 0;
+ max_frameworks = 0;
+ free (frameworks_in_use);
+ frameworks_in_use = 0;
+ }
+}
+
static void
darwin_register_frameworks_real (int stdinc)
{
+ reinit_frameworks ();
+
if (stdinc)
{
size_t i;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5969dc5c0e7..a6619be89b2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,19 @@
+2004-01-21 Mike Stump <mrs@apple.com>
+
+ * lex.c (lang_clear_identifier): Don't clear symbol table as we
+ use a conditional symbol table.
+
+ * lang-specs.h: Simplify and allow -server to be the default.
+
+ * decl.c (init_cxx_decl_processing_once): Allow options to
+ initialized more than once.
+ (init_cxx_decl_processing_eachsrc): Likewise.
+ * lex.c (init_cxx_once): Likewise.
+ (init_cxx_eachsrc): Likewise.
+ (extract_interface_info): Likewise.
+
+ * cp-lang.c (LANG_HOOKS_FINISH_SERVER): Add.
+
2003-12-15 Per Bothner <pbothner@apple.com>
* decl.c (setup_globals): ANSI-fy function header.
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index a062b0ed1d7..1455ac59143 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -52,6 +52,8 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_INIT init_cxx_eachsrc
#undef LANG_HOOKS_FINISH
#define LANG_HOOKS_FINISH cxx_finish
+#undef LANG_HOOKS_FINISH_SERVER
+#define LANG_HOOKS_FINISH_SERVER report_fragment_statistics
#undef LANG_HOOKS_INIT_PCH
#define LANG_HOOKS_INIT_PCH pch_init
#undef LANG_HOOKS_CLEAR_BINDING_STACK
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 292995353fa..d62eec78337 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2900,23 +2900,13 @@ init_cxx_decl_processing_once (void)
{
tree void_ftype;
tree void_ftype_ptr;
+ static int first = 1;
- /* Create all the identifiers we need. */
- initialize_predefined_identifiers ();
-
- /* Fill in back-end hooks. */
- lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
-
- /* Create the global variables. */
- push_to_top_level ();
-
- current_function_decl = NULL_TREE;
- current_binding_level = NULL;
- /* Enter the global namespace. */
- my_friendly_assert (global_namespace == NULL_TREE, 375);
- global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
- void_type_node);
- current_lang_name = NULL_TREE;
+ if (first)
+ {
+ /* Create all the identifiers we need. */
+ initialize_predefined_identifiers ();
+ }
/* Adjust various flags based on command-line settings. */
if (!flag_permissive)
@@ -2932,6 +2922,26 @@ init_cxx_decl_processing_once (void)
flag_inline_functions = 0;
}
+ if (! first)
+ {
+ return;
+ }
+
+ /* Fill in back-end hooks. */
+ lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
+
+ /* Create the global variables. */
+ push_to_top_level ();
+
+ current_function_decl = NULL_TREE;
+ current_binding_level = NULL;
+
+ /* Enter the global namespace. */
+ global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
+ void_type_node);
+
+ current_lang_name = NULL_TREE;
+
/* Force minimum function alignment if using the least significant
bit of function pointers to store the virtual bit. */
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
@@ -3092,6 +3102,8 @@ init_cxx_decl_processing_once (void)
say -fwritable-strings? */
if (flag_writable_strings)
flag_const_strings = 0;
+
+ first = 0;
}
void setup_globals (void)
@@ -3103,8 +3115,14 @@ void setup_globals (void)
void
init_cxx_decl_processing_eachsrc (void)
{
- /* We use a conditional symbol table, so there isn't anything
- special we need to do here. */
+ static int c_init_decl_done = 0;
+
+ /* We use a conditional symbol table, so there isn't anything special
+ we need to do here besides resetting the cpp symbol table. */
+ if (c_init_decl_done++ != 0 && server_mode != 1)
+ {
+ reset_cpp_hashnodes ();
+ }
}
/* Generate an initializer for a function naming variable from
diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index 06d184374ed..d6f1d149598 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -40,7 +40,7 @@ Boston, MA 02111-1307, USA. */
%{!E:%{!M:%{!MM:\
%{save-temps|no-integrated-cpp:cc1plus -E\
%(cpp_options) %2 -o %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
- %{!server:cc1plus} %{server:@.cc1plus -fserver}\
+ @.cc1plus\
%{save-temps|no-integrated-cpp:-fpreprocessed %{save-temps:%b.ii} %{!save-temps:%g.ii}}\
%{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\
%(cc1_options) %2 %{+e1*}\
@@ -51,7 +51,7 @@ Boston, MA 02111-1307, USA. */
%{!E:%{!M:%{!MM:\
%{save-temps|no-integrated-cpp:cc1plus -E\
%(cpp_options) %2 -o %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
- %{!server:cc1plus} %{server:@.cc1plus -fserver}\
+ @.cc1plus\
%{save-temps|no-integrated-cpp:-fpreprocessed %{save-temps:%b.ii} %{!save-temps:%g.ii}}\
%{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\
%(cc1_options) %2 %{+e1*}\
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 43c51e568df..94ef6df6612 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -383,6 +383,7 @@ init_cp_pragma (void)
void
init_cxx_once (void)
{
+ static int first_time = 1;
static const enum tree_code stmt_codes[] = {
c_common_stmt_codes,
cp_stmt_codes
@@ -390,6 +391,7 @@ init_cxx_once (void)
INIT_STATEMENT_CODES (stmt_codes);
+ /* ICK! We need one builtuns_fragment that is once per server and one that is once per unit. */
if (server_mode >= 0 && server_mode != 1)
create_builtins_fragment ();
@@ -398,50 +400,60 @@ init_cxx_once (void)
debugging.*/
push_srcloc ("<internal>", 0);
- init_reswords ();
- init_tree ();
- init_cp_semantics ();
- init_operators ();
- init_method ();
- init_error ();
+ if (first_time)
+ {
+ init_reswords ();
+ init_tree ();
+ init_cp_semantics ();
+ init_operators ();
+ init_method ();
+ init_error ();
+ }
current_function_decl = NULL;
- class_type_node = build_int_2 (class_type, 0);
- TREE_TYPE (class_type_node) = class_type_node;
- ridpointers[(int) RID_CLASS] = class_type_node;
+ if (first_time)
+ {
+ class_type_node = build_int_2 (class_type, 0);
+ TREE_TYPE (class_type_node) = class_type_node;
+ ridpointers[(int) RID_CLASS] = class_type_node;
- record_type_node = build_int_2 (record_type, 0);
- TREE_TYPE (record_type_node) = record_type_node;
- ridpointers[(int) RID_STRUCT] = record_type_node;
+ record_type_node = build_int_2 (record_type, 0);
+ TREE_TYPE (record_type_node) = record_type_node;
+ ridpointers[(int) RID_STRUCT] = record_type_node;
- union_type_node = build_int_2 (union_type, 0);
- TREE_TYPE (union_type_node) = union_type_node;
- ridpointers[(int) RID_UNION] = union_type_node;
+ union_type_node = build_int_2 (union_type, 0);
+ TREE_TYPE (union_type_node) = union_type_node;
+ ridpointers[(int) RID_UNION] = union_type_node;
- enum_type_node = build_int_2 (enum_type, 0);
- TREE_TYPE (enum_type_node) = enum_type_node;
- ridpointers[(int) RID_ENUM] = enum_type_node;
+ enum_type_node = build_int_2 (enum_type, 0);
+ TREE_TYPE (enum_type_node) = enum_type_node;
+ ridpointers[(int) RID_ENUM] = enum_type_node;
+ }
init_cxx_decl_processing_once ();
- /* Create the built-in __null node. */
- null_node = build_int_2 (0, 0);
- TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
- ridpointers[RID_NULL] = null_node;
+ if (first_time)
+ {
+ /* Create the built-in __null node. */
+ null_node = build_int_2 (0, 0);
+ TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
+ ridpointers[RID_NULL] = null_node;
+ }
init_c_common_once ();
- init_cp_pragma ();
+ if (first_time)
+ init_cp_pragma ();
if (parse_in->do_note_macros)
{
- parse_in->do_note_macros = 0;
cb_exit_fragment (parse_in, builtins_fragment);
parse_in->current_fragment = NULL;
}
pop_srcloc ();
+ first_time = 0;
}
int
@@ -449,8 +461,10 @@ lang_clear_identifier (cpp_reader *pfile ATTRIBUTE_UNUSED,
cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
{
tree tnode = HT_IDENT_TO_GCC_IDENT (node);
+#if 0
IDENTIFIER_NAMESPACE_BINDINGS (tnode) = NULL;
IDENTIFIER_BINDING (tnode) = NULL;
+#endif
reset_hashnode (node);
return 1;
@@ -463,7 +477,10 @@ lang_clear_identifier (cpp_reader *pfile ATTRIBUTE_UNUSED,
bool
init_cxx_eachsrc (void)
{
+#if 0
+ /* This is too late to clear the cpp symbol table, cpp builtins are done before this. */
init_cxx_decl_processing_eachsrc ();
+#endif
interface_unknown = 1;
@@ -485,6 +502,9 @@ extract_interface_info (void)
{
struct c_fileinfo *finfo = 0;
+ if (input_filename == 0)
+ return;
+
if (flag_alt_external_templates)
{
tree til = tinst_for_decl ();
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
index 6abc7e3bbd6..2bb4917dcdb 100644
--- a/gcc/cppfiles.c
+++ b/gcc/cppfiles.c
@@ -77,6 +77,10 @@ struct _cpp_file_data
/* If BUFFER above contains the true contents of the file. */
bool buffer_valid;
+
+ /* A generation counter, used to determine when to re-read files, so
+ that we can avoid excess system calls. */
+ int generation;
};
/* This structure represents a file searched for by CPP, whether it
@@ -190,6 +194,36 @@ static char *remap_filename (cpp_reader *pfile, _cpp_file *file);
static char *append_file_to_dir (const char *fname, cpp_dir *dir);
static bool validate_pch (cpp_reader *, _cpp_file *file, const char *pchname);
static bool include_pch_p (_cpp_file *file);
+static bool file_modified (struct stat st1, struct stat st2);
+
+/* Return false if the file hasn't been modified, otherwise return
+ true. */
+
+static bool file_modified (struct stat st1, struct stat st2)
+{
+ if (st1.st_mtimespec.tv_sec != st2.st_mtimespec.tv_sec
+ || st1.st_mtimespec.tv_nsec != st2.st_mtimespec.tv_nsec
+ || st1.st_ctimespec.tv_sec != st2.st_ctimespec.tv_sec
+ || st1.st_ctimespec.tv_nsec != st2.st_ctimespec.tv_nsec
+ || st1.st_size != st2.st_size)
+ return true;
+ return false;
+}
+
+/* A counter to determine when we can avoid re-opening files and
+ restating them, as those operations take time. */
+
+static int generation = 0;
+
+/* This routine is called when files should be checked against the
+ filesystem to ensure they are still up-to-date. A good compromise
+ is once every output file. */
+
+void
+cpp_notice_updates (void)
+{
+ ++generation;
+}
/* Given a filename in FILE->PATH, with the empty string interpreted
as <stdin>, open it.
@@ -256,6 +290,17 @@ open_file (cpp_reader *pfile, _cpp_file *file)
data = xcalloc (1, sizeof (_cpp_file_data));
file->data = data;
}
+ else
+ {
+ /* If a file was modified, we arrange to re-read
+ it. */
+ if (file_modified (st, data->st))
+ {
+ /* This will re-read the file. */
+ data->buffer_valid = false;
+ }
+ }
+ data->generation = generation;
data->st = st;
data->fd = fd;
file->err_no = 0;
@@ -470,7 +515,12 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
/* First check the cache before we resort to memory allocation. */
entry = search_cache (*hash_slot, start_dir);
- if (entry)
+ if (entry
+ /* But don't reuse a PCH file that has been read once. We have
+ to revalidate for new command line flags and possibly a new
+ pchname. */
+ && ! (include_pch_p (entry->u.file)
+ && entry->u.file->data->fd == -1))
return entry->u.file;
file = make_cpp_file (pfile, start_dir, fname);
@@ -516,6 +566,8 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool f
/* Cache for START_DIR too, sharing the _cpp_file structure. */
free ((char *) file->name);
free (file);
+ if (file->data)
+ entry->u.file->data->fd = file->data->fd;
file = entry->u.file;
}
else
@@ -623,6 +675,7 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
data->buffer = buf;
data->st.st_size = total;
data->buffer_valid = true;
+ data->generation = generation;
if (pfile->cb.exit_fragment != NULL)
{
@@ -647,6 +700,46 @@ read_file_guts (cpp_reader *pfile, _cpp_file *file)
return true;
}
+/* Determine if a file has been modified. If it has, the file will be
+ re-read. */
+
+static bool
+file_changed (cpp_reader *pfile, _cpp_file *file)
+{
+ struct stat st;
+
+ /* We avoid checking file modification times very often. */
+ if (file->data->generation == generation)
+ return false;
+
+ if (file->data->fd == -1)
+ {
+ /* open_file will check for modifications to the file. */
+ if (!open_file (pfile, file))
+ {
+ /* If we can't open a file, force it to be re-opened. */
+ return true;
+ }
+
+ /* open_file clears buffer_valid if the file was modified. */
+ if (file->data->buffer_valid)
+ return false;
+ }
+ else if (fstat (file->data->fd, &st) == 0)
+ {
+ if (! file_modified (file->data->st, st))
+ {
+ /* Conserve open files. */
+ close (file->data->fd);
+ file->data->fd = -1;
+ return false;
+ }
+ /* We can leave the file open, as we are going to re-read
+ it. */
+ }
+ return true;
+}
+
/* Convenience wrapper around read_file_guts that opens the file if
necessary and closes the file descriptor after reading. FILE must
have been passed through find_file() at some stage. */
@@ -656,10 +749,8 @@ read_file (cpp_reader *pfile, _cpp_file *file)
_cpp_file_data *data = file->data;
/* If we already have its contents in memory, succeed immediately. */
if (data->buffer_valid)
-#if 0
- if (! cached_version_is_current_according_to_stat (file))
-#endif
- return true;
+ if (! file_changed (pfile, file))
+ return true;
data = file->data;
@@ -831,10 +922,6 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
/* Generate the call back. */
_cpp_do_file_change (pfile, LC_ENTER, file->path, 1, sysp);
- if (CPP_OPTION (pfile, lang) == CLK_GNUCXX
- || CPP_OPTION (pfile, lang) == CLK_CXX98)
- _cpp_start_fragment (pfile);
-
return true;
}
@@ -853,9 +940,7 @@ purge_fragments (_cpp_file_data *data)
while (fragment != NULL)
{
cpp_fragment *next = fragment->next;
- if (fragment->macro_notes != NULL)
- free (fragment->macro_notes);
- free ((PTR) fragment);
+ delete_fragment (fragment);
fragment = next;
}
data->fragments = NULL;
@@ -1244,7 +1329,15 @@ _cpp_pop_file_buffer (cpp_reader *pfile, _cpp_file *file)
if (data && !data->buffer_valid)
{
+#if 1
+ /* MERGE I don't think this is necessary anymore */
+ if (data->buffer == NULL
+ /* In C++, we can reuse main file fragments as well. */
+ && ! (CPP_OPTION (pfile, lang) == CLK_GNUCXX
+ || CPP_OPTION (pfile, lang) == CLK_CXX98))
+#else
if (data->buffer)
+#endif
{
free ((void *) data->buffer);
data->buffer = NULL;
diff --git a/gcc/cppinit.c b/gcc/cppinit.c
index 13326886778..fb68668d9bf 100644
--- a/gcc/cppinit.c
+++ b/gcc/cppinit.c
@@ -447,6 +447,11 @@ cpp_post_options (cpp_reader *pfile)
/* Mark named operators before handling command line macros. */
if (CPP_OPTION (pfile, cplusplus) && CPP_OPTION (pfile, operator_names))
mark_named_operators (pfile);
+
+ /* We arrange to recheck for modified files once per output file.
+ Between output files, we don't recheck the modification times of
+ files for improved performance. */
+ cpp_notice_updates ();
}
/* Setup for processing input from the file named FNAME, or stdin if
@@ -490,6 +495,10 @@ cpp_push_main_file (cpp_reader *pfile)
{
_cpp_stack_file (pfile, pfile->main_file, false);
+ if (CPP_OPTION (pfile, lang) == CLK_GNUCXX
+ || CPP_OPTION (pfile, lang) == CLK_CXX98)
+ _cpp_start_fragment (pfile);
+
/* For foo.i, read the original filename foo.c now, for the benefit
of the front ends. */
if (CPP_OPTION (pfile, preprocessed))
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index bf810ffb94f..e9913b1f434 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -767,6 +767,7 @@ extern const char *cpp_get_path (struct _cpp_file *);
extern cpp_buffer *cpp_get_buffer (cpp_reader *);
extern struct _cpp_file *cpp_get_file (cpp_buffer *);
extern cpp_buffer *cpp_get_prev (cpp_buffer *);
+extern void cpp_notice_updates (void);
/* In cpppch.c */
struct save_macro_data;
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 33481bc534c..04267a8e310 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -238,7 +238,7 @@ static int save_temps_flag;
static int use_pipes;
#ifdef ENABLE_SERVER
-static int use_server;
+static int use_server = 1;
static int kill_server;
static int kill_servercp;
#endif
@@ -379,8 +379,6 @@ static void clear_args (void);
static void fatal_error (int);
#ifdef ENABLE_SERVER
static int get_server_socket (const char *, bool);
-static void write_input_request (const char *, int, int);
-static void write_input_requests (int);
static void write_switch_fds_request (int, int, int);
static void write_output_request (const char *, int);
#endif
@@ -785,7 +783,7 @@ static const char *cpp_unique_options =
%{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
%{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
%{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
- %{trigraphs} %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %{!server:%i}\
+ %{trigraphs} %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
%{E|M|MM:%W{o*}}";
/* This contains cpp options which are common with cc1_options and are passed
@@ -804,8 +802,8 @@ static const char *cpp_debug_options = "%{d*}";
/* NB: This is shared amongst all front-ends. */
static const char *cc1_options =
"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %1 %{!Q:-quiet} %{!server:-dumpbase %B} %{d*} %{m*} %{a*}\
- %{!server:-auxbase%{c|S:%{o*:-strip %*}%{!o*: %b}}%{!c:%{!S: %b}}}\
+ %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
+ -auxbase%{c|S:%{o*:-strip %*}%{!o*: %b}}%{!c:%{!S: %b}}\
%{g*} %{O*} %{W*&pedantic*} %{w} %{std*} %{ansi}\
%{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
%{Qn:-fno-ident} %{--help:--help}\
@@ -949,7 +947,7 @@ static const struct compiler default_compilers[] =
cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
%(cc1_options)}\
%{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
- %{!server:cc1} %{server:@.cc1} %(cpp_unique_options) %(cc1_options)}}}\
+ @.cc1 %(cpp_unique_options) %(cc1_options)}}}\
%{!fsyntax-only:%(invoke_as)}}}}", 0},
{"-",
"%{!E:%e-E required when input is from standard input}\
@@ -2752,7 +2750,6 @@ pexecute_server (const char *string,
pfatal_with_name ("(socket write)");
obstack_free (&obstack, base);
- write_input_requests (sock);
write_output_request (asm_name, sock);
*server_socketp = sock;
return 0;
@@ -2918,6 +2915,12 @@ execute (void)
char *errmsg_fmt, *errmsg_arg;
const char *string = commands[i].argv[0];
+ if (use_server == 0 && string[0] == '@' && string[1] == '.')
+ {
+ commands[i].argv[0] += 2;
+ string = commands[i].argv[0];
+ }
+
commands[i].server_socket = -1;
#ifdef ENABLE_SERVER
if (use_server && string[0] == '@' && string[1] == '.')
@@ -3726,10 +3729,18 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
report_times = 1;
else if (strcmp (argv[i], "-pipe") == 0)
{
- /* -pipe has to go into the switches array as well as
- setting a flag. */
- use_pipes = 1;
- n_switches++;
+ /* Need a way to turn off -pipe for the compile server.
+ use_server isn't set yet, and we can't delay unsetting
+ use_pipes, this increases fragment reused by allowing
+ more fragments to be valid, as we use ftell on the asm
+ file to check to see if we can reuse fragments. */
+ if (0)
+ {
+ /* -pipe has to go into the switches array as well as
+ setting a flag. */
+ use_pipes = 1;
+ n_switches++;
+ }
}
#ifdef ENABLE_SERVER
else if (strcmp (argv[i], "-server") == 0)
@@ -5889,6 +5900,50 @@ process_brace_body (const char *p, const char *atom, const char *end_atom,
}
#ifdef ENABLE_SERVER
+static void
+start_server (const char *);
+
+/* Start up a compile server of the appropriate type. This is called
+ when one is not already running. */
+
+static void
+start_server (const char *prog)
+{
+ char *buf;
+ /* Try starting server... */
+ char *s = find_a_file (&exec_prefixes, prog, X_OK, 0);
+ if (s == NULL)
+ pfatal_with_name ("finding compiler");
+
+ buf = alloca (strlen (s) + 10);
+ sprintf (buf, "'%s' -fserver &", s);
+ system (buf);
+
+ /* Hum... We need to let the compiler server start up and start
+ accepting connections... how long should be wait?
+
+ How about we have -fserver fork and have the parent return after
+ the child has started and is hot, then we can return when system
+ completes. */
+ sleep (1);
+}
+
+static void
+xread (int fd, char *buf, size_t len)
+{
+ if ((size_t)read (fd, buf, len) != len)
+ pfatal_with_name ("read");
+}
+
+static void
+waitforgo (int sock)
+{
+ char buf[1];
+ xread (sock, buf, 1);
+ if (buf[0] != 'G')
+ pfatal_with_name ("protocol violation");
+}
+
/* Contact a compile server. If loadbalancer is true, then contact
the load balancer instead. */
@@ -5898,6 +5953,7 @@ get_server_socket (const char *prog, bool loadbalancer)
struct sockaddr_un server;
char buf[1];
int sock;
+ int server_started = 0;
if (reuse_server_sockets && server_socket >= 0)
{
@@ -5912,16 +5968,22 @@ get_server_socket (const char *prog, bool loadbalancer)
server.sun_family = AF_UNIX;
sprintf (server.sun_path, ".%s-server", prog);
- if (connect (sock,
- (struct sockaddr *) &server,
- sizeof(struct sockaddr_un)) < 0)
+ while (connect (sock,
+ (struct sockaddr *) &server,
+ sizeof(struct sockaddr_un)) < 0)
{
-#if 0
- ... try starting server ...;
-#endif
- close (sock);
- pfatal_with_name ("connecting stream socket");
+ if (server_started)
+ {
+ close (sock);
+ pfatal_with_name ("connecting stream socket");
+ }
+ start_server (prog);
+ server_started = 1;
}
+#define DARWIN_JAG_BUG 1
+#ifdef DARWIN_JAG_BUG
+ waitforgo (sock);
+#endif
if (loadbalancer)
buf[0] = 'L';
else
@@ -5941,23 +6003,6 @@ get_server_socket (const char *prog, bool loadbalancer)
}
static void
-write_input_request (const char *filename, int filename_length, int fd)
-{
- int wlen;
- void *base;
- obstack_grow (&obstack, "I\000", 2);
- obstack_grow (&obstack, filename, filename_length);
- obstack_grow (&obstack, "\000\n", 2);
- base = obstack_base (&obstack);
- wlen = obstack_object_size (&obstack);
- if (((char*)base)[0] == 0)
- pfatal_with_name ("bad write, was 0");
- if (write (fd, base, wlen) != wlen)
- pfatal_with_name ("(socket write)");
- obstack_free (&obstack, base);
-}
-
-static void
write_output_request (const char *filename, int fd)
{
int filename_length = strlen (filename);
@@ -5974,23 +6019,6 @@ write_output_request (const char *filename, int fd)
}
static void
-write_input_requests (int sock)
-{
- if (combine_inputs)
- {
- int j;
- for (j = 0; (int) j < n_infiles; j++)
- write_input_request (infiles[j].name,
- strlen (infiles[j].name),
- sock);
- }
- else
- {
- write_input_request (input_filename, input_filename_length, sock);
- }
-}
-
-static void
send_fd (int fd, int sock)
{
struct msghdr msg;
@@ -6020,21 +6048,11 @@ send_fd (int fd, int sock)
}
static void
-xread (int fd, char *buf, size_t len)
-{
- if ((size_t)read (fd, buf, len) != len)
- pfatal_with_name ("read");
-}
-
-static void
write_switch_fds_request (int sock, int input_desc, int output_desc)
{
- char buf[1];
if (write (sock, "D\n", 2) != 2)
pfatal_with_name ("(socket write)");
- xread (sock, buf, 1);
- if (buf[0] != 'G')
- pfatal_with_name ("nope");
+ waitforgo (sock);
send_fd (input_desc, sock);
send_fd (output_desc, sock);
send_fd (2, sock);
diff --git a/gcc/objc/lang-specs.h b/gcc/objc/lang-specs.h
index a836c6f76a4..c98e0b79d6f 100644
--- a/gcc/objc/lang-specs.h
+++ b/gcc/objc/lang-specs.h
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
%{save-temps|no-integrated-cpp:cc1obj -E %(cpp_options) -o %{save-temps:%b.mi} %{!save-temps:%g.mi} \n\
cc1obj -fpreprocessed %{save-temps:%b.mi} %{!save-temps:%g.mi} %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}\
%{!save-temps:%{!no-integrated-cpp:\
- %{!server:cc1obj} %{server:@.cc1obj} %(cpp_unique_options) %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}}\
+ @.cc1obj %(cpp_unique_options) %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}}\
%{!fsyntax-only:%(invoke_as)}}}}", 0},
{".mi", "@objc-cpp-output", 0},
{"@objc-cpp-output",
diff --git a/gcc/opts.c b/gcc/opts.c
index 9dc75a89c17..daa65fede9f 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -468,6 +468,59 @@ add_input_filename (const char *filename)
in_fnames[num_in_fnames - 1] = filename;
}
+/* Any option that can change, we have to re-initialize here. */
+
+void
+reinit_opts ()
+{
+ pedantic = 0;
+ profile_flag = 0;
+ flag_pedantic_errors = 0;
+ quiet_flag = 0;
+ version_flag = false;
+ inhibit_warnings = false;
+ optimize_size = 0;
+ optimize = 0;
+ flag_defer_pop = 0;
+ flag_thread_jumps = 0;
+ flag_delayed_branch = 0;
+ flag_omit_frame_pointer = 0;
+ flag_guess_branch_prob = 0;
+ flag_cprop_registers = 0;
+ flag_loop_optimize = 0;
+ flag_crossjumping = 0;
+ flag_if_conversion = 0;
+ flag_if_conversion2 = 0;
+ flag_optimize_sibling_calls = 0;
+ flag_cse_follow_jumps = 0;
+ flag_cse_skip_blocks = 0;
+ flag_gcse = 0;
+ flag_expensive_optimizations = 0;
+ flag_strength_reduce = 0;
+ flag_rerun_cse_after_loop = 0;
+ flag_rerun_loop_opt = 0;
+ flag_caller_saves = 0;
+ flag_force_mem = 0;
+ flag_peephole2 = 0;
+ flag_schedule_insns = 0;
+ flag_schedule_insns_after_reload = 0;
+ flag_regmove = 0;
+ flag_strict_aliasing = 0;
+ flag_delete_null_pointer_checks = 0;
+ flag_reorder_blocks = 0;
+ flag_reorder_functions = 0;
+ flag_unit_at_a_time = 0;
+ flag_inline_functions = 0;
+ flag_rename_registers = 0;
+ flag_unswitch_loops = 0;
+ flag_web = 0;
+ align_loops = 0;
+ align_jumps = 0;
+ align_labels = 0;
+ align_functions = 0;
+ flag_reorder_blocks = 0;
+}
+
/* Parse command line options and set default flag values. Do minimal
options processing. */
void
@@ -475,10 +528,18 @@ decode_options (unsigned int argc, const char **argv)
{
unsigned int i, lang_mask;
+ reinit_opts ();
+
/* Perform language-specific options initialization. */
lang_mask = (*lang_hooks.init_options) (argc, argv);
- lang_hooks.initialize_diagnostics (global_dc);
+ {
+ static int first = 1;
+ if (first) {
+ lang_hooks.initialize_diagnostics (global_dc);
+ first = 0;
+ }
+ }
/* Scan to see what optimization level has been specified. That will
determine the default value of many flags. */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 003b9aa4204..f5b3c6e1261 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1598,6 +1598,8 @@ wrapup_global_declarations (tree *vec, int len)
{
decl = vec[i];
+ DECL_NEWEST_DUPLICATE (decl);
+
if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
continue;
@@ -1646,7 +1648,9 @@ wrapup_global_declarations (tree *vec, int len)
|| DECL_ARTIFICIAL (decl)))
needed = 0;
- if (needed)
+ /* Don't infinitely loop when we have written out the
+ decl already. */
+ if (needed && ! TREE_ASM_WRITTEN (decl))
{
reconsider = 1;
rest_of_decl_compilation (decl, NULL, 1, 1);
@@ -4532,8 +4536,6 @@ lang_dependent_init (void)
debug output. */
(*debug_hooks->init) (main_input_filename);
- lang_hooks.pch_init ();
-
timevar_pop (TV_SYMOUT);
return 1;
@@ -4617,20 +4619,25 @@ finalize (void)
static void
init_compile_once (void)
{
+ static int first = 1;
/* The bulk of the command line switch processing. */
process_options ();
if (server_mode < 0 && num_in_fnames > 1)
server_mode = 0;
- init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
- || debug_info_level == DINFO_LEVEL_VERBOSE
+ if (first)
+ {
+ init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
+ || debug_info_level == DINFO_LEVEL_VERBOSE
#ifdef VMS_DEBUGGING_INFO
- /* Enable line number info for traceback. */
- || debug_info_level > DINFO_LEVEL_NONE
+ /* Enable line number info for traceback. */
+ || debug_info_level > DINFO_LEVEL_NONE
#endif
- || flag_test_coverage
- || warn_notreached);
+ || flag_test_coverage
+ || warn_notreached);
+ first = 0;
+ }
(*lang_hooks.init_once) ();
}
@@ -4747,6 +4754,7 @@ server_get_command (int fd, char **bufp, int *posp, int *limp, int *blenp)
{
if (buf[0] == 0)
{
+ fatal_error ("kernel bug in 10.2.x, fixed in 10.3");
/* This looks to be a kernel bug with Jaguar. */
fprintf (stderr, "bad read, got 0, assuming I\n");
buf[0] = 'I';
@@ -4927,6 +4935,15 @@ pop_fd (void)
static int
get_job (const char *);
+static void
+waitforgo (int sock)
+{
+ char buf[1];
+ xread (sock, buf, 1);
+ if (buf[0] != 'G')
+ fatal_error ("protocol violation");
+}
+
/* Get a job from the load balancer. */
static int
@@ -4956,6 +4973,10 @@ get_job (const char *prog)
return -1;
fatal_error ("connecting stream socket: %m");
}
+#define DARWIN_JAG_BUG 1
+#ifdef DARWIN_JAG_BUG
+ waitforgo (sock);
+#endif
xwrite (sock, "S", 1);
/* Wait here until the load balancer says go. */
@@ -5005,6 +5026,10 @@ get_request_from_load_balancer (int *sockp)
} while (fd < 0 && errno == EINTR);
if (fd < 0)
fatal_error ("can't connect to client socket: %m");
+#define DARWIN_JAG_BUG 1
+#ifdef DARWIN_JAG_BUG
+ xwrite (fd, "G", 1);
+#endif
xread (fd, xbuf, 1);
switch (xbuf[0])
@@ -5188,18 +5213,39 @@ server_loop (void)
char *fname = command_buffer + 2;
fname [asm_name_length] = 0;
memcpy (abuf, fname, asm_name_length+1);
+ if (asm_file_name)
+ free ((void*)asm_file_name);
asm_file_name = abuf;
if (! quiet_flag)
fprintf (stderr, "Assembler file: '%s'\n", asm_file_name);
- do_compile ();
+ save_argv = server_argv;
+
+ /* Parse the options and do minimal processing; basically just
+ enough to default flags appropriately. */
+ decode_options (server_argc, server_argv);
+
+ randomize ();
+
+ /* Exit early if we can (e.g. -help). */
+ if (!exit_after_options)
+ {
+ init_compile_once ();
+
+ /* If an error has already occurred, give up. */
+ if (! errorcount)
+ {
+ do_compile ();
+ }
+ }
for (i = num_in_fnames; --i >= 0; )
{
const char *name = in_fnames[i];
- free ((void*) name);
in_fnames[i] = NULL;
+ free ((void*) name);
}
+ free (in_fnames);
in_fnames = NULL;
num_in_fnames = 0;
if (old_fd[0] != -1)
@@ -5208,6 +5254,11 @@ server_loop (void)
xbuf[0] = (errorcount || sorrycount ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE);
xwrite (fd, xbuf, 1);
+#define DARWIN_JAG_BUG2 1
+#ifdef DARWIN_JAG_BUG2
+ close (fd);
+ fd = -1;
+#endif
/* This is for testing, to get the server to stop with each
error that should not be an error. Eventually, this
should be removed when the server works well. */
@@ -5329,6 +5380,16 @@ toplev_main (unsigned int argc, const char **argv)
/* Initialization of GCC's environment, and diagnostics. */
general_init (argv[0]);
+ /* Should just be == 2. */
+ if (argc >= 2 && strcmp (argv[1], "-fserver") == 0)
+ server_mode = 2;
+
+ if (server_mode > 0)
+ {
+ server_loop ();
+ return 0;
+ }
+
/* Parse the options and do minimal processing; basically just
enough to default flags appropriately. */
decode_options (argc, argv);