This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 10/16] binutils: Introduce "gas_main", and state-purging with "gas" subdir
- From: David Malcolm <dmalcolm at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, binutils at sourceware dot org
- Cc: David Malcolm <dmalcolm at redhat dot com>
- Date: Mon, 1 Jun 2015 17:04:18 -0400
- Subject: [PATCH 10/16] binutils: Introduce "gas_main", and state-purging with "gas" subdir
- Authentication-results: sourceware.org; auth=none
- References: <1433192664-50156-1-git-send-email-dmalcolm at redhat dot com>
Currently this has only been tested on x86_64, and hardcodes this
cleanup:
extern void config_obj_elf_c_finalize (void);
extern void config_tc_i386_c_finalize (void);
Clearly this would need generalizing.
gas/ChangeLog:
* app.c (app_c_finalize): New function.
* as.c: Include new header "libgas.h".
(gas_timer): New variable.
(emulations): Make the underlying struct emulation be const.
(parse_args): Reset internal state of getopt_long_only.
(main): Rename to gas_internal_main. Make static.
Add param "standalone". Add uses of GAS_TIMER_PUSH and
GAS_TIMER_POP. Conditionalize calls to xatexit with check
for "standalone", and explicitly call close_output_file in
the non-standalone case. Replace calls to xexit with
return statements.
(config_obj_elf_c_finalize): Add prototype.
(config_tc_i386_c_finalize): Likwise.
(gas_main): New function.
(as_c_finalize): New function.
* as.h (app_c_finalize): New prototype.
(depend_c_finalize): New prototype.
(gas_timer): New variable.
(GAS_TIMER_PUSH): New macro.
(GAS_TIMER_POP): New macro.
* asmain.c: New file.
* config/obj-elf.c (obj_elf_ident): Split out the function-level
static variable "comment_section" into...
(obj_elf_ident_comment_section): ...this file-level static
variable.
(config_obj_elf_c_finalize): New function.
* config/tc-i386.c (config_tc_i386_c_finalize): New function.
* depend.c (depend_c_finalize): New function.
* dw2gencfi.c (dw2gencfi_c_finalize): New function.
* dw2gencfi.h (dw2gencfi_c_finalize): New prototype.
* libgas.h: New file.
* macro.c (macro_c_finalize): New function.
* macro.h (macro_c_finalize): New prototype.
* output-file.c (output_file_c_finalize): New function.
* output-file.h (output_file_c_finalize): New prototype.
* read.c (read_c_finalize): New function.
* read.h (read_c_finalize): New prototype.
* subsegs.c (subsegs_c_finalize): New function.
* subsegs.h (subsegs_c_finalize): New prototype.
* symbols.c (symbols_c_finalize): New function.
* symbols.h (symbols_c_finalize): New prototype.
* write.c (write_c_finalize): New function.
* write.h (write_c_finalize): New prototype.
---
gas/app.c | 27 ++++++++
gas/as.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++---
gas/as.h | 12 ++++
gas/asmain.c | 35 ++++++++++
gas/config/obj-elf.c | 25 +++++--
gas/config/tc-i386.c | 79 ++++++++++++++++++++++
gas/depend.c | 10 +++
gas/dw2gencfi.c | 12 ++++
gas/dw2gencfi.h | 2 +
gas/libgas.h | 41 ++++++++++++
gas/macro.c | 18 +++++
gas/macro.h | 2 +
gas/output-file.c | 8 +++
gas/output-file.h | 1 +
gas/read.c | 47 +++++++++++++
gas/read.h | 2 +
gas/subsegs.c | 10 +++
gas/subsegs.h | 1 +
gas/symbols.c | 41 ++++++++++++
gas/symbols.h | 2 +
gas/write.c | 15 +++++
gas/write.h | 1 +
22 files changed, 558 insertions(+), 15 deletions(-)
create mode 100644 gas/asmain.c
create mode 100644 gas/libgas.h
diff --git a/gas/app.c b/gas/app.c
index 67402e2..fda8216 100644
--- a/gas/app.c
+++ b/gas/app.c
@@ -1479,3 +1479,30 @@ do_scrub_chars (size_t (*get) (char *, size_t), char *tostart, size_t tolen)
return to - tostart;
}
+
+/* Reset all global state within app.c. */
+
+void
+app_c_finalize (void)
+{
+#ifdef H_TICK_HEX
+ enable_h_tick_hex = 0;
+#endif
+#ifdef TC_M68K
+ scrub_m68k_mri = 0;
+#endif
+#if defined TC_ARM && defined OBJ_ELF
+ symver_state = NULL;
+#endif
+ CLEAR_VAR (lex);
+ state = 0;
+ old_state = 0;
+ out_string = NULL;
+ CLEAR_VAR (out_buf);
+ add_newlines = 0;
+ saved_input = NULL;
+ saved_input_len = 0;
+ CLEAR_VAR (input_buffer);
+ mri_state = NULL;
+ mri_last_ch = 0;
+}
diff --git a/gas/as.c b/gas/as.c
index 2a8923f..90dc298 100644
--- a/gas/as.c
+++ b/gas/as.c
@@ -31,6 +31,8 @@
#define COMMON
+#include "libgas.h"
+
#include "as.h"
#include "subsegs.h"
#include "output-file.h"
@@ -66,6 +68,8 @@ struct defsym_list
valueT value;
};
+/* Global timer. */
+struct ctimer *gas_timer;
/* True if a listing is wanted. */
int listing;
@@ -135,7 +139,7 @@ extern struct emulation mipsbelf, mipslelf, mipself;
extern struct emulation i386coff, i386elf, i386aout;
extern struct emulation crisaout, criself;
-static struct emulation *const emulations[] = { EMULATIONS };
+static const struct emulation *const emulations[] = { EMULATIONS };
static const int n_emulations = sizeof (emulations) / sizeof (emulations[0]);
static void
@@ -546,6 +550,9 @@ parse_args (int * pargc, char *** pargv)
new_argc = 1;
new_argv[new_argc] = NULL;
+ /* Reset internal state of getopt_long_only. */
+ optind = 0;
+
while (1)
{
/* getopt_long_only is like getopt_long, but '-' as well as '--' can
@@ -1122,13 +1129,18 @@ perform_an_assembly_pass (int argc, char ** argv)
}
-int
-main (int argc, char ** argv)
+/* Run the assembler: almost the top-level of the assembler implementation.
+ Called by gas_main after it has set up gas_timer. */
+
+static int
+gas_internal_main (int argc, char ** argv, int standalone)
{
char ** argv_orig = argv;
int macro_strip_at;
+ GAS_TIMER_PUSH ("before pass");
+
start_time = get_run_time ();
#ifdef HAVE_SBRK
start_sbrk = (char *) sbrk (0);
@@ -1183,9 +1195,10 @@ main (int argc, char ** argv)
expr_begin ();
/* It has to be called after dump_statistics (). */
- xatexit (close_output_file);
+ if (standalone)
+ xatexit (close_output_file);
- if (flag_print_statistics)
+ if (flag_print_statistics && standalone)
xatexit (dump_statistics);
macro_strip_at = 0;
@@ -1236,8 +1249,14 @@ main (int argc, char ** argv)
PROGRESS (1);
+ GAS_TIMER_POP ();
+
/* Assemble it. */
+ GAS_TIMER_PUSH ("perform_an_assembly_pass");
perform_an_assembly_pass (argc, argv);
+ GAS_TIMER_POP ();
+
+ GAS_TIMER_PUSH ("after pass");
cond_finish_check (-1);
@@ -1316,13 +1335,158 @@ main (int argc, char ** argv)
END_PROGRESS (myname);
- /* Use xexit instead of return, because under VMS environments they
- may not place the same interpretation on the value given. */
+ if (!standalone)
+ close_output_file ();
+
+ GAS_TIMER_POP ();
+
if (had_errors () != 0)
- xexit (EXIT_FAILURE);
+ return EXIT_FAILURE;
/* Only generate dependency file if assembler was successful. */
print_dependencies ();
- xexit (EXIT_SUCCESS);
+ return EXIT_SUCCESS;
+}
+
+static void as_c_finalize (void);
+
+/* FIXME. */
+extern void config_obj_elf_c_finalize (void);
+extern void config_tc_i386_c_finalize (void);
+
+/* Public API entrypoint. */
+
+int
+gas_main (int argc, char **argv, int standalone, struct ctimer *timer)
+{
+ int result;
+
+ /* Set global gas_timer. */
+ gas_timer = timer;
+
+ GAS_TIMER_PUSH ("gas_main");
+
+ result = gas_internal_main (argc, argv, standalone);
+ if (!standalone)
+ {
+ GAS_TIMER_PUSH ("cleanup");
+
+ if (flag_print_statistics)
+ dump_statistics ();
+
+ /* Restore all state. */
+ bfd_uninit ();
+
+ /* Restore all state within gas. */
+ app_c_finalize ();
+ as_c_finalize ();
+ depend_c_finalize ();
+ dw2gencfi_c_finalize ();
+ macro_c_finalize ();
+ read_c_finalize ();
+ output_file_c_finalize ();
+ subsegs_c_finalize ();
+ symbols_c_finalize ();
+ write_c_finalize ();
+ /* FIXME: */
+ config_obj_elf_c_finalize ();
+ config_tc_i386_c_finalize ();
+
+ GAS_TIMER_POP ();
+ }
+
+ GAS_TIMER_POP ();
+
+ gas_timer = NULL;
+
+ return result;
+}
+
+/* Reset all global state within as.c. */
+
+static void
+as_c_finalize (void)
+{
+ listing = 0;
+ debug_type = DEBUG_UNSPECIFIED;
+ use_gnu_debug_info_extensions = 0;
+ max_macro_nest = 100;
+ myname = NULL;
+ chunksize = 0;
+ debug_memory = 0;
+ verbose = 0;
+ keep_it = 0;
+ reg_section = NULL;
+ expr_section = NULL;
+ text_section = NULL;
+ data_section = NULL;
+ bss_section = NULL;
+ listing_filename = NULL;
+ defsyms = NULL;
+#ifdef HAVE_ITBL_CPU
+ itbl_files = NULL;
+#endif
+ start_time = 0;
+#ifdef HAVE_SBRK
+ start_sbrk = NULL;
+#endif
+ flag_macro_alternate = 0;
+
+ /* The header files use the prefix COMMON for various declarations,
+ which for most translation units is "extern".
+ Within as.c, COMMON is empty, and so this file contains
+ their definitions.
+ Reset their state here. */
+
+ /* "COMMON" vars within as.h. */
+ now_subseg = 0;
+ now_seg = NULL;
+ flag_no_comments = 0;
+ flag_debug = 0;
+ flag_signed_overflow_ok = 0;
+#ifndef WORKING_DOT_WORD
+ flag_warn_displacement = 0;
+#endif
+ flag_keep_locals = 0;
+ flag_mri = 0;
+ flag_readonly_data_in_text = 0;
+ flag_no_warnings = 0;
+ flag_fatal_warnings = 0;
+ flag_always_generate_output = 0;
+ flag_print_statistics = 0;
+ flag_strip_local_absolute = 0;
+ flag_traditional_format = 0;
+ flag_compress_debug = 0;
+ flag_execstack = 0;
+ flag_noexecstack = 0;
+ out_file_name = NULL;
+ insttbl_file_name = NULL;
+ need_pass_2 = 0;
+ linkrelax = 0;
+ flag_dwarf_sections = 0;
+#ifdef TC_M68K
+ flag_m68k_mri = 0;
+#endif
+#ifdef WARN_COMMENTS
+ warn_comment = 0;
+ found_comment = 0;
+ found_comment_file = NULL;
+#endif
+#if defined OBJ_ELF || defined OBJ_MAYBE_ELF
+ flag_size_check = 0;
+#endif
+
+ /* "COMMON" var within emul.h. */
+#ifdef USE_EMULATIONS
+ this_emulation = NULL;
+#endif
+
+ /* "COMMON" vars within frags.h. */
+ frag_now = NULL;
+ CLEAR_VAR (zero_address_frag);
+ CLEAR_VAR (predefined_address_frag);
+
+ /* "COMMON" var within obj.h. */
+ this_format = NULL;
}
diff --git a/gas/as.h b/gas/as.h
index 6de319e..8e241a9 100644
--- a/gas/as.h
+++ b/gas/as.h
@@ -517,6 +517,9 @@ void register_dependency (char *);
void print_dependencies (void);
segT subseg_get (const char *, int);
+extern void app_c_finalize (void);
+extern void depend_c_finalize (void);
+
const char *remap_debug_filename (const char *);
void add_debug_prefix_map (const char *);
@@ -631,4 +634,13 @@ flag_size_check;
#error "Octets per byte conflicts with its power-of-two definition!"
#endif
+extern struct ctimer *gas_timer;
+
+#define GAS_TIMER_PUSH(ITEM_NAME) \
+ do { CTIMER_PUSH (gas_timer, (ITEM_NAME)); } while (0)
+
+#define GAS_TIMER_POP() \
+ do { CTIMER_POP (gas_timer); } while (0)
+
+
#endif /* GAS */
diff --git a/gas/asmain.c b/gas/asmain.c
new file mode 100644
index 0000000..687ae73
--- /dev/null
+++ b/gas/asmain.c
@@ -0,0 +1,35 @@
+/* asmain.c - "main" for standalone "as" program.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include "as.h"
+#include "libgas.h"
+
+int
+main (int argc, char ** argv)
+{
+ int result = gas_main (argc,
+ argv,
+ 1, /* standalone */
+ NULL); /* timer */
+
+ /* Use xexit instead of return, because under VMS environments they
+ may not place the same interpretation on the value given. */
+ xexit (result);
+}
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 4d7a8a7..cb44a10 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -1947,10 +1947,11 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED)
demand_empty_rest_of_line ();
}
+static segT obj_elf_ident_comment_section;
+
static void
obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
{
- static segT comment_section;
segT old_section = now_seg;
int old_subsection = now_subseg;
@@ -1958,14 +1959,14 @@ obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
md_flush_pending_output ();
#endif
- if (!comment_section)
+ if (!obj_elf_ident_comment_section)
{
char *p;
- comment_section = subseg_new (".comment", 0);
- bfd_set_section_flags (stdoutput, comment_section,
+ obj_elf_ident_comment_section = subseg_new (".comment", 0);
+ bfd_set_section_flags (stdoutput, obj_elf_ident_comment_section,
SEC_READONLY | SEC_HAS_CONTENTS
| SEC_MERGE | SEC_STRINGS);
- comment_section->entsize = 1;
+ obj_elf_ident_comment_section->entsize = 1;
#ifdef md_elf_section_change_hook
md_elf_section_change_hook ();
#endif
@@ -1973,7 +1974,7 @@ obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
*p = 0;
}
else
- subseg_set (comment_section, 0);
+ subseg_set (obj_elf_ident_comment_section, 0);
stringer (8 + 1);
subseg_set (old_section, old_subsection);
}
@@ -2681,3 +2682,15 @@ const struct format_ops elf_format_ops =
0,
elf_adjust_symtab
};
+
+/* FIXME. */
+extern void config_obj_elf_c_finalize (void);
+
+/* Reset all global state within this source file. */
+
+void
+config_obj_elf_c_finalize (void)
+{
+ obj_elf_ident_comment_section = NULL;
+ /* TODO: anything else? */
+}
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index db263ee..cbc6e13 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -10655,3 +10655,82 @@ handle_large_common (int small ATTRIBUTE_UNUSED)
}
}
#endif /* OBJ_ELF || OBJ_MAYBE_ELF */
+
+/* FIXME. */
+extern void config_tc_i386_c_finalize (void);
+
+/* Reset all global state within this source file. */
+
+void
+config_tc_i386_c_finalize (void)
+{
+#ifdef TE_LINUX
+ flag_compress_debug = COMPRESS_DEBUG_ZLIB;
+#endif
+ default_arch = DEFAULT_ARCH;
+ CLEAR_VAR (rc_op);
+ CLEAR_VAR (mask_op);
+ CLEAR_VAR (broadcast_op);
+ CLEAR_VAR (i);
+ current_templates = NULL;
+ CLEAR_VAR (disp_expressions);
+ CLEAR_VAR (im_expressions);
+ this_operand = -1;
+ flag_code = 0;
+ object_64bit = 0;
+ disallow_64bit_reloc = 0;
+ use_rela_relocations = 0;
+#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
+ || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \
+ || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O))
+ x86_elf_abi = I386_ABI;
+#endif
+#if defined (TE_PE) || defined (TE_PEP)
+ use_big_obj = 0;
+#endif
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ no_shared = 0;
+#endif
+ intel_syntax = 0;
+ intel_mnemonic = !SYSV386_COMPAT;
+ old_gcc = OLDGCC_COMPAT;
+ allow_pseudo_reg = 0;
+ allow_naked_reg = 0;
+ add_bnd_prefix = 0;
+ allow_index_reg = 0;
+ omit_lock_prefix = 0;
+ operand_check = check_warning;
+ register_prefix = "%";
+ stackop_size = '\0';
+ optimize_align_code = 1;
+ quiet_warnings = 0;
+ cpu_arch_name = NULL;
+ cpu_sub_arch_name = NULL;
+ //cpu_arch_flags = CPU_UNKNOWN_FLAGS;
+ cpu_arch_tune_set = 0;
+ cpu_arch_tune = PROCESSOR_UNKNOWN;
+ CLEAR_VAR (cpu_arch_tune_flags);
+ cpu_arch_isa = PROCESSOR_UNKNOWN;
+ CLEAR_VAR (cpu_arch_isa_flags);
+ no_cond_jump_promotion = 0;
+ sse2avx = 0;
+ avxscalar = 0;
+ evexlig = 0;
+ evexwig = 0;
+ evexrcig = rne;
+ GOT_symbol = NULL;
+ x86_dwarf2_return_column = 0;
+ x86_cie_data_alignment = 0;
+ input_line_pointer = NULL;
+ if (op_hash)
+ {
+ hash_die (op_hash);
+ op_hash = NULL;
+ }
+ if (reg_hash)
+ {
+ hash_die (reg_hash);
+ reg_hash= NULL;
+ }
+ cons_sign = -1;
+}
diff --git a/gas/depend.c b/gas/depend.c
index 1a1ec63..cc8a3e0 100644
--- a/gas/depend.c
+++ b/gas/depend.c
@@ -205,3 +205,13 @@ print_dependencies (void)
if (fclose (f))
as_warn (_("can't close `%s'"), dep_file);
}
+
+/* Reset all global state within depend.c. */
+
+void
+depend_c_finalize (void)
+{
+ dep_file = NULL;
+ dep_chain = NULL;
+ column = 0;
+}
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index ef97e18..1527624 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -2084,3 +2084,15 @@ cfi_finish (void)
{
}
#endif /* TARGET_USE_CFIPOP */
+
+/* Reset all global state within dw2gencfi.c. */
+
+void
+dw2gencfi_c_finalize (void)
+{
+ dwcfi_hash = NULL;
+ all_fde_data = NULL;
+ last_fde_data = &all_fde_data;
+ cie_root = NULL;
+ cfi_sections = CFI_EMIT_eh_frame;
+}
diff --git a/gas/dw2gencfi.h b/gas/dw2gencfi.h
index 6e2c50e..009eee3 100644
--- a/gas/dw2gencfi.h
+++ b/gas/dw2gencfi.h
@@ -133,4 +133,6 @@ extern struct fde_entry *all_fde_data;
#define CFI_val_encoded_addr 0x105
#define CFI_label 0x106
+extern void dw2gencfi_c_finalize (void);
+
#endif /* DW2GENCFI_H */
diff --git a/gas/libgas.h b/gas/libgas.h
new file mode 100644
index 0000000..479a990
--- /dev/null
+++ b/gas/libgas.h
@@ -0,0 +1,41 @@
+/* API for the GNU Assembler.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file is part of the GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#ifndef LIBGAS_H
+#define LIBGAS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ctimer;
+
+extern int
+gas_main (int argc,
+ char **argv,
+ int standalone,
+ struct ctimer *timer);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* ! defined (LIBGAS_H) */
diff --git a/gas/macro.c b/gas/macro.c
index 119b1bf..76e8fdf 100644
--- a/gas/macro.c
+++ b/gas/macro.c
@@ -1401,3 +1401,21 @@ expand_irp (int irpc, size_t idx, sb *in, sb *out, size_t (*get_line) (sb *))
return err;
}
+
+/* Reset all global state within macro.c. */
+
+void
+macro_c_finalize (void)
+{
+ if (macro_hash)
+ {
+ hash_die (macro_hash);
+ macro_hash = NULL;
+ }
+ macro_defined = 0;
+ macro_alternate = 0;
+ macro_mri = 0;
+ macro_strip_at = 0;
+ macro_expr = 0;
+ macro_number = 0;
+}
diff --git a/gas/macro.h b/gas/macro.h
index 46b1575..a0c48c3 100644
--- a/gas/macro.h
+++ b/gas/macro.h
@@ -93,4 +93,6 @@ extern int check_macro (const char *, sb *, const char **, macro_entry **);
extern void delete_macro (const char *);
extern const char *expand_irp (int, size_t, sb *, sb *, size_t (*) (sb *));
+extern void macro_c_finalize (void);
+
#endif
diff --git a/gas/output-file.c b/gas/output-file.c
index 94dbc2e..769bd43 100644
--- a/gas/output-file.c
+++ b/gas/output-file.c
@@ -71,3 +71,11 @@ output_file_close (char *filename)
as_fatal (_("can't close %s: %s"), filename,
bfd_errmsg (bfd_get_error ()));
}
+
+/* Reset all global state within output-file.c. */
+
+void
+output_file_c_finalize (void)
+{
+ stdoutput = NULL;
+}
diff --git a/gas/output-file.h b/gas/output-file.h
index bfba284..3e8d848 100644
--- a/gas/output-file.h
+++ b/gas/output-file.h
@@ -21,5 +21,6 @@
void output_file_append (char *where, long length, char *filename);
void output_file_close (char *filename);
void output_file_create (char *name);
+void output_file_c_finalize (void);
/* end of output-file.h */
diff --git a/gas/read.c b/gas/read.c
index 2224c0e..d49b122 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -6170,3 +6170,50 @@ find_end_of_line (char *s, int mri_string)
{
return _find_end_of_line (s, mri_string, 0, 0);
}
+
+/* Reset all global state within read.c. */
+
+void
+read_c_finalize (void)
+{
+ input_line_pointer = NULL;
+ /* FIXME: char lex_type[256] = { */
+ /* FIXME:char is_end_of_line[256] = { */
+#ifndef TC_CASE_SENSITIVE
+ CLEAR_VAR (original_case_string);
+#endif
+ buffer = NULL;
+ buffer_limit = NULL;
+ target_big_endian = TARGET_BYTES_BIG_ENDIAN;
+ include_dirs = NULL;
+ include_dir_count = 0;
+ include_dir_maxlen = 1;
+#ifndef WORKING_DOT_WORD
+ broken_words = NULL;
+ new_broken_words = 0;
+#endif
+ abs_section_offset = 0;
+ line_label = NULL;
+ mri_common_symbol = NULL;
+ mri_pending_align = 0;
+#ifndef NO_LISTING
+#ifdef OBJ_ELF
+ dwarf_file_string = 0;
+#endif
+#endif
+#ifdef HANDLE_BUNDLE
+ bundle_align_p2 = 0;
+ bundle_lock_frag = NULL;
+ bundle_lock_frchain = NULL;
+ bundle_lock_depth = 0;
+#endif
+ if (po_hash)
+ {
+ hash_die (po_hash);
+ po_hash = NULL;
+ }
+ pop_override_ok = 0;
+ pop_table_name = NULL;
+ scrub_string = NULL;
+ scrub_string_end = NULL;
+}
diff --git a/gas/read.h b/gas/read.h
index d7ac6ce..7d17a7a 100644
--- a/gas/read.h
+++ b/gas/read.h
@@ -198,3 +198,5 @@ extern void s_xstab (int what);
extern void s_rva (int);
extern void s_incbin (int);
extern void s_weakref (int);
+
+extern void read_c_finalize (void);
diff --git a/gas/subsegs.c b/gas/subsegs.c
index 4e422de..331ec29 100644
--- a/gas/subsegs.c
+++ b/gas/subsegs.c
@@ -325,4 +325,14 @@ subsegs_print_statistics (FILE *file)
}
}
+/* Reset all global state within subsegs.c. */
+
+void
+subsegs_c_finalize (void)
+{
+ frchain_now = NULL;
+ obstack_free (&frchains, 0);
+ CLEAR_VAR (dummy_frag);
+}
+
/* end of subsegs.c */
diff --git a/gas/subsegs.h b/gas/subsegs.h
index 82837a3..78e5b2f 100644
--- a/gas/subsegs.h
+++ b/gas/subsegs.h
@@ -117,3 +117,4 @@ typedef struct segment_info_struct {
extern symbolS *section_symbol (segT);
extern void subsegs_print_statistics (FILE *);
+extern void subsegs_c_finalize (void);
diff --git a/gas/symbols.c b/gas/symbols.c
index 07362bb..d660d53 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -3248,3 +3248,44 @@ symbol_relc_make_expr (expressionS * exp)
}
#endif
+
+/* Reset all global state within symbols.c. */
+
+void
+symbols_c_finalize (void)
+{
+ symbols_case_sensitive = 1;
+ if (sy_hash)
+ {
+ hash_die (sy_hash);
+ sy_hash = NULL;
+ }
+ if (local_hash)
+ {
+ hash_die (local_hash);
+ local_hash = NULL;
+ }
+ symbol_rootP = NULL;
+ symbol_lastP = NULL;
+ CLEAR_VAR (abs_symbol);
+ CLEAR_VAR (dot_symbol);
+ obstack_free (¬es, 0);
+ CLEAR_VAR (notes);
+#ifdef TE_PE
+ an_external_name = NULL;
+#endif
+ local_symbol_count = 0;
+ local_symbol_conversion_count = 0;
+ dollar_labels = NULL;
+ dollar_label_instances = NULL;
+ dollar_label_defines = NULL;
+ dollar_label_count = 0;
+ dollar_label_max = 0;
+ CLEAR_VAR (fb_low_counter);
+ fb_labels = NULL;
+ fb_label_instances = NULL;
+ fb_label_count = 0;
+ fb_label_max = 0;
+ indent_level = 0;
+ max_indent_level = 8;
+}
diff --git a/gas/symbols.h b/gas/symbols.h
index cf4f30f..8a88383 100644
--- a/gas/symbols.h
+++ b/gas/symbols.h
@@ -213,3 +213,5 @@ void symbol_set_obj (symbolS *, OBJ_SYMFIELD_TYPE *);
TC_SYMFIELD_TYPE *symbol_get_tc (symbolS *);
void symbol_set_tc (symbolS *, TC_SYMFIELD_TYPE *);
#endif
+
+extern void symbols_c_finalize (void);
diff --git a/gas/write.c b/gas/write.c
index bc76962..9562a7b 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -2907,3 +2907,18 @@ print_fixup (fixS *fixp)
TC_FIX_DATA_PRINT (stderr, fixp);
#endif
}
+
+/* Reset all global state within write.c. */
+
+void
+write_c_finalize (void)
+{
+ finalize_syms = 0;
+ symbol_table_frozen = 0;
+ abs_section_sym = NULL;
+ dot_value = 0;
+ dot_frag = NULL;
+ reloc_list = NULL;
+ frags_chained = 0;
+ n_fixups = 0;
+}
diff --git a/gas/write.h b/gas/write.h
index e0b5b36..63026f9 100644
--- a/gas/write.h
+++ b/gas/write.h
@@ -184,5 +184,6 @@ extern fixS *fix_new_exp
(fragS * frag, int where, int size, expressionS *exp, int pcrel,
bfd_reloc_code_real_type r_type);
extern void write_print_statistics (FILE *);
+extern void write_c_finalize (void);
#endif /* __write_h__ */
--
1.8.5.3