OSDN Git Service

Initial revision
authorrth <rth>
Mon, 3 May 1999 07:29:06 +0000 (07:29 +0000)
committerrth <rth>
Mon, 3 May 1999 07:29:06 +0000 (07:29 +0000)
257 files changed:
binutils/ChangeLog [new file with mode: 0644]
binutils/Makefile.am [new file with mode: 0644]
binutils/Makefile.in [new file with mode: 0644]
binutils/NEWS [new file with mode: 0644]
binutils/README [new file with mode: 0644]
binutils/acinclude.m4 [new file with mode: 0644]
binutils/aclocal.m4 [new file with mode: 0644]
binutils/addr2line.1 [new file with mode: 0644]
binutils/addr2line.c [new file with mode: 0644]
binutils/ar.1 [new file with mode: 0644]
binutils/ar.c [new file with mode: 0644]
binutils/arlex.l [new file with mode: 0644]
binutils/arparse.y [new file with mode: 0644]
binutils/arsup.c [new file with mode: 0644]
binutils/arsup.h [new file with mode: 0644]
binutils/binutils.texi [new file with mode: 0644]
binutils/bucomm.c [new file with mode: 0644]
binutils/bucomm.h [new file with mode: 0644]
binutils/budbg.h [new file with mode: 0644]
binutils/coffdump.c [new file with mode: 0644]
binutils/coffgrok.c [new file with mode: 0644]
binutils/coffgrok.h [new file with mode: 0644]
binutils/config.in [new file with mode: 0644]
binutils/configure [new file with mode: 0755]
binutils/configure.bat [new file with mode: 0755]
binutils/configure.com [new file with mode: 0644]
binutils/configure.in [new file with mode: 0644]
binutils/cxxfilt.man [new file with mode: 0644]
binutils/debug.c [new file with mode: 0644]
binutils/debug.h [new file with mode: 0644]
binutils/deflex.l [new file with mode: 0644]
binutils/defparse.y [new file with mode: 0644]
binutils/dep-in.sed [new file with mode: 0644]
binutils/dlltool.c [new file with mode: 0644]
binutils/dlltool.h [new file with mode: 0644]
binutils/dllwrap.c [new file with mode: 0644]
binutils/dyn-string.c [new file with mode: 0644]
binutils/dyn-string.h [new file with mode: 0644]
binutils/filemode.c [new file with mode: 0644]
binutils/ieee.c [new file with mode: 0644]
binutils/is-ranlib.c [new file with mode: 0644]
binutils/is-strip.c [new file with mode: 0644]
binutils/mac-binutils.r [new file with mode: 0644]
binutils/makefile.vms-in [new file with mode: 0644]
binutils/maybe-ranlib.c [new file with mode: 0644]
binutils/maybe-strip.c [new file with mode: 0644]
binutils/mpw-config.in [new file with mode: 0644]
binutils/mpw-make.sed [new file with mode: 0644]
binutils/nlmconv.1 [new file with mode: 0644]
binutils/nlmconv.c [new file with mode: 0644]
binutils/nlmconv.h [new file with mode: 0644]
binutils/nlmheader.y [new file with mode: 0644]
binutils/nm.1 [new file with mode: 0644]
binutils/nm.c [new file with mode: 0644]
binutils/not-ranlib.c [new file with mode: 0644]
binutils/not-strip.c [new file with mode: 0644]
binutils/objcopy.1 [new file with mode: 0644]
binutils/objcopy.c [new file with mode: 0644]
binutils/objdump.1 [new file with mode: 0644]
binutils/objdump.c [new file with mode: 0644]
binutils/po/Make-in [new file with mode: 0644]
binutils/po/POTFILES.in [new file with mode: 0644]
binutils/po/binutils.pot [new file with mode: 0644]
binutils/prdbg.c [new file with mode: 0644]
binutils/ranlib.1 [new file with mode: 0644]
binutils/ranlib.sh [new file with mode: 0755]
binutils/rclex.l [new file with mode: 0644]
binutils/rcparse.y [new file with mode: 0644]
binutils/rdcoff.c [new file with mode: 0644]
binutils/rddbg.c [new file with mode: 0644]
binutils/readelf.c [new file with mode: 0644]
binutils/rename.c [new file with mode: 0644]
binutils/resbin.c [new file with mode: 0644]
binutils/rescoff.c [new file with mode: 0644]
binutils/resrc.c [new file with mode: 0644]
binutils/resres.c [new file with mode: 0644]
binutils/sanity.sh [new file with mode: 0755]
binutils/size.1 [new file with mode: 0644]
binutils/size.c [new file with mode: 0644]
binutils/srconv.c [new file with mode: 0644]
binutils/stabs.c [new file with mode: 0644]
binutils/stamp-h.in [new file with mode: 0644]
binutils/strings.1 [new file with mode: 0644]
binutils/strings.c [new file with mode: 0644]
binutils/strip.1 [new file with mode: 0644]
binutils/sysdump.c [new file with mode: 0644]
binutils/sysinfo.y [new file with mode: 0644]
binutils/syslex.l [new file with mode: 0644]
binutils/sysroff.info [new file with mode: 0644]
binutils/testsuite/ChangeLog [new file with mode: 0644]
binutils/testsuite/binutils-all/ar.exp [new file with mode: 0644]
binutils/testsuite/binutils-all/bintest.s [new file with mode: 0644]
binutils/testsuite/binutils-all/hppa/addendbug.s [new file with mode: 0644]
binutils/testsuite/binutils-all/hppa/objdump.exp [new file with mode: 0644]
binutils/testsuite/binutils-all/nm.exp [new file with mode: 0644]
binutils/testsuite/binutils-all/objcopy.exp [new file with mode: 0644]
binutils/testsuite/binutils-all/objdump.exp [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.exp [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.h [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.r [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.s [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.ss [new file with mode: 0644]
binutils/testsuite/binutils-all/readelf.wi [new file with mode: 0644]
binutils/testsuite/binutils-all/size.exp [new file with mode: 0644]
binutils/testsuite/binutils-all/testprog.c [new file with mode: 0644]
binutils/testsuite/config/default.exp [new file with mode: 0644]
binutils/testsuite/config/hppa.sed [new file with mode: 0644]
binutils/testsuite/lib/utils-lib.exp [new file with mode: 0644]
binutils/version.c [new file with mode: 0644]
binutils/windres.c [new file with mode: 0644]
binutils/windres.h [new file with mode: 0644]
binutils/winduni.c [new file with mode: 0644]
binutils/winduni.h [new file with mode: 0644]
binutils/wrstabs.c [new file with mode: 0644]
config/ChangeLog [new file with mode: 0644]
config/acinclude.m4 [new file with mode: 0755]
config/mh-a68bsd [new file with mode: 0644]
config/mh-aix386 [new file with mode: 0644]
config/mh-aix43 [new file with mode: 0644]
config/mh-apollo68 [new file with mode: 0644]
config/mh-armpic [new file with mode: 0644]
config/mh-cxux [new file with mode: 0644]
config/mh-cygwin [new file with mode: 0644]
config/mh-decstation [new file with mode: 0644]
config/mh-delta88 [new file with mode: 0644]
config/mh-dgux [new file with mode: 0644]
config/mh-dgux386 [new file with mode: 0644]
config/mh-djgpp [new file with mode: 0644]
config/mh-elfalphapic [new file with mode: 0644]
config/mh-hp300 [new file with mode: 0644]
config/mh-hpux [new file with mode: 0644]
config/mh-hpux8 [new file with mode: 0644]
config/mh-interix [new file with mode: 0644]
config/mh-irix4 [new file with mode: 0644]
config/mh-irix5 [new file with mode: 0644]
config/mh-irix6 [new file with mode: 0644]
config/mh-lynxos [new file with mode: 0644]
config/mh-lynxrs6k [new file with mode: 0644]
config/mh-m68kpic [new file with mode: 0644]
config/mh-mingw32 [new file with mode: 0644]
config/mh-ncr3000 [new file with mode: 0644]
config/mh-ncrsvr43 [new file with mode: 0644]
config/mh-necv4 [new file with mode: 0644]
config/mh-papic [new file with mode: 0644]
config/mh-ppcpic [new file with mode: 0644]
config/mh-riscos [new file with mode: 0644]
config/mh-sco [new file with mode: 0644]
config/mh-solaris [new file with mode: 0644]
config/mh-sparcpic [new file with mode: 0644]
config/mh-sun3 [new file with mode: 0644]
config/mh-sysv [new file with mode: 0644]
config/mh-sysv4 [new file with mode: 0644]
config/mh-sysv5 [new file with mode: 0644]
config/mh-vaxult2 [new file with mode: 0644]
config/mh-x86pic [new file with mode: 0644]
config/mpw-mh-mpw [new file with mode: 0644]
config/mpw/ChangeLog [new file with mode: 0644]
config/mpw/MoveIfChange [new file with mode: 0644]
config/mpw/README [new file with mode: 0644]
config/mpw/forward-include [new file with mode: 0644]
config/mpw/g-mpw-make.sed [new file with mode: 0644]
config/mpw/mpw-touch [new file with mode: 0644]
config/mpw/mpw-true [new file with mode: 0644]
config/mpw/null-command [new file with mode: 0644]
config/mpw/open-brace [new file with mode: 0644]
config/mpw/tr-7to8-src [new file with mode: 0644]
config/mpw/true [new file with mode: 0644]
config/mt-armpic [new file with mode: 0644]
config/mt-d30v [new file with mode: 0644]
config/mt-elfalphapic [new file with mode: 0644]
config/mt-linux [new file with mode: 0644]
config/mt-m68kpic [new file with mode: 0644]
config/mt-netware [new file with mode: 0644]
config/mt-ospace [new file with mode: 0644]
config/mt-papic [new file with mode: 0644]
config/mt-ppcpic [new file with mode: 0644]
config/mt-sparcpic [new file with mode: 0644]
config/mt-v810 [new file with mode: 0644]
config/mt-x86pic [new file with mode: 0644]
etc/ChangeLog [new file with mode: 0644]
etc/Makefile.in [new file with mode: 0644]
etc/add-log.el [new file with mode: 0644]
etc/add-log.vi [new file with mode: 0644]
etc/configbuild.ein [new file with mode: 0644]
etc/configbuild.fig [new file with mode: 0644]
etc/configbuild.jin [new file with mode: 0644]
etc/configbuild.tin [new file with mode: 0644]
etc/configdev.ein [new file with mode: 0644]
etc/configdev.fig [new file with mode: 0644]
etc/configdev.jin [new file with mode: 0644]
etc/configdev.tin [new file with mode: 0644]
etc/configure [new file with mode: 0755]
etc/configure.in [new file with mode: 0644]
etc/configure.texi [new file with mode: 0644]
etc/make-stds.texi [new file with mode: 0644]
etc/standards.texi [new file with mode: 0644]
gprof/.gdbinit [new file with mode: 0644]
gprof/ChangeLog [new file with mode: 0644]
gprof/Makefile.am [new file with mode: 0644]
gprof/Makefile.in [new file with mode: 0644]
gprof/NOTES [new file with mode: 0644]
gprof/TEST [new file with mode: 0644]
gprof/TODO [new file with mode: 0644]
gprof/aclocal.m4 [new file with mode: 0644]
gprof/alpha.c [new file with mode: 0644]
gprof/basic_blocks.c [new file with mode: 0644]
gprof/basic_blocks.h [new file with mode: 0644]
gprof/bb_exit_func.c [new file with mode: 0644]
gprof/bbconv.pl [new file with mode: 0755]
gprof/bsd_callg_bl.m [new file with mode: 0644]
gprof/call_graph.c [new file with mode: 0644]
gprof/call_graph.h [new file with mode: 0644]
gprof/cg_arcs.c [new file with mode: 0644]
gprof/cg_arcs.h [new file with mode: 0644]
gprof/cg_dfn.c [new file with mode: 0644]
gprof/cg_dfn.h [new file with mode: 0644]
gprof/cg_print.c [new file with mode: 0644]
gprof/cg_print.h [new file with mode: 0644]
gprof/configure [new file with mode: 0755]
gprof/configure.bat [new file with mode: 0644]
gprof/configure.in [new file with mode: 0644]
gprof/corefile.c [new file with mode: 0644]
gprof/corefile.h [new file with mode: 0644]
gprof/flat_bl.m [new file with mode: 0644]
gprof/fsf_callg_bl.m [new file with mode: 0644]
gprof/gconfig.in [new file with mode: 0644]
gprof/gen-c-prog.awk [new file with mode: 0644]
gprof/gmon.h [new file with mode: 0644]
gprof/gmon_io.c [new file with mode: 0644]
gprof/gmon_io.h [new file with mode: 0644]
gprof/gmon_out.h [new file with mode: 0644]
gprof/gprof.1 [new file with mode: 0644]
gprof/gprof.c [new file with mode: 0644]
gprof/gprof.h [new file with mode: 0644]
gprof/gprof.texi [new file with mode: 0644]
gprof/hertz.c [new file with mode: 0644]
gprof/hertz.h [new file with mode: 0644]
gprof/hist.c [new file with mode: 0644]
gprof/hist.h [new file with mode: 0644]
gprof/i386.c [new file with mode: 0644]
gprof/po/Make-in [new file with mode: 0644]
gprof/po/POTFILES.in [new file with mode: 0644]
gprof/po/gprof.pot [new file with mode: 0644]
gprof/search_list.c [new file with mode: 0644]
gprof/search_list.h [new file with mode: 0644]
gprof/source.c [new file with mode: 0644]
gprof/source.h [new file with mode: 0644]
gprof/sparc.c [new file with mode: 0644]
gprof/stamp-h.in [new file with mode: 0644]
gprof/sym_ids.c [new file with mode: 0644]
gprof/sym_ids.h [new file with mode: 0644]
gprof/symtab.c [new file with mode: 0644]
gprof/symtab.h [new file with mode: 0644]
gprof/tahoe.c [new file with mode: 0644]
gprof/utils.c [new file with mode: 0644]
gprof/utils.h [new file with mode: 0644]
gprof/vax.c [new file with mode: 0644]

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
new file mode 100644 (file)
index 0000000..b8a3d27
--- /dev/null
@@ -0,0 +1,6404 @@
+1999-04-26  Tom Tromey  <tromey@cygnus.com>
+
+       * aclocal.m4, configure: Updated for new version of libtool.
+
+1999-04-18  Ian Lance Taylor  <ian@zembu.com>
+
+       * stabs.c (parse_stab_range_type): Correct parenthesization in
+       BFD64 case.
+
+       * readelf.c (get_section_type_name): Use correct types in printf
+       formats.
+       (process_relocs): Likewise.
+       (process_dynamic_segment): Likewise.
+       (process_symbol_table): Likewise.
+       (process_mips_specific): Likewise.
+
+Tue Apr 13 21:22:00 1999  Catherine Moore  <clm@cygnus.com>
+
+       * dlltool.c (make_one_lib_file): Mark thumb functions as
+       C_THUMBEXTFUNC.
+
+1999-04-11  Richard Henderson  <rth@cygnus.com>
+
+       * bucomm.h (environ): Declare it, if needed.
+       (alloca) [C_ALLOCA]: Don't use gcc's builtin or <alloca.h>.
+       * configure.in (environ): Detect declaration.
+       * nm.c (main): Don't declare environ.
+       * configure, config.in: Rebuild.
+
+       * dlltool.c (gen_exp_file): Pad out the .reloc section to a
+       32-byte boundary with dummy relocations, to make the BeOS loader
+       happy.  Patch from Bob Manson <manson@charmed.cygnus.com>.
+
+1999-04-08  Tom Tromey  <tromey@cygnus.com>
+
+       * binutils.texi (c++filt): Updated for -j/--java, and hp/edg
+       formats.
+
+1999-04-08  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c: Add ability to decode new constants found in April 25
+       1998 Draft of System V ABI spec.
+
+1999-04-06  Ian Lance Taylor  <ian@zembu.com>
+
+       * bucomm.h (LC_MESSAGES): Never define.
+       * addr2line.c (main): Don't pass LC_MESSAGES to setlocale if the
+       system does not define it.
+       * ar.c (main): Likewise.
+       * coffdump.c (main): Likewise.
+       * dlltool.c (main): Likewise.
+       * nlmconv.c (main): Likewise.
+       * nm.c (main): Likewise.
+       * objcopy.c (main): Likewise.
+       * objdump.c (main): Likewise.
+       * size.c (main): Likewise.
+       * srconv.c (main): Likewise.
+       * strings.c (main): Likewise.
+       * sysdump.c (main): Likewise.
+       * windres.c (main): Likewise.
+       * readelf.c (main): Call locale setting functions.
+
+1999-04-05  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (decode_location_expression): Fix DW_OP_const8{s|u}
+       decodes. 
+
+1999-04-04  Ian Lance Taylor  <ian@zembu.com>
+
+       * rename.c: New file, copied out of objcopy.c with a few changes.
+       * bucomm.h (set_times, smart_rename): Declare.
+       * ar.c: Don't include <utime.h>.
+       (extract_file): Call set_times rather than utime.
+       (write_archive): Call smart_rename rather than unlink and rename.
+       * objcopy.c: Don't include <utime.h>.
+       (simple_copy, smart_rename, set_times): Move to rename.c.
+       (strip_main): Update smart_rename call for new parameter.
+       (copy_main): Likewise.
+       * Makefile.am: Rebuild dependencies.
+       (CFILES): Add rename.c.
+       (objcopy_SOURCES, strip_new_SOURCES): Add rename.c.
+       (ar_SOURCES, ranlib_SOURCES): Add rename.c.
+       * Makefile.in: Rebuild.
+
+       * Makefile.am: Rebuild dependencies.
+       (EXTRA_PROGRAMS): Remove backslash which troubles current version
+       of automake.
+       * Makefile.in: Rebuild.
+
+       * dllwrap.c (main): Expect correct type in format string.
+       * resres.c: Include "bfd.h", "bucomm.h", "libiberty.h", and
+       <time.h>.  Don't include <stdio.h> and <errno.h>.
+       (write_res_file): Remove unused locals e and i.
+       (read_resource_entry): Remove unused locals rtype and n.
+       (read_unistring): Remove unused local n.
+
+1999-04-03  Ian Lance Taylor  <ian@zembu.com>
+
+       * arparse.y: Declare yylex.
+       * objdump.c (disassemble_bytes): Initialize bytes.  Add comment
+       for incorrect use of bytes.
+       * readelf.c: Change many formats to avoid warnings.
+
+1999-04-01  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (reset_state_machine): New function.  Resets the
+       registers of the source line number state machine.
+       (process_extended_line_op): Use state machine.
+       (display_debug_lines): Use state machine.  Handle multiple line
+       number blocks within the same section.
+
+1999-03-29  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * readelf.c (process_extended_line_op): end_sequence also resets
+       the line number.
+       (display_debug_lines): advance_line takes a signed operand.
+       (read_and_display_attr): Print refs as <%x>, addresses as %#x,
+       others as %d.  Handle other location expression attributes.
+       (display_debug_info): Handle nesting.  Always print the offset.
+
+1999-03-23  Ian Lance Taylor  <ian@zembu.com>
+
+       * objcopy.c (filter_symbols): When checking whether to keep a
+       symbol, check the BFD section symbol for a symbol with
+       BSF_SECTION_SYM set.
+
+1999-03-10  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (process_dynamic_segment): Print new Solaris dynamic
+       section entries.  Correct printing of DT_POSFLAG_1 and DT_FLAGS_1.
+
+1999-03-10  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (request_dump): New function.
+       Removed arbitary limit on the number of sections that can be
+       dumped.
+
+Wed Mar 10 15:10:14 1999  Stan Cox  <scox@cygnus.com>
+
+       * dlltool.c (make_one_lib_file): Use %05d to output the stub name so
+       order in the import library is preserved.
+
+1999-02-19  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c: Fix compile time warings.
+
+1999-02-17  DJ Delorie  <dj@cygnus.com>
+
+        * resbin.c (res_to_bin_versioninfo): Instead of entering a value
+       length of zero in a version info string, enter the appropriate
+       length.
+
+Tue Feb 16 16:00:33 1999  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Require autoconf 2.13.  Change AM_PROG_INSTALL to
+       AC_PROG_INSTALL.  Add comments for AC_DEFINE calls.
+       * acconfig.h: Remove.
+       * aclocal.m4: Rebuild.
+       * configure: Rebuild.
+       * Makefile.in: Rebuild.
+       * config.in: Rebuild.
+
+1999-02-02  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (read_and_display_attr): Add display of basic type
+       encodings.
+       (display_debug_aranges): New function: Display the contents of a
+       .debug_aranges section.
+       (display_debug_info): Dump tags found after compunit entry.
+
+       * binutils.texi: Fixed bug in readelf documentation.
+
+Mon Feb  1 12:38:01 1999  Catherine Moore  <clm@cygnus.com>
+
+        * readelf.c (dump_relocations):  Handle EM_ARM as REL.
+
+1999-01-29  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (process_symbol_table): Do not produce a histogram of
+       bucket chains if none were found.
+
+1999-01-27  Nick Clifton  <nickc@cygnus.com>
+
+       * version.c: Add 1999 copyright.
+
+       * binutils.texi (readelf): Document new command line options
+       --debug-dump and --histogram.
+
+       * readelf.c: Add ability to display contents of some or all of the
+       Dwarf2 debug sections.  {Work only partially completed}.
+       (display_debug_section): New function.
+       (display_debug_info): New function.
+       (display_debug_not_supported): New function.
+       (display_debug_line): New function.
+       (display_debug_abbrev): New function.
+       (process_abbrev_section): New function.
+       (read_leb128): New function.
+       (process_extended_line_op): New function.
+       (get_TAG_name): New function.
+       (get_AT_name): New function.
+       (get_FORM_name): New function.
+       (free_abbrevs): New function.
+       (add_abbrev): New function.
+       (add_abbrev_attr): New function.
+       (read_and_display_attr): New function.
+       (display_block): New function.
+
+Thu Jan 14 23:36:11 1999  Jeffrey A Law  (law@cygnus.com)
+
+       * coffdump.c (xcalloc): Remove, in libiberty now.
+       * srconv.c (xcalloc): Likewise.
+       * sysdump.c (xcalloc): Likewise.
+
+1999-01-14  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (process_section_headers): Omit trailing space at end
+       of section header contents line.
+
+Wed Dec 16 17:20:05 1998  Doug Evans  <devans@canuck.cygnus.com>
+
+       * aclocal.m4: Regenerate.
+
+Mon Dec 14 12:55:36 1998  Jim Wilson  <wilson@cygnus.com>
+
+       * dllwrap.c: Include bfd.h and bucomm.h.  Move getopt.h include
+       after libiberty.h include.
+
+Tue Dec  8 16:29:43 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.1: Fix typo (-d to -D).  From Nokubi Hirotaka
+       <hnokubi@yyy.or.jp>.
+
+Sun Dec  6 13:28:09 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (SFILE): Add size field.
+       (objdump_sprintf): Merge both versions into one.  Increase buffer
+       size as needed to avoid overflow.
+       (disassemble_bytes): Change buf from 1000 bytes to 50.  Change
+       initialization and use of sfile to match changes to
+       objdump_sprintf.
+
+       * strip.1: Fix typo (-V to -v).  From Issei Hirayama
+       <iss@mail.wbs.or.jp>.
+
+1998-12-03  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (process_dynamic_segment): Improve output format for
+       various DT_* values.
+
+1998-12-02  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (process_mips_specific): Print .conflict section
+       content.
+
+       * readelf.c (process_mips_specific): Print l_flags in liblist in
+       textual form.
+
+1998-11-30  Nick Clifton  <nickc@cygnus.com>
+
+       * ar.c (extract_file): Add some paranoia checks for negatively
+       sized files.
+
+Tue Nov 24 09:39:24 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * stabs.c (DIR_SEPARATOR): Define as '\\' if WIN32 is defined.
+
+Tue Nov 17 10:25:26 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * Makefile.in: Regenerate.
+
+Mon Nov 16 19:17:23 1998  Dave Brolley  <brolley@cygnus.com>
+
+       * po/binutils.pot: Regenerate.
+
+Mon Nov 16 10:18:53 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * Makefile.am: Regernated dependencies.
+       * aclocal.m4: Regenerated.
+       * configure: Regenerated.
+
+Sat Nov 14 14:50:56 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * debug.c (debug_name_type): Correct return type from false to
+       DEBUG_TYPE_NULL.
+
+Sat Nov 14 14:48:21 1998  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>
+
+       * objdump.c (disassemble_data): Skip over relocs below start
+       address.
+
+Tue Nov 10 15:31:52 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * Makefile.am: Add dependency of readelf.c on elf/fr30.h
+       * Makefile.in: Regenerate.
+
+Wed Nov  4 16:25:55 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c: Add support for the FR30.
+
+Mon Nov  2 14:59:33 1998  Geoffrey Noer  <noer@cygnus.com>
+
+        * configure.in: detect cygwin* instead of cygwin32*
+        * configure: regenerate
+
+Fri Oct 30 15:14:49 1998  Geoffrey Noer  <noer@cygnus.com>
+
+        * dllwrap.c: change all references to cygwin32_ to cygwin_,
+       change Cygwin target def to CYGWIN.
+
+Wed Oct 28 10:31:19 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * objdump.c (disassemble_data): Replace 'unsigned long' with
+       'bfd_vma'.
+
+Tue Oct 27 14:39:00 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * objdump.c (disassemble_bytes): Applied this patch from Philip
+       Blundell <pb@nexus.co.uk>:  Make address variables unsigned to
+       avoid problems when disassembling code at high-bit-set addresses.
+
+Mon Oct 26 14:07:59 1998  Mumit Khan  <khan@xraylith.wisc.edu>
+
+        * dllwrap.c (strhash): New function.
+        (main): Use it to supply image base if not supplied by user.
+        (program_version): Up to 0.2.4.
+
+Mon Oct 26 14:07:59 1998  Mumit Khan  <khan@xraylith.wisc.edu>
+
+        * dlltool.c (add_stdcall_alias): New global.
+        (long_options): Add --add-stdcall-alias option.
+        (main): Handle it.
+        (scan_drectve_symbols): Add alias if --add-stdcall-alias is
+        specified.
+        (scan_filtered_symbols): Likewise.
+        (gen_def_file): Output alias for stdcall syms if appropriate.
+
+        * binutils.texi (dlltool): Document --add-stdcall-alias option.
+
+        * dllwrap.c (long_options): Add --add-stdcall-alias option.
+        (main): Handle it.
+
+        * defparse.y (opt_name): Allow "." in name.
+        * dlltool.c (def_name): Set dll_name from NAME entry in def file.
+        (def_library): Set dll_name from LIBRARY entry in def file.
+
+Mon Oct 26 14:07:59 1998  Mumit Khan  <khan@xraylith.wisc.edu>
+
+        * dllwrap.c (long_options): --implib synonym for --output-lib.
+        (main): Pass --export-all to dlltool only if specified.
+        (program_version): Up to 0.2.3.
+
+Mon Oct 26 14:07:59 1998  Mumit Khan  <khan@xraylith.wisc.edu>
+
+        * dllwrap.c (mybasename): New function.
+        (main): Run dlltool to create export definition file and import
+        library file if necessary.
+        Change exp_file_name so that it's based on the dll name.
+
+Sun Oct 25 10:37:45 1998  Mumit Khan  <khan@xraylith.wisc.edu>
+
+        * dlltool.c (scan_all_symbols): Fix patch error.
+
+Fri Oct 16 22:56:20 1998  Felix Lee  <flee@cygnus.com>
+
+       * nm.c (display_rel_file): fix "no symbols" messages.
+       * objdump.c (slurp_symtab): ditto.
+       * po/POTFILES.in, po/binutils.pot: rebuilt
+
+Mon Oct 12 14:28:03 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (dump_relocations): Rename field from Value to Info to
+       match name of field in ELF structures.
+
+Thu Oct  8 15:33:08 1998  Geoffrey Noer  <noer@cygnus.com>
+
+       * configure.in: call AC_EXEEXT instead of AM_EXEEXT and
+       AM_CYGWIN32.
+       * aclocal.m4: remove local AM_EXEEXT/AM_CYGWIN32 macros.
+       * configure: regenerate
+
+Thu Oct  8 15:33:08 1998  Geoffrey Noer  <noer@cygnus.com>
+
+       From Mumit Khan  <khan@xraylith.wisc.edu>:
+        * dlltool.c (scan_all_symbols): Don't re-export symbols exported
+        by other DLLs.
+
+Thu Oct  8 15:33:08 1998  Geoffrey Noer  <noer@cygnus.com>
+
+       * Makefile.am (BUILD_DLLWRAP): Add.
+       (BUILD_DLLWRAP, DLLWRAP_PROG): Add.
+       (bin_PROGRAMS): Add dllwrap.
+       * Makefile.in: regenerate with automake
+
+       From Mumit Khan  <khan@xraylith.wisc.edu>:
+        * dllwrap.c: New file from dllhelpers v0.2.1.
+       (print_version): New function.
+       (long_options): Add --version.
+       (main): Handle.
+        * dyn-string.h, dyn-string.c: New files from egcs-1.1/gcc.
+        * configure.in (BUILD_DLLWRAP): Add.
+        * configure: Regenerate.
+
+Tue Oct  6 18:20:10 1998  Geoffrey Noer  <noer@cygnus.com>
+
+       * Makefile.am (windres_SOURCES): Add resres.c.
+       (windres_OBJECTS): Add resres.o.
+       * Makefile.in: regenerate with automake
+
+        From Anders Norlander <anorland@hem2.passagen.se>.
+        * resres.c: New file.  Implementation of read_res_file and
+        write_res_file functions for windres.
+        * rcparse.y: Handle CONTROL's with named classes.
+        * resbin.c: Bug in res_to_bin_dialog and bin_to_res_dialog
+        when dialog is extended: The version and signature fields should
+        be reversed (despite what the docs say). Id is 32 bits long in
+        extended dialogs.
+        * resrc.c (write_rc_dialog): properly print controls with named
+        classes.
+        * windres.c (read_res_file, write_res_file): Remove stubs.
+        * resres.c (write_res): Rename RT_ACCELERATORS to RT_ACCELERATOR.
+
+Sun Oct  4 20:34:42 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       From Nokubi Hirotaka <hnokubi@yyy.or.jp>:
+       * objcopy.1: Fix typo in --remove-leading-char docs.
+       * objdump.1: Fix formatting in --stabs docs.
+
+Sat Sep 19 23:33:56 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * rcparse.y (memflags_move): Correct recursion.
+
+1998-09-10  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (process_symbol_table): Print in histogram how many
+       symbols are covered by the current chain length.
+
+Sun Sep  6 16:15:47 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (process_section_contents): Do not try to dump empty
+       sections.
+
+Sat Sep  5 19:17:10 1998  Mumit Khan  <khan@xraylith.wisc.edu>
+
+       * dlltool.c (scan_all_symbols): Don't re-export symbols exported
+       by other DLLs.
+
+1998-09-02 14:50  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (process_dynamic_segment): Print DT_* value only if
+       do_dynamic.
+       (do_histogram): New variable.
+       (options): New long option histogram.  Set do_histogram if this
+       option is used.
+       (usage): Document --histogram.
+       (parse_args): Handle 0 return value from getopt_long.  Enable
+       do_histogram for -a.
+       (process_symbol_table): Read hash table also if only do_histogram.
+       Add code to print hash table histogram.
+
+1998-08-25 16:45  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (process_dynamic_segment): Read syminfo section if
+       available.
+       (process_syminfo): New function.  Print syminfo information.
+       (process_file): Call process_syminfo and free syminfo data at the end.
+
+Wed Aug 19 16:19:51 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.c (usage): Add file parameter.  Change all callers.
+       (main): Don't treat '?' as a special case in getopt return.
+
+       * binutils.texi (dlltool): Document new options.  Add some uses of
+       @var.
+
+Wed Aug 19 16:19:07 1998  Mumit Khan  <khan@xraylith.wisc.edu>
+
+       * dlltool.c (gen_def_file): Plug memory leak.  Don't print
+       demangled name if it is NULL.
+
+       Support for exporting all symbols to an output export def file:
+       * dlltool.c ({export_all_symbols, no_default_excludes,
+       no_default_excludes, excludes}): New file static variables.
+       (struct string_list): Type to hold list of symbols to exclude.
+       (scan_drectve_symbols): Renamed from scan_open_obj_file.
+       (scan_filtered_symbols): New static function.
+       (add_excludes): New static function.
+       (match_exclude): New static function.
+       (set_default_excludes): New static function.
+       (filter_symbols): New static function.
+       (scan_all_symbols): New static function.
+       (scan_open_obj_file): New static function.
+       (usage): Document new options.
+       (long_options): Add new options.
+       (main): Handle new options.
+
+1998-07-31 21:24  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (process_program_headers): Print p_offset value with
+       six hex digits.
+       (dynamic_segment_mips_val): Add support for DT_MIPS_FLAGS,
+       DT_MIPS_IVERSION, and DT_MIPS_TIME_STAMP.
+       (process_mips_specific): Also print seconds of time stamp.
+
+Fri Jul 31 10:04:23 1998  Catherine Moore  <clm@cygnus.com>
+
+        * readelf.c (dump_relocations):  EM_ARM uses rela relocs.
+
+1998-07-30 16:25  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (get_dynamic_type): Don't used gettext on the names.
+       Add new DT_* values from Solaris.  Don't print nuemric value in
+       case of an unknown entry.
+       (process_dynamic_segment): Handle new DT_* entries.  Print numeric
+       values in decimal, not hex.
+
+Fri Jul 24 16:28:57 1998  Jeff Holcomb  <jeffh@cygnus.com>
+
+       * readelf.c (get_dynamic_type): Remove empty default from switch
+       statement.
+
+Fri Jul 24 16:28:12 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (install-exec-local): Don't remove the file before
+       checking whether $(bindir) == $(tooldir)/bin.  From Maciej
+       W. Rozycki <macro@ds2.pg.gda.pl>.
+       * Makefile.in: Rebuild.
+
+Fri Jul 24 09:38:59 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * objcopy.c: Removed spurious inclusion of elf/internal.h and
+       elf-bfd.h.
+
+1998-07-22  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c: Consistantly use elf_ prefix for *_reloc_type
+       functions.
+
+Wed Jul 22 16:29:12 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (dump_relocations): Add dumps of HPPA and ARC
+       relocations.
+
+       (process_relocs): Do not abort if no string table can be found.
+
+1998-07-22 14:58  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c: Remove definition of functions to return relocation
+       symbol strings.  They now get implicitly defined when include the
+       system specific ELF header.
+
+1998-07-22 13:51  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c: Before include system specific ELF header define
+       START_RELOC_NUMBERS, RELOC_NUMBER, and END_RELOC_NUMBERS.  For now
+       used for ppc, mips, and mn10300.
+
+Wed Jul 22 10:26:32 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (dump_relocations): Display number of unrecognised
+       relocations.
+
+1998-07-21 13:13  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c: Use symbolic names of relocation entries for the various
+       architectures.  Correct more layout details.
+       Print names of MIPS specific section types.  Print Alpha, ARM, and
+       MIPS relocation type names.
+
+1998-07-20  Vladimir N. Makarov  <vmakarov@cygnus.com>
+
+       * objcopy.c (filter_symbols): Add code for strip all symbols case.
+        (copy_objects): Strip all case is now processed also through
+       filter_symbols.  No marking symbols used in relocations when strip
+       all symbols case.
+       (copy_section): When strip all symbols case, remove relocations
+       which are not in keep strip specific list.
+       (strip_main): Remove guard `strip_specific_list == NULL' for
+       setting up strip all symbols by default.
+
+Mon Jul 20 12:51:16 1998  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * addr2line.c (find_address_in_section): Only consider a section
+       if the pc value is completely contained within it.
+       (translate_addresses): Don't crash if functionname or filename are
+       null.
+
+1998-07-20 07:45  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c (process_symbol_table): Fix little alignment problem
+       in printed table header.
+
+1998-07-20 07:14  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c: Correct reading of .dynamic section.
+       (dynamic_section): Now a global variable.
+       (process_mips_fpe_exception, process_mips_specific,
+       process_arch_specific): New functions.
+       (get_file_header): Call process_arch_specific.
+
+1998-07-19 15:15  Ulrich Drepper  <drepper@cygnus.com>
+
+       * readelf.c: Fix several versioning related bugs.  Produce nicer
+       output.
+       Add support for processor specific information on MIPS.
+
+Fri Jul 10 15:57:58 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c: Switch prototypes from unsigned short to unsigned
+       int.
+
+Fri Jul 10 16:17:50 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       From Christian Holland <CHolland@de.lucent.com>:
+       * ieee.c (parse_ieee): Initialize info.global_vars and
+       info.global_types.
+       (parse_ieee_atn): Ignore register lifetime information reportedly
+       emitted by MRI compiler.
+
+Thu Jul  9 13:08:01 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (MAINTAINERCLEANFILES): Define.
+       * Makefile.in: Rebuild.
+
+Tue Jul  7 21:48:54 1998  Jeffrey A Law  (law@cygnus.com)
+
+       * readelf.c (byte_get): Use PARAMS in prototype.
+       (error): Make it work with non-ANSI compilers.
+       (warn): Likewise.
+       (get_ver_flags): Don't use an ANSI prototype in the definition.
+
+Tue Jul  7 13:26:13 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (filter_bytes): Set size correctly if the size of the
+       section is not an even multiple of the interleave.  Based on patch
+       from Brion Stone <Brion.Stone@attws.com>.
+
+Thu Jul  2 14:01:34 1998  Klaus Kaempf  <kkaempf@rmi.de>
+
+       * configure.com: Add vax/vms support.
+       * makefile.vms-in: Renamed from makefile.vms.  Add substitutions
+       now done by configure.com.
+
+Wed Jul  1 20:43:52 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (parse_stab_range_type): Handle 4 and 8 byte signed
+       integers with real upper bounds.  Handle a lower bound one larger
+       than the upper bound as a signed integer.  Handle 8 byte signed
+       integers.
+       (stab_demangle_template): Optionally return the demangled name of
+       the template.
+       (stab_demangle_qualified): Treat a template name as a tagged
+       type.
+       (stab_demangle_fund_type): Likewise.
+
+Wed Jul  1 16:29:50 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * objcopy.c: Minor formatting improvements.
+       * readelf.c: Minor output formatting improvement.
+
+Wed Jul  1 14:23:48 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * rclex.l: Add casts and change types to avoid warnings.
+       * rcparse.y: Likewise.
+       * resbin.c: Likewise.
+       * rescoff.c: Likewise.
+       * resrc.c: Likewise.
+
+       * Makefile.am: Rebuild dependencies.
+       (HFILES): Remove readelf.h.
+       * Makefile.in: Rebuild.
+
+       Based on patches from Andrew Kozin
+       <Andrew.Kozin@p14.f960.n5020.z2.fidonet.org>:
+       * winduni.h: New file, from windres.h.
+       * winduni.c: New file, from windres.c.
+       * windres.c: Move Unicode functions into winduni.c.
+       * windres.h: Move Unicode declarations into winduni.h.  Include
+       winduni.h.
+       (RT_ACCELERATOR): Rename from RT_ACCELERATORS to match Windows
+       macro.  Change all uses.
+       (RT_PLUGPLAY, RT_VXD): Correct values.
+       * Makefile.am (HFILES): Add windres.h.
+       (CFILES): Add winduni.c.
+       (windres_SOURCES): Add winduni.c.
+
+Mon Jun 29 17:01:21 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c: Use BFD Internal and External Elf structures.
+       * readelf.h: Removed - no longer needed.
+       * Makefile.in: Remove readelf.c's dependency upon readelf.h.
+
+1998-06-26  Vladimir N. Makarov  <vmakarov@cygnus.com>
+
+       * objcopy.c (strip_main): keep_specific_list == NULL as additional
+       condition to set up strip all symbols by default.
+       (copy_archive): don't change archive when error in object files of
+       the archive.
+
+Wed Jun 24 17:53:47 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (parse_number): Sign extend negative values correctly if
+       bfd_vma is larger than unsigned long.
+
+Tue Jun 23 14:55:05 1998  Mike Stump  <mrs@wrs.com>
+
+       * Makefile.am (install-exec-local): Don't let EXEEXT interfere
+       with the program transform name.
+       * Makefile.in: Rebuild.
+
+Tue Jun 23 11:08:53 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c: Rewrite to use fopen/fread ratehr than mmap.
+
+       Add --section-headers command line switch, which is an alias for
+       --sections.
+
+       Incorporate improvemnts made by Andreas Schwab
+       <schwab@issan.informatik.uni-dortmund.de> including output
+       formatting and version info display.
+
+       * binutils.texi: Document --section-headers switch to readelf.
+
+Mon Jun 22 18:28:19 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * readelf.c: Include bfd.h and bucomm.h before system header
+       files.
+       (parse_args): Change type of c from char to int.
+
+Sun Jun 14 14:26:28 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (usage): Write to stdout, not stderr.
+
+Fri Jun 12 13:33:51 1998  Tom Tromey  <tromey@cygnus.com>
+
+       * po/Make-in (all-yes): Depend on .pot file if maintainer mode
+       enabled.
+       ($(PACKAGE).pot): Unconditionally depend on POTFILES.
+
+Fri Jun 12 16:06:15 1998  Michael Meissner  <meissner@cygnus.com>
+
+       * readelf.c (get_ppc_rel_type): New PowerPC support.
+       (dump_relocations): PowerPC uses RELA relocations.
+       (get_machine_name): Spell PowerPC correctly.
+       (get_file_type): Change unsigned short parameter to unsigned.
+       (get_machine_name): Ditto.
+       (get_machine_data): Return whether big endian or little endian.
+       (get_machine_flags): Interpret PowerPC, M32R, and MIPS flags.
+       (process_elf_header): Print endian-ess.  Convert all numeric
+       formats to long or unsigned long.  Print out machine specific flag
+       bits.
+       (process_section_headers): Increase name by 3 columns and decrease
+       type by the same so that .gcc_except_table fits in the space.
+
+       * readelf.h: Include elf/ppc.h, elf/mips.h, and elf/m32r.h to get
+       machine specific flag bits.
+
+Thu Jun 11 17:54:26 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c: Remove extraneous #includes.  Fix warnings produced
+       by -Wall when compiling under Linux.
+
+       * Makefile.am (readelf_LDADD): Add $(LIBIBERTY).
+
+Thu Jun 11 18:30:20 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (struct stab_handle): Add self_crossref field.
+       (parse_stab_string): If a tag is a cross reference to itself,
+       don't define it in the tags list.
+       (parse_stab_type): Set info->self_crossref.
+
+       * debug.c (struct debug_type_real_list): Define.
+       (debug_get_real_type): Add list parameter.  Change all callers.
+       Check for circularity to avoid crashing when it occurs.
+
+Thu Jun 11 14:48:32 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c: New file: Display contents of ELF format file.
+       * readelf.h: New file: Header file for readelf.c
+       * Makefile.am: Add rules to build readelf.
+       * Makefile.in: Rebuilt.
+       * binutils.texi: Document readelf.
+       * NEWS: Mention inclusion of readelf into binutils.
+       * po/POTFILES.in; Rebuilt.
+
+Fri Jun  5 18:43:40 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (setup_section): Adjust the section size if copy_byte
+       is >= 0.
+       (copy_section): Do not call bfd_set_section_size.
+
+Thu Jun  4 09:12:27 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * objcopy.c (copy_usage): Add missing \n\ from help description.
+
+Wed Jun  3 19:31:33 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (YACC): Correct bison -L option.
+       * Makefile.in: Rebuild.
+
+       * binutils.texi, objdump.1: Document -p/--private-headers.
+
+Wed Jun  3 12:09:40 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * objcopy.c: Add new command line options: --change-section-lma
+       and --change-section-vma.  Rename old command line option
+       --adjust-section-vma to --change-section-address.  Rename
+       --adjust-vma to --change-addresses and --adjust-start to
+       --change-start.  Provide aliases to support the old versions of
+       these command line options.
+
+       Change the names of macros and enum elements to upper case to
+       match the GNU coding standard.
+
+       Replace calls to fprintf (stderr,...) with calls to fatal () or
+       non_fatal () as appropriate.
+
+       * objcopy.1: Document command line option changes.
+       * binutils.texi: Document command line option changes.
+
+       * bucomm.h: New exported funtion from bucomm.c: non_fatal().
+       * bucomm.c (non_fatal): New exported function.  Just like fatal()
+       except that it returns rather than calling xexit().
+
+       (bfd_check_format_matches): Call fatal() rather than bfd_fatal().
+
+       (check_matching_formats): Fix C formating.
+
+       (parse_vma): Call fatal().
+
+Mon Jun  1 18:26:40 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       From Yuli Barcohen <yuli.barcohen@telrad.co.il>:
+       * debug.c (debug_type_samep): Avoid endless loops comparing
+       function and method parameter types.
+
+Fri May 22 14:02:42 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.c (dump_iat): Comment out; not used.
+       (display): Rename from tell.  Change all callers.
+
+Thu May 14 14:00:56 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * dlltool.c: Add support for Thumb DLLs.  Add support for
+       interworking between ARM and Thumb programs and DLLs.  Tidy the
+       code.
+
+       * binutils.texi: Document dlltool.
+
+       * configure: Build dlltool for thumb-pe targets.
+
+       * version.c (print_version): Include 1998 in copyright strings.
+
+       * stabs.c (parse_stab): Support Win32 style directory separators.
+
+Sun May 10 22:34:44 1998  Jeffrey A Law  (law@cygnus.com)
+
+       * po/Make-in (install-info): New target.
+
+Fri May  8 10:33:13 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * ar.c (usage): Extend information provided about command line
+       options.
+
+Wed May  6 15:28:51 1998  Klaus Kaempf  <kkaempf@progis.de>
+
+       * makefile.vms: Run dec c with /nodebug.  Pass CC value when
+       calling make.
+
+Tue May  5 15:19:00 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * configure: Build dlltool for thumb-pe target.
+       * configure.in: Build dlltool for thumb-pe target.
+
+Sun May  3 22:04:49 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (EXTRA_PROGRAMS): Change $(SRCONV_PROG) to sysconf
+       sysdump coffdump to avoid extra $(EXEEXT).
+       * Makefile.in: Rebuild.
+
+Wed Apr 29 22:22:55 1998  Geoffrey Noer <noer@cygnus.com>
+
+       * configure.in: Stop appending EXEEXT to the end of
+       SRCONV_PROG (wrong because that variable may contain multiple
+       programs)
+       * Makefile.am: instead, add EXEEXTs to each SRCONV_PROG
+       program
+       * Makefile.in: regenerate
+       * configure: regenerate
+
+Tue Apr 28 19:14:34 1998  Tom Tromey  <tromey@cygnus.com>
+
+       * addr2line.c (main): Conditionally call setlocale.
+       * windres.c (main): Likewise.
+       * sysdump.c (main): Likewise.
+       * strings.c (main): Likewise.
+       * srconv.c (main): Likewise.
+       * size.c (main): Likewise.
+       * objdump.c (main): Likewise.
+       * objcopy.c (main): Likewise.
+       * nm.c (main): Likewise.
+       * nlmconv.c (main): Likewise.
+       * dlltool.c (main): Likewise.
+       * coffdump.c (main): Likewise.
+       * ar.c (main): Likewise.
+       * bucomm.h: Include <locale.h> if HAVE_LOCALE_H.
+       (LC_MESSAGES): Now can be defined even when ENABLE_NLS.
+
+Tue Apr 28 10:33:07 1998  Bill Moyer  <ttk@cygnus.com>
+
+       Add support for IMPORTS:
+       * defparse.y (impline): Add IMPORTS syntaxes.
+       * dlltool.c (ifunctype, iheadtype): New typedefs.
+       (import_list): New static variable.
+       (append_import): New static function.
+       (def_import): Add an entry to import_list.
+       (generate_idata_ofile): New static function.
+       (gen_exp_file): Call generate_idata_ofile.
+       * dlltool.h (def_import): Update declaration.
+
+Mon Apr 27 16:39:22 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Change version number to 2.9.4
+       * configure: Rebuild.
+
+Wed Apr 22 16:00:35 1998  Tom Tromey  <tromey@cygnus.com>
+
+       * po/Make-in (MKINSTALLDIRS): Don't look in $(top_srcdir).
+
+Wed Apr 22 00:33:56 1998  Tom Tromey  <tromey@scribbles.cygnus.com>
+
+       * Makefile.am (INCLUDES): Search intl dirs for headers; define
+       LOCALEDIR.
+       * addr2line.c (main): Call setlocale, bindtextdomain, textdomain.
+       * ar.c (main): Likewise.
+       * coffdump.c (main): Likewise.
+       * dlltool.c (main): Likewise.
+       * nlmconv.c (main): Likewise.
+       * nm.c (main): Likewise.
+       * objcopy.c (main): Likewise.
+       * objdump.c (main): Likewise.
+       * size.c (main): Likewise.
+       * srconv.c (main): Likewise.
+       * strings.c (main): Likewise.
+       * sysdump.c (main): Likewise.
+       * windres.c (main): Likewise.
+
+Tue Apr 21 22:13:08 1998  Tom Tromey  <tromey@scribbles.cygnus.com>
+
+       * Many files: Added gettext invocations around user-visible
+       strings.
+       * bucomm.h: Added gettext-related includes and defines.
+       * acconfig.h (ENABLE_NLS, HAVE_CATGETS, HAVE_GETTEXT, HAVE_STPCPY,
+       HAVE_LC_MESSAGES): Define.
+       * configure.in: Call CY_GNU_GETTEXT.  Create po/Makefile.in and
+       po/Makefile.  Use AM_PROG_LEX.
+       * Makefile.am (SUBDIRS): New macro.
+       (POTFILES): Likewise.
+       (po/POTFILES.in): New target.
+       (LDADD): Added INTLLIBS.
+       (objdump_LDADD): Likewise.
+       (c__filt_LDADD): Likewise.
+       (ar_LDADD): Likewise.
+       (ranlib_LDADD): Likewise.
+       (dlltool_LDADD): Likewise.
+       (windres_LDADD): Likewise.
+       * po/Make-in, po/POTFILES.in, po/binutils.pot: New files.
+
+Tue Apr 21 16:07:18 1998  Stanislav Brabec  <utx@k332.feld.cvut.cz>
+
+       * objcopy.c (preserve_dates): New file static variable.
+       (smart_rename): If preserve_dates, call set_times when copying.
+       (strip_main): Remove preserve_dates local variable.
+       (copy_main): Likewise.
+
+Tue Apr  7 15:41:15 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (DISTSTUFF): Add defparse.h, defparse.c, rclex.c,
+       rcparse.h, and rcparse.c
+       * Makefile.in: Rebuild.
+
+Mon Apr  6 16:24:35 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (PROGS): Move $(ADDR2LINE_PROG) to end, so that
+       Makefile.in doesn't have an empty continuation line.
+       (bin_PROGRAMS): Likewise.
+       * Makefile.in: Rebuild.
+
+Fri Apr  3 14:48:42 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (DISTCLEANFILES): Add site.exp and site.bak.
+       (MOSTLYCLEANFILES): Add binutils.log, binutils.sum, and abcdefgh*.
+       (mostlyclean-local): New target.
+       * Makefile.in: Rebuild.
+
+Wed Apr  1 15:54:16 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       From Zack Weinberg <zack@rabi.phys.columbia.edu> and H.J. Lu
+       <hjl@gnu.org>:
+       * ar.c (usage): Mention S modifier.
+       (main): Add S modifier.
+       * ar.1, binutils.texi: Document S modifier.
+
+Wed Apr  1 13:11:23 1998  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * binutils.texi: Use @itemx for a secondary item in a table.
+
+Tue Mar 31 18:44:13 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dep-in.sed: Add rule to remove @OBJDIR@.
+       * Makefile.am (dep.sed): Substitute for @OBJDIR@.
+       * Makefile.in: Rebuild.
+
+Mon Mar 30 12:47:18 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Set version to 2.9.1.
+       * configure: Rebuild.
+
+       * Branched binutils 2.9.
+
+       * Makefile.am (DISTCLEANFILES): Remove defparse.h, arparse.h,
+       rcparse.h, and nlmheader.h.
+       * Makefile.in: Rebuild.
+
+Sat Mar 28 17:39:27 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (MOSTLYCLEANFILES): Define.
+       * Makefile.in: Rebuild.
+
+       Fix some gcc -Wall warnings:
+       * nlmconv.c (main): Add casts to avoid warnings.
+       (alpha_mangle_relocs): Likewise.
+       * objdump.c (dump_section_stabs): Likewise.
+       * size.c (print_sysv_format): Likewise.
+       * srcconv.c (wr_ob): Likewise.
+       * wrstabs.c (stab_modify_type): Likewise.
+       (stab_variable): Likewise.
+       * nlmconv.c (main): Initialize variables to avoid warnings.
+       * nm.c (sort_symbols_by_size): Likewise.
+       * objdump.c (disassemble_bytes): Likewise.
+       * wrstabs.c (stab_end_class_type): Likewise.
+       * coffgrok.c (do_sections_p2): Change j to unsigned int.
+       (do_lines): Change l to unsigned int.
+       * nlmheader.y (yylex): Change i to unsigned int.
+       * nm.c (print_symbol): Change j to long.
+       * size.c (lprint_number): Comment out.
+       * srconv.c (wr_ob): Change i to bfd_size_type.
+       * sysdump.c (unit_info_list): Comment out.
+       (object_body_list, program_structure, debug_list): Likewise.
+       * sysinfo.y (yyerror): Return value.
+
+Thu Mar 26 17:06:51 1998  Richard Henderson  <rth@cygnus.com>
+
+       * defparse.y (explist): Allow epsilon.
+       Suggestion from Jonathan-Harris@psion.com.
+
+Thu Mar 26 16:59:09 1998  Richard Henderson  <rth@cygnus.com>
+
+       * coffgrok.c (do_sections_p1): Use the section's lma instead of vma
+       for the benefit of prom loaders.
+
+Wed Mar 25 13:05:39 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       Based on patch from H.J. Lu  <hjl@gnu.org>:
+       * Makefile.am (DISTSTUFF): New variable.
+       (diststuff): New target.
+       (DISTCLEANFILES): New variable.
+       * Makefile.in: Rebuild.
+
+Tue Mar 24 19:33:08 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * rclex.l: Accept { and } as synonyms for BEGIN and END.
+
+Fri Mar 20 19:18:08 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * aclocal.m4, configure: Rebuild with libtool 1.2.
+
+Tue Feb 24 13:07:50 1998  Doug Evans  <devans@canuck.cygnus.com>
+
+       * objdump.c (disassemble_data): Delete "++place" after call to
+       find_symbol_for_address.  Set disasm_info.symbols to array of
+       symbols at the current address.
+
+Wed Feb 18 23:39:46 1998  Richard Henderson  <rth@cygnus.com>
+
+       * Makefile.am (install-exec-local): Install properly when ln
+       fails or tooldir == prefix.
+
+Tue Feb 17 18:40:55 1998  Richard Henderson  <rth@cygnus.com>
+
+       * objcopy.c (compare_section_lma): Rename from _vma.
+        (copy_object): Gap fill based on LMA not VMA.
+       * binutils.texi: Update and clarify.
+       * objcopy.1: Likewise.
+
+Tue Feb 17 20:34:11 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.c (gen_exp_file): Generate _imp__%s as well as __imp_%s,
+       for Microsoft compatibility.
+       (make_one_lib_file): Likewise.
+
+       * dlltool.c (make_one_lib_file): Don't add 1 to hint.
+
+Fri Feb 13 16:37:44 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (AUTOMAKE_OPTIONS): Define.
+       * configure, Makefile.in, aclocal.m4: Rebuild with automake 1.2e.
+
+Thu Feb 12 14:13:46 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * deflex.l: Accept '?' in symbol names, for VC++ mangled names.
+       From Mikey <jeffdb@netzone.com>.
+
+       * addr2line.c (usage): Update bug-gnu-utils address.
+       * ar.c (usage): Likewise.
+       * nlmconv.c (show_usage): Likewise.
+       * nm.c (usage): Likewise.
+       * objcopy.c (copy_usage): Likewise.
+       (strip_usage): Likewise.
+       * objdump.c (usage): Likewise.
+       * size.c (usage): Likewise.
+       * strings.c (usage): Likewise.
+       * windres.c (usage): Likewise.
+       * binutils.texi (Bug Reporting): Likewise.
+
+Sat Feb  7 15:36:24 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure, aclocal.m4: Rebuild with new libtool.
+
+Thu Feb  5 12:21:13 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure, Makefile.in, aclocal.m4: Rebuild with new libtool.
+
+Fri Jan 30 19:16:28 1998  Doug Evans  <devans@canuck.cygnus.com>
+
+       * Makefile.am (CC_FOR_TARGET,nlmcomv.o): Change program_transform_name
+       to transform.
+       * Makefile.in: Regenerate.
+
+Thu Jan 29 16:24:04 1998  Mumit Khan  <khan@xraylith.wisc.edu>
+
+       * dlltool.c: Define exit status macros for _WIN32 but not
+       __CYGWIN32__.
+       (gen_lib_file): Check for exit status of unlink.
+       * resrc.c: Define popen and pclose if _WIN32 but not
+       __CYGWIN32__.
+
+Wed Jan 28 17:45:46 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Remove vfork check.
+       * nlmconv.c: Never include vfork.h.
+       * aclocal.m4, configure, Makefile.in, config.in: Rebuild.
+
+Wed Jan 28 17:43:02 1998  J.J. van der Heijden <J.J.vanderHeijden@student.utwente.nl>
+
+       * objcopy.c (copy_archive): Only pass one argument to mkdir if
+       _WIN32 but not __CYGWIN32__.
+       (smart_rename): Add code for _WIN32 (not __CYGWIN32__), to cope
+       with different rename behaviour and lack of chown.
+
+       * configure.in: Check for mingw32 when deciding whether to build
+       dlltool.
+       * dlltool.c: Never include vfork.h.
+       (run): Use pexecute rather than vfork.
+       (gen_lib_file): Check for errors from bfd_set_archive_head and
+       bfd_close.  Close all the BFDs in the archive before deleting the
+       temporary files.
+
+Thu Jan 22 16:22:55 1998  Fred Fish  <fnf@cygnus.com>
+
+       * objdump.c (disassemble_bytes): Add flag INSN_HAS_RELOC to tell
+       disassembly function there is a reloc on this line.
+
+Wed Jan 14 15:29:43 1998  Richard Henderson  <rth@cygnus.com>
+
+       * srconv.c (sh, h8300): Delete variables.
+       (addrsize, toolname, rnames): New variables.
+       (writeINT): Use addrsize.
+       (wr_un): Use toolname.
+       (wr_hd): Set up addrsize et al properly for h8300[hs].
+       (walk_tree_symbol): Zero dsy.  Use rnames.
+       (wr_un, wr_hd, wr_ob, wr_du): Use proper bfd access macros.
+       * sysdump.c (sh, h8300): Delete variables.
+       (addrsize): New variable.
+       (getINT): Use it.
+       (getone): Initialize it.
+       (getBITS): Range check on MAX.
+
+Mon Dec 29 16:58:05 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       From Matthew Bellantoni <matthew@chrysalis.com>:
+       * ar.c (get_pos_bfd): Add default_posname parameter.  Change all
+       callers.
+       (replace_members): Default to replacing in the same position.
+
+Mon Dec 22 11:27:22 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * rclex.l: Don't permit a comma in a STRING.
+       * rcparse.y (acc_entry): Warn if an inappropriate modifier is used
+       with a non VIRTKEY.
+       (acc_event): For a control character, set VIRTKEY, and force the
+       character to uppercase.
+       (acc_options): Don't require a comma separator.
+
+Tue Dec  9 13:25:42 1997  Michael Meissner  <meissner@cygnus.com>
+
+       * size.c (size_number): New function to provide size of field.
+       ({l,r}print_number): For octal and hex fields, print field using
+       '0' and '0x' suffixes.  Do not include following tab.
+       (sysv_internal_sizer): Size section name, section size, and vma
+       address fields.
+       (sysv_internal_printer): Use calculated sizes for the columns.
+       (print_sysv_format): Size columns before printing.
+       (print_berkeley_format): Print tabs between numbers now that
+       {l,r}print_number doesn't.  Print fields right justified.
+
+Mon Dec  8 11:22:04 1997  Nick Clifton  <nickc@cygnus.com>
+
+       * objdump.c (objdump_print_addr_with_sym): Remove call to
+       disasm_symaddr() as this function no longer exists.
+
+Tue Dec  2 10:23:50 1997  Nick Clifton  <nickc@cygnus.com>
+
+       * objdump.c (objdump_print_addr_with_sym): Call disasm_symaddr()
+       to allow backend to know which symbol has just been displayed.
+
+Tue Dec  2 13:06:46 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * windres.h (ESCAPE_*): Define standard escape sequences.
+       * rclex.l (handle_quotes): Handle standard escape sequences.  Warn
+       about an unrecognized escape character.
+       * windres.c (unicode_print): Print standard escape sequences.
+       * rcparse.y (acc_event): Initialize $$.next.
+       * resbin.c (bin_to_res_menuitems): Don't set MENUITEM_POPUP or
+       MENUITEM_ENDMENU in the menu item flags.
+       (bin_to_res_accelerators): Allocate a structure (the old code
+       never worked).
+       (res_to_bin_accelerator): Correct the test for setting ACC_LAST.
+       (res_to_bin_dialog): Save the extended style rather than saving
+       the style twice.  Remove useless shadowing length variable.  Set
+       the length of control data correctly.
+       * resrc.c (write_rc_dialog): Don't print the class or menu if the
+       string length is zero.
+
+Mon Nov 24 18:52:43 1997  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * stabs.c (parse_stab_argtypes): Don't try to parse the name of a
+       destructor as mangled argument types.
+
+Mon Nov 10 17:51:41 1997  Gavin Koch  <gavin@cygnus.com>
+
+       * addr2line.c (translate_addresses): Use bfd_scan_vma rather
+       than strtol to scan addresses.
+
+Sun Nov  9 11:01:31 1997  Jeffrey A Law  (law@cygnus.com)
+
+       * Makefile.am (bin_PROGRAMS): Don't use line continuations here.
+
+Tue Nov  4 11:56:14 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (copy_section): Don't crash if there is no particular
+       information for a section.
+
+Mon Nov  3 12:36:19 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (parse_flags): Make flag check case insensitive.
+       Check for `contents' flag.  Give an error for unrecognized flags.
+       (copy_section): If the contents flag was set for a section that
+       had no contents, zero out the new contents.
+       * binutils.texi (objcopy): Document contents section flag.
+
+Sun Nov  2 14:49:56 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c: Move new struct and variable definitions to top of
+       file.  Remove obsolete add_strip_symbol and is_strip_symbol
+       declarations.  Add prototype declarations for add_specific_symbol
+       and is_specified_symbol.
+
+Mon Oct 20 15:31:43 1997  Klaus K"ampf  <kkaempf@progis.de>
+
+       * configure.com (HAVE_SBRK): Undefine.
+
+Tue Oct 14 16:14:35 1997  Nick Clifton  <nickc@cygnus.com>
+
+       * objdump.c (objdump_symbol_at_address): New function.  Returns
+       true if a symbol can be found at the address passed in.
+       (disassemble_data): Set the symbol_at_address_func field to point
+       to objdump_symbol_at_address.
+
+Fri Oct 10 14:13:09 1997  Richard Henderson  <rth@cygnus.com>
+
+       * objcopy.c, objcopy.1, binutils.texi: "localize" is a better name
+       than "privatize".  Update all references.
+
+Thu Oct  9 15:57:29 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils.texi (strip): Remove duplicate --target.  From Marty
+       Leisner <leisner@sdsp.mc.xerox.com>.
+
+       * nm.c (lineno_cache_bfd): New file static variable.
+       (lineno_cache_rel_bfd): New file static variable.
+       (display_archive): Clear lineno_cache_bfd and lineno_cache_rel_bfd
+       when closing a BFD.
+       (display_file): Likewise.
+       (print_symbol): Use lineno_cache_bfd and lineno_cache_rel_bfd
+       instead of cache_bfd and cache_rel_bfd.  Make seccount static, and
+       only set it when setting relocs.
+
+Wed Oct  8 21:19:11 1997  Richard Henderson  <rth@cygnus.com>
+
+       * objcopy.c (keep_specific_list, privatize_specific_list,
+       weaken_specific_list): New variables.
+       (keep_symbols): Removed.
+       (add_specific_symbol): New function from the carcas of
+       add_strip_symbol.  Takes a list as an argument.
+       (is_specified_symbol): Likewise from is_strip_symbol.
+       (filter_symbols): Honor the new privatize and weaken lists.
+       Optimize bfd_asymbol_name handling.
+       (copy_object, copy_options, copy_usage): Add privatize-symbol &
+       weaken-symbol options.
+
+       * objcopy.1, binutils.texi: Update docs.
+
+Sun Oct  5 09:05:44 1997  Frank Ch. Eigler  <fche@cygnus.com>
+
+       * objdump.c (disassemble_data): Make "--prefix-addresses"
+       disassembly adjust to mixed-length instructions.
+       (objdump_print_addr_with_sym): Add "0x" prefix for hexadecimal
+       symbol-offsets in disassembly.
+
+Fri Oct  3 12:04:25 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (set_times): New static function, replacing
+       make_same_dates.
+       (strip_main): If preserve_dates, stat the input file before
+       copying it, and call set_times afterward.
+       (copy_main): Likewise.
+
+       * wrstabs.c (write_stabs_in_sections_debugging_info): Cast p to
+       char * when calling strcpy and strlen.
+
+Wed Sep 24 11:34:05 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils.texi (ar cmdline): Document that q now works like r.
+       From Marty Leisner <leisner@sdsp.mc.xerox.com>.
+
+       * binutils.texi (size): The object file argument is optional.
+       From Marty Leisner <leisner@sdsp.mc.xerox.com>.
+
+       * aclocal.m4: Rebuild with new libtool.
+       * configure: Rebuild.
+
+Tue Aug 26 17:48:34 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (EXEEXT_FOR_BUILD): New variable.  Use it in all
+       references to the sysinfo program.
+       * configure.in: Rebuild with new bfd/acinclude.m4.
+       * Makefile.in: Rebuild.
+
+Fri Aug  8 15:32:49 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * windres.c: Include <time.h>.
+       (define_resource): Set a timestamp for the resource.
+
+Wed Aug  6 13:37:58 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Define TARGET in header file.
+       * acconfig.h (TARGET): Add #undef.
+       * Makefile.am (version.o, bucomm.o): Remove special targets.
+       * bucomm.c (target): Remove.
+       * nm.c (program_name): Don't declare.
+       (target): Make static.
+       * size.c (target): Make static.
+       * configure, config.in, Makefile.in: Rebuild.
+
+Tue Aug  5 00:01:41 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (check-DEJAGNU): Export r.
+       (.dep1): Use $(INCLUDES) rather than $(ALL_CFLAGS).
+       * Makefile.in: Rebuild.
+
+       * nlmheader.y: Use VERSIONK rather than VERSION.
+
+       * Makefile.am (STRIP_PROG): Change from strip.new to strip-new.
+       (NM_PROG): Change from nm.new to nm-new.
+       (TOOL_PROGS, install-exec-local): Adjust accordingly.
+       * Makefile.in: Rebuild.
+
+Mon Aug  4 11:47:31 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Remove AC_ARG_PROGRAM; it's invoked by
+       AM_INIT_AUTOMAKE.
+       * configure: Rebuild.
+
+       * Makefile.am (install-exec-local): Create $(tooldir)/bin before
+       trying to install anything into it.
+       * Makefile.in: Rebuild.
+
+       * Makefile.am (TOOL_PROGS): Use an explicit $(EXEEXT).
+       (install-exec-local): When handling $(noinst_PROGRAMS), only use
+       $(EXEEXT) on the installed file.  When handling $(TOOL_PROGS),
+       handle $(EXEEXT) correctly.
+       * configure.in: Add an explicit $(EXEEXT) when substituting for
+       the name of a program to build.
+       * Makefile.in, configure: Rebuild.
+
+       * aclocal.m4, configure, Makefile.in: Rebuild with new automake
+       patches.
+
+       * deflex.l, defparse.y: Use VERSIONK rather than VERSION.
+       * rclex.l, rcparse.y: Likewise.
+       * Makefile.am (windres_SOURCES): Add $(BULIBS).
+       * Makefile.in: Rebuild.
+
+Fri Aug  1 13:08:39 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * acinclude.m4: Include bfd/acinclude.m4, not bfd/acmacros.m4.
+       * aclocal.m4, configure: Rebuild with new libtool.
+
+Thu Jul 31 11:51:35 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am: New file, based on old Makefile.in.
+       * acinclude.m4: New file, from old aclocal.m4.
+       * configure.in: Call AM_INIT_AUTOMAKE and AM_PROG_LIBTOOL.  Remove
+       shared library handling; now handled by libtool.  Replace
+       AC_CONFIG_HEADER with AM_CONFIG_HEADER.  Call AC_PROG_YACC,
+       AC_PROG_LEX, AC_DECL_YYTEST, AM_MAINTAINER_MODE, AM_CYGWIN32, and
+       AM_EXEEXT.  Replace AC_PROG_INSTALL with AM_PROG_INSTALL.  Remove
+       stamp-h handling in AC_OUTPUT.
+       * acconfig.h: Mention PACKAGE and VERSION.
+       * stamp-h.in: New file.
+       * Makefile.in: Now built with automake.
+       * aclocal.m4: Now built with aclocal.
+       * config.in, configure: Rebuild.
+
+       From Ton van Overbeek <tvoverbe@wk.estec.esa.nl>:
+       * rcparse.y (dialog): Default menu and class to be named.
+       (styles): If FONT is seen, set DS_SETFONT in dialog style.
+       * resbin.c (res_to_bin_dialog): Correct computation of font
+       information length.
+
+Wed Jul 30 11:21:06 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       From Ton van Overbeek <tvoverbe@wk.estec.esa.nl>:
+       * resbin.c (res_to_bin_menu): Correct computation of menu
+       vs. menuex length.
+       * resrc.c (define_stringtable): Add 1 to resource ID.
+
+Tue Jul 29 11:06:03 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * resbin.c (bin_to_res_string): Correct adjustment of data and
+       length.  From Ton van Overbeek <tvoverbe@wk.estec.esa.nl>.
+
+Tue Jul 22 18:01:23 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * nlmconv.c (link_inputs): Call libiberty pexecute function.
+       (pexecute) [multiple versions]: Remove.
+
+Tue Jul 22 16:19:34 1997  Robert Hoehne <robert.hoehne@Mathematik.TU-Chemnitz.DE>
+
+       * bucomm.c (make_tempname): If we might be using a DOS filesystem,
+       check for a backslash as well as a slash.
+
+Thu Jun 26 13:53:17 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * windres.c (main): Quit if we didn't get any resources.
+       (usage): Fix --yydebug usage message.
+       * rescoff.c (write_coff_file): Don't free the relocation array
+       until after we've closed the BFD.
+       (read_coff_rsrc): Quit rather than try to read standard input.
+       (write_coff_file): Quit rather than try to write to standard
+       output.
+       * rcparse.y: Add a couple of missing semicolons (accepted by bison
+       but not byacc).
+       * binutils.texi: Document windres.
+
+Wed Jun 25 20:57:06 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * resbin.c: New file.
+       * rclex.l, rcparse.y, rescoff.c, resrc.c, windres.c, windres.h:
+       Numerous fixes and improvements.
+       * Makefile.in: Rebuild dependencies.
+       (CFILES): Add resbin.c.
+       (WINDRES_OBJS): Add resbin.o.
+
+Sun Jun 22 17:29:41 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       First stab at Windows resource compiler:
+       * windres.h: New file.
+       * windres.c: New file.
+       * resrc.c: New file.
+       * rcparse.y: New file.
+       * rclex.l: New file.
+       * rescoff.c: New file.
+       * configure.in: Define and substitute BUILD_WINDRES.
+       * configure: Rebuild.
+       * Makefile.in: Rebuild dependencies.
+       (WINDRES_PROG): New variable.
+       (PROGS): Add @BUILD_WINDRES@.
+       (HFILES): Add dlltool.h and windres.h.
+       (CFILES): Add windres.c and resrc.c.
+       (GENERATED_CFILES): Add rcparse.c and rclex.c.
+       (WINDRES_OBJS): New variable.
+       $(WINDRES_PROG): New target.
+       (rcparse.c, rcparse.h, rclex.c): New targets.
+
+Thu Jun 12 12:27:51 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.c (export_type): Add data field.
+       (def_exports): Add data parameter.  Change all callers.
+       (dump_def_info): Print data field.
+       (gen_def_file): Likewise.
+       (make_one_lib_file): Handle data field by not emitting simple
+       label and not emitting anything in SEC_TEXT.
+       (dtab): Print data field.
+       (process_duplicates): Merge data field.
+       * dlltool.h (def_exports): Update declaration.
+       * defparse.y (expline): Accept opt_DATA.  Pass it to def_exports.
+       (opt_DATA): New non-terminal.
+
+Wed Jun 11 17:15:47 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.h: New file.
+       * deflex.l: Include dlltool.h and libiberty.h.  Don't declare
+       strdup.  Use xstrdup rather than strdup.
+       * defparse.y: Include bfd.h, bucomm.h, and dlltool.h.
+       * dlltool.c: Include dlltool.h and time.h.  Make a lot of
+       variables and functions static.  Make a lot of char * variables
+       and parameters const.  Add declarations for static functions.  Do
+       some reindenting.  Hide more PowerPC stuff inside DLLTOOL_PPC.
+
+Wed Jun 11 12:05:52 1997  H.J. Lu  <hjl@gnu.ai.mit.edu>
+
+       * ar.c (bfd_special_undocumented_glue): Add const.
+
+Mon May 12 22:09:35 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       * Makefile.in (check): Pass CC_FOR_TARGET and CFLAGS_FOR_TARGET
+       to runtest.
+
+Mon May 12 13:14:22 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Don't clear OPCODES when --enable-commonbfdlib is
+       used on HP/UX.
+       * configure: Rebuild.
+
+Fri Apr 25 14:22:08 1997  H.J. Lu  <hjl@gnu.ai.mit.edu>
+
+       * Makefile.in (maintainer-clean realclean): Change *.info*
+       to binutils.info* to save sysroff.info.
+
+Tue Apr 15 13:42:22 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (INSTALL): Set to @INSTALL@.
+       (INSTALL_XFORM, INSTALL_XFORM1): Remove.
+       (install): Depend upon installdirs.  Use $(program_transform_name)
+       directly, rather than using $(INSTALL_XFORM) and
+       $(INSTALL_XFORM1).
+       (installdirs): New target.
+       (install-info): Run mkinstalldirs.
+
+Mon Apr 14 11:52:39 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (INSTALL): Change install.sh to install-sh.
+
+       From Thomas Graichen <graichen@rzpd.de>:
+       * Makefile.in: Always use $(SHELL) when running move-if-change.
+       * configure.in: Use ${CONFIG_SHELL} when running $ac_config_sub.
+       * configure: Rebuild.
+
+Fri Apr  4 13:28:02 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Add AC_FUNC_ALLOCA.
+       * configure, config.in: Rebuild.
+       * bucomm.h: Add alloca handling, copied from gas/as.h.
+       * dlltool.c: Add #pragma alloca for AIX to start of file.
+       * nlmconv.c: Likewise.
+
+       * Makefile.in (distclean): Remove site.exp and site.bak.  Remove
+       everything that clean removes.
+
+Thu Apr  3 13:18:39 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (VERSION): Set to 2.8.1.
+
+       * Branched binutils 2.8.
+
+Tue Apr  1 16:21:44 1997  Klaus Kaempf  <kkaempf@progis.de>
+
+       * configure.com: New file.
+       * config.h-vms: Remove file.
+       * makefile.vms: Update for new configure scheme.
+
+Mon Mar 31 15:30:43 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>
+
+       * objcopy.c (make_same_dates): Use statbuf, not buf, if not
+       HAVE_GOOD_UTIME_H.
+
+Fri Mar 28 17:57:53 1997  Alan Modra  <alan@spri.levels.unisa.edu.au>
+
+       * Makefile.in ($(OBJDUMP_PROG)): Don't link against BFDLIB twice.
+       * configure.in: Add AC_ARG_ENABLE for commonbfdlib.  If it is set,
+       set OPCODES to empty.
+       * configure: Rebuild.
+
+Thu Mar 27 16:03:02 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       Based on patch from Marty Leisner <leisner@sdsp.mc.xerox.com>:
+       * objcopy.c: Include <utime.h> or <sys/time.h>.
+       (strip_options): Add "preserve-dates".
+       (copy_options): Likewise.
+       (copy_usage): Mention -p and --preserve-dates.
+       (strip_usage): Likewise.
+       (make_same_dates): New static function.
+       (strip_main): Handle -p.
+       (copy_main): Likewise.
+       * binutils.texi, strip.1, objcopy.1: Document new option.
+
+       addr2line.c contributed by Ulrich Lauther
+       <Ulrich.Lauther@zfe.siemens.de>:
+       * addr2line.c: New file.
+       * Makefile.in: Rebuild dependencies.
+       (ADDR2LINE_PROG): New variable.
+       (MANPAGES): Add addr2line.
+       (PROGS): Add $(ADDR2LINE_PROG).
+       (CFILES): Add addr2line.c.
+       ($(ADDR2LINE_PROG)): New target.
+       * binutils.texi: Document addr2line.
+       * addr2line.1: New file.
+
+       * version.c (print_version): Update copyright date.
+
+Mon Mar 24 10:52:45 1997  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * objdump.c (disassemble_data): Don't exit if a file cannot be
+       disassembled, instead just return.
+
+Thu Mar 20 21:16:51 1997  Jeffrey A Law  (law@cygnus.com)
+
+       * size.c (usage): Make definition match its prototype.
+       (display_bfd, lprint_number, rprint_number): Likewise.
+       (print_berkeley_format, sysv_internal_printer): Likewise.
+       (print_sysv_format): Likewise.
+       * nm.c (set_print_radix, set_output_format): Likewise.
+       * objcopy.c (filter_bytes): Likewise.
+
+Tue Mar 18 16:39:55 1997  H.J. Lu  <hjl@lucon.org>
+
+       * Many files: Add function prototypes.
+       * ar.c (mri_emul, get_pos_bfd): Make static.
+       * arlex.l: Include "libiberty.h".  Don't declare strdup.  Use
+       xstrdup rather than strdup.
+       * arparse.y (yyerror): Make argument const.  Correct typo.
+       * arsup.c (strdup): Don't declare.
+       (ar_save): Use xstrdup rather than strdup.
+       * filemode.c: Include "bucomm.h".
+       * nm.c (usage): Make static.
+       (print_symname): Make format and name const.
+       * objcopy.c (cat): Remove.
+       (copy_archive): Make output_target const.  Use concat, not cat.
+       (copy_file, simple_copy, smart_rename): Make arguments const.
+       * objdump.c (read_section_stabs): Likewise.
+       (print_section_stabs): Likewise.
+       (display_target_tables): Don't declare getenv.
+       * strings.c (strings_object_file): Change file to const.
+       (print_strings): Change filename to const.
+       * Makefile.in: Rebuild dependencies.
+
+Tue Mar 18 11:37:24 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Add BFD_NEED_DECLARATION(getenv).
+       * acconfig.h: Add NEED_DECLARATION_GETENV.
+       * bucomm.h (getenv): Declare if NEED_DECLARATION_GETENV.
+       * configure, config.in: Rebuild.
+       * nlmconv.c (getenv): Don't declare.
+
+       * Makefile.in: Rebuild dependencies.
+
+Sat Mar 15 15:35:56 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       Based on patches from Jamie Lokier <jamie@rebellion.co.uk>:
+       * objdump.c: Include "demangle.h".
+       (do_demangle): New static variable.
+       (usage): Mention -C/--demangle.
+       (long_options): Add "demangle".
+       (objdump_print_symname): New static function.
+       (objdump_print_addr_with_sym): Use objdump_print_symname.
+       (disassemble_bytes): Likewise.
+       (dump_reloc_set): Likewise.
+       (dump_symbols): Demangle symbol name.
+       (main): Handle -C.
+       * binutils.texi, objdump.1: Document -C/--demangle.
+
+       * objdump.c (usage): Mention --no-show-raw-insn.
+       (long_options): Add "no-show-raw-insn".
+       (disassemble_bytes): Handle --no-show-raw-insn.
+       * binutils.texi, objdump.1: Document --no-show-raw-insn.
+
+Wed Mar 12 11:42:00 1997  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * rddbg.c (free_saved_stabs): Set the strings to NULL after being
+       freed.
+
+Fri Feb 28 17:18:45 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * bucomm.c (set_default_bfd_target): New function.
+       * bucomm.h (set_default_bfd_target): Declare.
+       * ar.c (main): Call set_default_bfd_target.
+       * nlmconv.c (main): Likewise.
+       * nm.c (main): Likewise.
+       * objcopy.c (main): Likewise.
+       * objdump.c (main): Likewise.
+       * size.c (main): Likewise.
+       * strings.c (main): Likewise.
+       * Makefile.in (bucomm.o): New target, to define TARGET.
+
+Tue Feb 25 21:28:38 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (adjust_section_vma): New static variable.
+       (usage): Mention --adjust-section-vma.
+       (OPTION_ADJUST_VMA): Define.
+       (long_options): Add "addjust-vma".
+       (display_bfd): If adjust_section_vma is not 0, add it to all the
+       section addresses.
+       (main): Handle OPTION_ADJUST_VMA.
+       * binutils.texi, objdump.1: Document --adjust-vma.
+
+Fri Feb 14 18:46:47 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * nm.c (print_symbol): Cache the BFD as well as the symbols and
+       relocs, and don't try to use the symbols or relocs with a
+       different BFD.
+
+Thu Feb 13 21:34:43 1997  Klaus Kaempf  (kkaempf@progis.de)
+
+       * config.h-vms: sbrk() is provided on openVMS/Alpha.
+       * makefile.vms: allow compiling with current gcc snapshot.
+
+Thu Feb 13 20:14:40 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * arsup.c, coffgrok.c, dlltool.c, nlmconv.c: Use xmalloc rather
+       than malloc.
+
+Wed Feb 12 16:12:02 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (disassemble_data): Correct VMA argument to
+       find_symbol_for_address.  Improve handling of code with no symbol
+       followed by code with a symbol.
+
+Wed Feb 12 12:16:47 1997  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * objdump.c (disassemble_bytes): Make output of raw instructions
+       work better for non-standard values of bytes_per_chunk and
+       bytes_per_line.
+
+Thu Feb  6 14:14:59 1997  Martin M. Hunt  <hunt@pizza.cygnus.com>
+
+       * objdump.c (disassemble_bytes): Added code to allow some control
+       over the way raw instructions are displayed.
+
+Thu Feb  6 12:36:03 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (struct bincl_file): Add next_stack field.
+       (push_bincl): Put the new file on both bincl_list and
+       bincl_stack.  Clear the file_types field.
+       (pop_bincl): Use the next_stack field when popping the stack.
+       Don't put the file on bincl_list.
+       (find_excl): Include the file name when warning about an unfound
+       N_EXCL.
+
+       * debug.c (debug_type_samep): Don't crash if we are passed NULL.
+
+Thu Feb  6 11:54:24 1997  Alan Modra  <alan@spri.levels.unisa.edu.au>
+
+       * objcopy.1: Add missing space after .B.
+
+Fri Jan 31 10:33:07 1997  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * objdump.c (disassemble_data): Initialize `aux.require_sec'.
+
+Wed Jan 29 13:21:21 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (objdump_print_value): Add skip_zeroes parameter.
+       Change all callers.
+       (objdump_print_addr_with_sym): Likewise.  Call objdump_print_value
+       to print address.
+       (objdump_print_addr): New static function.
+       (objdump_print_address): Just call objdump_print_addr.
+       (disassemble_bytes): Print real address, not function offset.
+       Skip a certain number of leading zeroes.
+
+       * objdump.c (disassemble_zeroes): New static variable.
+       (usage): Mention --disassemble-zeroes.
+       (long_options): Add "disassemble-zeroes".
+       (disassemble_bytes): Check disassemble_zeroes.
+
+Tue Jan 28 16:47:26 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (disassemble_bytes): Don't skip zeroes if the
+       disassembler has told us that we are in a branch delay slot.
+
+Mon Jan 20 14:24:04 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * size.c (berkeley_sum): Rewrite.  Skip sections which are not
+       SEC_ALLOC.  Count SEC_READONLY sections as text.
+
+Tue Jan 14 15:14:14 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (maintainer-clean realclean): Remove *.info*, not
+       just *.info.  From H.J. Lu <hjl@lucon.org>.
+
+Tue Dec 31 15:42:54 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (ALL_CFLAGS): Add -D_GNU_SOURCE.
+
+Fri Dec 27 11:19:26 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Work around bug in AC_FUNC_VFORK in autoconf 2.12.
+       * configure: Rebuild.
+
+Thu Dec 19 13:11:20 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       Based on patch from Andrew J Klossner <andrew@pogo.wv.tek.com>:
+       * objcopy.c (OPTION_WEAKEN): Define.
+       (copy_options): Add "weaken".
+       (copy_usage): Mention --weaken.
+       (weaken): New static variable.
+       (filter_symbols): Handle weaken.
+       (copy_object): Call filter_symbols if weaken.
+       (copy_main): Handle OPTION_WEAKEN.
+       * binutils.texi, objcopy.1: Document --weaken.
+
+Wed Dec 18 22:49:13 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-make.sed: Use NewFolderRecursive for installation.
+
+Sat Dec  7 10:17:25 1996  Jeffrey A Law  (law@cygnus.com)
+
+       * Makefile.in (install): Add "else true" clause to cater to
+       broken "make" on some systems.
+
+Fri Dec  6 17:21:41 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c (parse_ieee_bb): Always initialize namcopy to avoid gcc
+       warning about uninitialized variable.
+       (ieee_read_cxx_class): Likewise, for pf.
+       (ieee_enum_type): Likewise, for i.
+
+Tue Nov 26 17:01:25 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * wrstabs.c (stab_array_type): Add casts when printing
+       bfd_signed_vma values.
+
+       * configure: Rebuild with autoconf 2.12.
+
+Mon Nov 25 16:53:18 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (disassemble_data): Don't crash if there is no
+       symbol.
+
+Fri Nov 22 17:29:14 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * ar.c (open_inarch): Don't call bfd_openr with a null name.
+
+Fri Nov  1 12:08:13 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils.texi: Add section on reporting bugs.
+
+Thu Oct 31 18:20:53 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (struct stab_handle): Add bincl_list field.
+       (parse_stab): Pass value to push_bincl.  Call find_excl for
+       N_EXCL.
+       (struct bincl_file): Add hash, file and file_types fields.
+       (push_bincl): Add hash parameter.  Save it in the new hash field.
+       Save the file number in the new file field.
+       (pop_bincl): Put the bincl_file on bincl_list, rather than freeing
+       it.  Save the file types in the new file_types field.
+       (find_excl): New static function.
+
+       * ieee.c (ieee_lineno): Don't compare line number addresses to
+       info->highaddr (undo part of October 28 patch).
+
+Tue Oct 29 16:40:22 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (objdump_print_value): Don't print the empty string
+       for zero.
+
+Mon Oct 28 16:58:14 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (struct stab_handle): Add function_end field.
+       (start_stab): Initialize function_end.
+       (finish_stab): Pass info->function_end to debug_end_function.
+       (parse_stab): If info->function_end is set, use it as the address
+       which ends a function.
+
+       * ieee.c (ieee_array_type): Remember the correct size.
+
+       * ieee.c (ieee_finish_compilation_unit): Permit coalescing ranges
+       that are up to 0x1000 bytes apart, not just 64.
+       (ieee_add_bb11_blocks): Don't bother to emit a BB11 that is less
+       than 0x100 bytes.
+       (ieee_lineno): Only emit line numbers that are less than
+       info->highaddr.
+
+Fri Oct 25 12:12:17 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c (struct ieee_defined_enum): Add defined field.
+       (ieee_enum_type): If the enum tag has been seen before but not
+       defined, reuse the same type index, and define it.
+       (ieee_tag_type): If this enum has not been defined, add an
+       undefined entry to the list of enums.
+
+       * objdump.c (disassemble_bytes): Let the disassembler override the
+       number of bytes printed on a line.
+
+Thu Oct 24 16:42:10 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (prefix_addresses): New static variable.
+       (long_options): Add "prefix-addresses".
+       (compare_symbols): Sort BSF_FUNCTION symbols before other
+       symbols.
+       (find_symbol_for_address): New static function, broken out of
+       objdump_print_address.
+       (objdump_print_addr_with_sym): New static function, broken out of
+       objdump_print_address.
+       (objdump_print_address): Call new functions.
+       (disassemble_bytes): New static function, broken out of
+       disassemble_data.  Change disassembly format, unless
+       prefix_addresses is set.
+       (disassemble_data): Call disassemble_bytes.  Unless
+       prefix_addresses is set, disassemble in chunks headed by a
+       symbol.
+       * binutils.texi, objdump.1: Document --prefix-addresses.
+
+       * rddbg.c (read_section_stabs_debugging_info): Preserve the
+       backslash when concatenating multiple stabs strings.
+
+Thu Oct 10 11:36:31 1996  Doug Evans  <dje@canuck.cygnus.com>
+
+       * dlltool.c (scan_open_obj_file): Fix loop exit test.
+       Add missing parameter to def_exports.
+
+Tue Oct  8 12:06:17 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (LEX_OPTIONS): Set to empty string.  -I -Cem is the
+       default for flex, and is not recognized by lex.
+
+Thu Oct  3 17:41:23 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils.texi (Target Selection): Document that you can now
+       specify targets using configuration triplets.
+
+       * ar.c (usage): Declare.  Make sure all callers pass an argument.
+
+Thu Oct  3 15:39:42 1996  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * Makefile.in (clean): Remove config.log.
+
+Wed Oct  2 15:49:16 1996  Klaus Kaempf  <kkaempf@progis.de>
+
+       * makefile.vms: Bump version date.
+
+Tue Oct  1 15:00:59 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * version.c (print_version): New function.
+       * bucomm.h (print_version): Declare.
+       * ar.c (program_version): Don't declare.
+       (do_show_version): Remove.
+       (usage): Add help parameter.  Print bug report address.
+       (main): Set is_ranlib at start.  Check for --help and --version.
+       Call print_version, not do_show_version.
+       * nlmconv.c (program_version): Don't declare.
+       (main): Call print_version.
+       (show_usage): Print bug report address.
+       * nm.c (program_version, print_version): Don't declare.
+       (usage): Print bug report address.
+       (main): Call print_version.
+       * objcopy.c (program_version): Don't declare.
+       (copy_usage): Print bug report address.
+       (strip_usage): Likewise.
+       (strip_main): Call print_version.
+       (copy_main): Likewise.
+       * objdump.c (program_version): Don't declare.
+       (usage): Print bug report address.
+       (main): Call print_version.
+       * size.c (program_version): Don't declare.
+       (usage): Print bug report address.
+       (main): Call print_version.
+       * strings.c (program_version): Don't declare.
+       (main): Call print_version.
+       (usage): Print bug report address.
+       * Makefile.in: Update dependencies.
+
+Thu Sep 19 14:53:15 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c: Revert Monday's reflocalp patch, and apply this patch
+       instead:
+       (write_ieee_debugging_info): Write a dummy type at the end of the
+       global type block.
+
+Mon Sep 16 15:30:54 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c (struct ieee_write_type): Add reflocalp field.
+       (ieee_pointer_type): Set reflocalp after pushing type.
+       (ieee_function_type): If reflocalp is set, make this type local.
+       (ieee_range_type, ieee_array_type, ieee_set_type): Likewise.
+       (ieee_const_type, ieee_volatile_type): Likewise.
+       (ieee_struct_field, ieee_class_baseclass): Likewise.
+
+       * ieee.c (struct ieee_info): Add global_types field.
+       (parse_ieee_bb): When starting a BB1, initialize the types field
+       to the global_types field.
+       (parse_ieee_be): When ending a BB2, copy the types field to the
+       global_types field.
+
+Fri Sep 13 17:32:21 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (change_leading_char): New static variable.
+       (OPTION_CHANGE_LEADING_CHAR): Define.
+       (copy_options): Add "change-leading-char".
+       (copy_usage): Mention --change-leading-char.
+       (filter_symbols): Add obfd parameter.  Change all callers.
+       Implement change_leading_char.
+       (copy_object): Call filter_symbols if change_leading_char.
+       (copy_main): Handle OPTION_CHANGE_LEADING_CHAR.
+       * binutils.texi, objcopy.1: Document --change-leading-char.
+
+Tue Sep  3 14:05:29 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c (ieee_enum_type): Don't check index into a NULL names
+       array.
+       * nm.c (sort_symbols_by_size): Always initialize next.
+       * rdcoff.c (parse_coff_type): Warn about an incomprehensible
+       type rather than crashing.
+       * rddbg.c (read_symbol_stabs_debugging_info): Initialize f.
+       * stabs.c (parse_stab_members): Set context in all cases.
+
+Thu Aug 29 16:56:52 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * configure.in (i[345]86-*-*): Recognize i686 for pentium pro.
+       * configure: Regenerate.
+
+Thu Aug 29 11:29:20 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (L_tmpnam): Never define.
+       (display_target_list): Use choose_temp_base instead of tmpnam.
+       (display_info_table): Likewise.
+
+Tue Aug 27 18:15:01 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (parse_stab): An N_FUN symbol with an empty string
+       indicates the end of a function.
+
+Thu Aug 22 17:08:00 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * wrstabs.c (struct string_hash_entry): Add next field.
+       (struct stab_write_handle): Change strings to a pointer to
+       string_hash_entry.  Add last_strings field.  Remove strings_alloc
+       field.
+       (string_hash_newfunc): Initialize next field.
+       (stab_write_symbol): Copy string into hash table rather than into
+       buffer.  Keep a list of hash table entries.
+       (write_stabs_in_sections_debugging_info): Initialize last_string.
+       Copy strings from list of hash table entries in memory.
+       (stab_modify_type): If the entry on the stack is a definition,
+       make a new definition rather than failing an assert.
+       (stab_array_type): The size is only zero if high is strictly less
+       than low.
+
+       * ieee.c (struct ieee_info): Add saw_filename field.
+       (parse_ieee): Initialize saw_filename.
+       (parse_ieee_bb): Set saw_filename for a BB1 or BB2.  In a BB1,
+       discard the current variables and types.  In a BB10, if no
+       filename has been seen, call debug_set_filename.
+       (parse_ieee_ty): In case 'g', the type is optional.
+
+       * prdbg.c (pr_fix_visibility): Don't abort on
+       DEBUG_VISIBILITY_IGNORE.
+
+       * debug.c (debug_name_type): Correct error message.
+
+       * configure.in: Substitute HLDENV.
+       * configure: Rebuild.
+       * Makefile.in (HLDENV): New variable.  Use it whenever linking a
+       program.
+
+Thu Aug 15 19:30:41 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-make.sed: Add symbolic doublequotes around the version
+       number.
+
+Thu Aug  8 12:27:52 1996  Klaus Kaempf  <kkaempf@progis.de>
+
+       * makefile.vms: Add better support for DEC C compilation.
+       Add new macros as in Makefile.in.
+
+Wed Aug  7 14:27:33 1996  Philippe De Muyter  <phdm@info.ucl.ac.be>
+
+       * configure.in: Call BFD_NEED_DECLARATION on strstr and sbrk.
+       * acconfig.h (NEED_DECLARATION_STRSTR): New macro.
+       (NEED_DECLARATION_SBRK): New macro.
+       * configure, config.in: Rebuild.
+       * bucomm.h (strstr): Declare if NEED_DECLARATION_STRSTR.
+       (sbrk): Declare if HAVE_SBRK and NEED_DECLARATION_SBRK.
+
+       * prdbg.c (pr_end_struct_type): Avoid using a string constant in
+       assert, for the benefit of broken assert macros.
+
+Fri Jul 26 14:06:50 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (disassemble_data): Set disasm_info.flavour from
+       abfd.
+
+Tue Jul 23 13:59:54 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.c (secdata): In non DLLTOOL_PPC case, change alignment
+       of .text section to 2.
+
+Mon Jul 22 08:46:15 1996  Stu Grossman  (grossman@lisa.cygnus.com)
+
+       * objdump.c (dump_section_stabs):  Fix test for stabs sections
+       ending with numbers.  This fixes a problem with .stab being
+       confused with .stab.index.
+
+Wed Jul 10 13:32:28 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (stab_demangle_fund_type): Return a void * for a
+       template, rather than simply aborting.
+
+Mon Jul  8 15:28:05 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ar.c (open_inarch): Add file parameter.  Change all callers.  If
+       this is a newly created archive, set the target based on the
+       file.
+       * arsup.h (open_inarch): Update declaration.
+
+Thu Jul  4 12:00:55 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (VERSION): Set to cygnus-2.7.1.
+
+       * Released binutils 2.7.
+
+       * rdcoff.c (parse_coff): Get address to pass to debug_end_function
+       from function size, not value of .ef symbol.  From Ning
+       Mosberger-Tang <ning@AZStarNet.com>.
+
+Sat Jun 29 21:18:09 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (strip_main): Add -o option, and handle it.
+       (strip_usage): Mention -o.
+       * binutils.texi, strip.1: Mention -o.
+
+Mon Jun 24 17:19:02 1996  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir,
+       INSTALL_PROGRAM, INSTALL_DATA): Use autoconf set values.
+       (docdir): Removed.
+       * configure.in (AC_PREREQ): Autoconf 2.5 or higher.
+
+Mon Jun 24 11:59:13 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (endian): New static variable.
+       (usage): Mention -EB/-EL/--endian.
+       (long_options): Add "endian".
+       (disassemble_data): If endianness was specified, replace
+       abfd->xvec with a copy of itself with the given endianness.
+       (main): Handle -EB/-EL/--endian.
+       * binutils.texi, objdump.1: Mention -EB/-EL/--endian.
+
+       * objdump.c: Make most variables and functions static.
+
+       * configure.in: On alpha*-*-osf*, link against libbfd.a if not
+       using shared libraries.
+       * configure: Rebuild with autoconf 2.10.
+
+Sun Jun 23 14:47:36 1996  Kim Knuttila  <krk@cygnus.com>
+
+       * dlltool.c (secdata): Changed .rdata to .reldata so .reloc will work.
+       (make_one_lib_file): Removed cruft. (#if 1)
+
+Wed Jun 19 14:46:38 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (stabs): Change from struct internal_nlist * to
+       bfd_byte *.
+       (print_section_stabs): Fetch stabs information directly, rather
+       than assuming that struct internal_nlist is the right size.
+
+       * binutils.texi: Document change to binary format: file position
+       based on load address, not section VMA.
+
+       * bucomm.h: Define SEEK_SET, SEEK_CUR, and SEEK_END if they are
+       not already defined.
+
+Tue Jun 18 18:25:00 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (DISTSTUFF): Add deflex.c.
+
+Tue Jun 18 15:03:44 1996  Klaus Kaempf  <kkaempf@progis.de>
+
+       * config.h-vms, makefile.vms: New files.
+
+Mon Jun 17 09:47:31 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.c (make_one_lib_file): Use BFD_RELOC_RVA rather than
+       BFD_RELOC_32 in IDATA7.
+
+Wed Jun 12 11:52:06 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * nm.c (struct get_relocs_info): Define.
+       (line_numbers): New static variable.
+       (long_options): Add "line-numbers".
+       (usage): Mention -l and --line-numbers.
+       (main): Handle -l.
+       (print_symbol): Print line numbers if requested.
+       (get_relocs): New static function.
+       * binutils.texi, nm.1: Document -l/--line-numbers.
+
+Tue Jun 11 20:12:15 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (dump_reloc_set): Add sec parameter.  Change all
+       callers.  If with_line_numbers is set, display line numbers of
+       relocation entries.
+       * binutils.texi, objdump.1: Document -l with -r.
+
+Mon Jun 10 23:42:59 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ar.c (open_inarch): Report BFD error message if an archive can
+       not be recognized.  List matching formats if the file is
+       ambiguously recognized.
+       (ranlib_touch): Likewise.
+
+Thu Jun  6 13:56:14 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * README: Add notes on how to build if you don't have ar.
+
+       * Makefile.in: Remove old incorrect setting of CC.
+
+Tue Jun  4 10:52:49 1996  Tom Tromey  <tromey@csk3.cygnus.com>
+
+       * Makefile.in (install): Don't check to see if tooldir exists.
+       Make $(tooldir) and $(tooldir)/bin.
+
+Mon Jun  3 17:40:23 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * strings.c (main): Make main an int function, not void.
+
+Fri May 31 13:59:24 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * nm.c (filter_symbols): Check for BSF_WEAK as well as
+       BSF_GLOBAL.
+       * objcopy.c (filter_symbols): Likewise.
+
+Wed May  8 16:57:20 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (copy_object): Make clear that it is only a warning
+       when the output file can not represent the architecture.
+
+Fri May  3 11:30:17 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (disassemble_data): Don't refer to bytes past the end
+       of data.
+
+Wed Apr 24 14:10:21 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * rddbg.c (read_symbol_stabs_debugging_info): Move call to
+       free_saved_stabs outside the loop over the symbols.
+
+Tue Apr 23 12:56:11 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (compare_symbols): Sort symbols whose names start with
+       `.' after other symbols.  If no other decision can be made, sort
+       symbols by name.
+
+Thu Apr 18 16:02:11 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dep-in.sed: Substitute $(BFDDIR) for @BFDDIR@.
+       * Makefile.in: Rebuild dependencies.
+       (dep.sed): Substitute $(BFDDIR) for @BFDDIR@.
+
+Tue Apr 16 13:50:22 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * rdcoff.c: New file.
+       * rddbg.c (read_debugging_info): Read COFF symbols if COFF flavour
+       and no stabs were found.
+       * budbg.h (parse_coff): Declare.
+       * Makefile.in: Rebuild dependencies.
+       (CFILES): Add rdcoff.c.
+       (DEBUG_OBJS): Add rdcoff.o.
+
+Mon Apr 15 15:55:01 1996  Doug Evans  <dje@canuck.cygnus.com>
+
+       * nlmconv.c (choose_temp_base{,_try}): Delete, in libiberty now.
+       (link_inputs): Update call to choose_temp_base.
+
+Mon Apr  8 14:40:05 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Permit --enable-shared to specify a list of
+       directories.
+       * configure: Rebuild.
+
+Fri Mar 29 16:11:33 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (dump_section_header): Print the SEC_LINK_ONCE flag
+       and the SEC_LINK_DUPLICATES field.
+
+Fri Mar 29 11:35:55 1996  J.T. Conklin  (jtc@lisa.cygnus.com)
+
+       * nlmconv.1: Changed to be recognized by catman -w on Solaris.
+
+Thu Mar 28 14:17:02 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * wrstabs.c (stab_enum_type): Set buf before using it.
+
+Fri Mar 22 15:49:08 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (struct stab_handle): Add field abfd.
+       (start_stab): Add abfd parameter.
+       (parse_stab_string): Skip the symbol leading char when searching
+       for the value of a global symbol.
+       * budbg.h (start_stab): Update declaration.
+       * rddbg.c (read_section_stabs_debugging_info): Pass abfd to
+       start_stab.
+       (read_symbol_stabs_debugging_info): Likewise.
+
+Thu Mar 21 12:40:48 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * wrstabs.c (stab_function_type): Output an empty typedef for an
+       unused argument, rather than making up a meaningless name.
+       (stab_variable): Use N_RSYM for a DEBUG_REGISTER variable.
+
+       * ieee.c (struct ieee_info): Add global_vars field.
+       (parse_ieee_be): When ending the global typedef block, copy the
+       variables into info->global_vars.
+       (parse_ieee_atn): Don't require an NN record for a pmisc ATN.
+       (ieee_read_reference): Search the global variables after the local
+       variables.
+
+Wed Mar 20 18:08:19 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * objdump.c (disassemble_data): Make sure sym_name is always set.
+       (dump_section_header): Always put a space after the section name.
+       (dump_bfd_header): Terminate output with newline.
+
+Wed Mar 20 16:35:20 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * wrstabs.c: New file.
+       * budbg.h (write_stabs_in_sections_debugging_info): Declare.
+       * objcopy.c (write_debugging_info): For COFF or ELF, output stabs
+       in sections.
+       * Makefile.in: Rebuild dependencies.
+       (CFILES): Add wrstabs.c.
+       (WRITE_DEBUG_OBJS): New variable.
+       ($(OBJCOPY_PROG)): Use $(WRITE_DEBUG_OBJS), not $(DEBUG_OBJS).
+       ($(STRIP_PROG)): Likewise.
+
+       * stabs.c (parse_stab_members): Make type stub detection more like
+       gdb.
+
+       * ieee.c (struct ieee_handle): Add fields complex_float_index and
+       complex_double_index.
+       (ieee_complex_type): Cache type index in complex_float_index and
+       complex_double_index, depending upon size.  Set size on type stack
+       to size * 2.
+
+       * ieee.c (ieee_empty_type): Use builtin_unknown, not 0.
+       (ieee_void_type): Use builtin_void, not 1.
+
+       * ieee.c (parse_ieee_ty): Handle 'V' type code.
+       (parse_ieee_atn): Don't require two numbers for type 10.
+
+       * ieee.c (parse_ieee_be): Add one to offset at end of function or
+       block.
+
+       * ieee.c (struct ieee_block): Add field skip.
+       (parse_ieee_bb): Don't call debug_record_function for __XRYCPP
+       function, and set skip field.
+       (parse_ieee_be): Don't call debug_end_function if skip is set.
+
+       * debug.c (struct debug_handle): Add fields current_write_lineno
+       and current_write_lineno_index.
+       (debug_write): Initialize current_write_lineno and
+       current_write_lineno_index for each unit.  Call
+       debug_write_linenos rather than writing out the line numbers
+       directly.
+       (debug_write_function): Call debug_write_linenos.
+       (debug_write_block): Likewise.
+       (debug_write_linenos): New static function.
+
+       * debug.c (debug_write_type): For DEBUG_KIND_FUNCTION, push return
+       type before arguments.
+
+Mon Mar 18 18:05:33 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Add AC_FUNC_VFORK.
+       * configure, config.in: Rebuild.
+       * dlltool.c, nlmconv.c: Include <vfork.h> if HAVE_VFORK_H is
+       defined.
+
+       * stabs.c (parse_stab_range_type): A complex type is defined as a
+       subrange of itself with the high bound zero.
+       * ieee.c (ieee_complex_type): Don't crash on sizes of 12 or 16.
+
+Tue Mar 12 12:09:43 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c (ieee_write_undefined_tag): Switch to global_types even
+       if it is not empty.
+       (ieee_tag_type): For an enum, look through info->enums.
+
+       * configure: Rebuild with autoconf 2.8.
+
+       * debug.c (debug_type_samep): Don't loop endlessly in
+       DEBUG_KIND_ENUM case.  From Eric Baur <ecb@nexen.com>.
+
+Mon Mar 11 12:35:03 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * rddbg.c (read_section_stabs_debugging_info): Call save_stab for
+       each stab entry, call stab_context on an error, and call
+       free_saved_stabs before rturning.
+       (read_symbol_stabs_debugging_info): Likewise.
+       (SAVE_STABS_COUNT): Define.
+       (struct saved_stab): Define.
+       (saved_stabs, saved_stabs_index): New static variables.
+       (save_stab, stab_context, free_saved_stabs): New static functios.
+
+       * objdump.c (stab_name): Remove.
+       (struct stab_print): Remove.
+       (stab_print): Remove.
+       (dump_stabs): Don't initialize stab_name.
+       (print_section_stabs): Call bfd_get_stab_name rather than using
+       the stab_name array.
+
+Tue Feb 27 19:52:01 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * prdbg.c (pr_int_constant): Initialize info correctly.
+       (pr_float_constant): Likewise.
+
+Mon Feb 26 18:11:37 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-make.sed: Update to handle shared library support.
+
+Sat Feb 24 11:21:49 1996  Alan Modra  <alan@spri.levels.unisa.edu.au>:
+
+       * Makefile.in ($(OBJDUMP_PROG)): Search $(BFDLIB) before
+       $(OPCODES).
+
+Thu Feb 15 12:44:45 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Don't tamper with LDFLAGS.  Call AC_PROG_CC before
+       configure.host.
+       * configure: Rebuild.
+
+       * configure.in: Substitute RPATH_ENVVAR.
+       * configure: Rebuild.
+       * Makefile.in (RPATH_ENVVAR): New variable.
+       (check): Use $(RPATH_ENVVAR) rather than LD_LIBRARY_PATH.
+
+       * objcopy.c (smart_rename): Rather than doing chmod then chown, do
+       chmod without setuid, then chown, then chmod with setuid.
+
+Wed Feb 14 16:46:42 1996  Martin Anantharaman  <martin@mail.imech.uni-duisburg.de>
+
+       * arsup.c (map_over_list): Reindent.  Don't assume that the
+       function does not delete the BFD.
+       (ar_addlib_doer): Don't set prev->next if prev is NULL.
+
+Wed Feb 14 15:12:17 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c (ieee_regno_to_genreg): Convert register numbers for m68k
+       and i960.
+       (ieee_genreg_to_regno): Likewise.
+
+Mon Feb 12 14:19:59 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c: Extensive changes to write code to put types in the
+       global type block when possible, to output ranges for all memory
+       occupied by the module, and to improve efficiency.
+
+       * debug.c (struct debug_handle): Remove class_mark field.  Add
+       id_list and compare_list fields.
+       (struct debug_class_id): Define.
+       (struct debug_type_compare_list): Define.
+       (debug_write): Initialize info->id_list
+       (debug_write_name): Remove reference to info->class_mark.
+       (debug_write_type): Get id for all structs and classes.  Simplify
+       test for whether struct has already been written.
+       (debug_write_class_type): Get id for all classes.  Simplify test
+       for whether class has already been written.
+       (debug_write_block): Don't write out blocks other than the top
+       level block if they have no local variables.
+       (debug_set_class_id): New static function.
+       (debug_type_samep): New static function.
+       (debug_class_type_samep): New static function.
+       * prdbg.c (pr_start_struct_type): Always print id.
+       (pr_start_class_type): Likewise.
+       (pr_tag_type): Likewise.
+
+       * stabs.c (struct stab_handle): Add syms and symcount fields.
+       (start_stab): Add syms and symcount parameters.  Change all
+       callers.
+       (parse_stab_string): Look up global variables in the symbol table
+       to get the right value.
+       * budbg.h (start_stab): Update declaration.
+       * rddbg.c (read_section_stabs_debugging_info): Add syms and
+       symcount parameters.  Change all callers.
+
+       * stabs.c (parse_stab_array_type): If the index type is 0, use
+       int.
+
+Wed Feb  7 14:17:45 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c (ieee_start_compilation_unit): Clear modified and
+       modified_alloc fields of info.
+
+       * configure.in: Check for --enable-shared.  Substitute new
+       variables BFDLIB and OPCODES.
+       * configure: Rebuild.
+       * Makefile.in (BFDLIB): Set to @BFDLIB@.
+       (OPCODES): Set to @OPCODES@.
+
+Mon Feb  5 16:18:42 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       Support for building bfd and opcodes as shared libraries, based on
+       patches from Alan Modra <alan@spri.levels.unisa.edu.au>:
+       * configure.in (HLDFLAGS): New substitution.
+       * configure: Rebuild.
+       * Makefile.in (HLDFLAGS): New variable.  Make all links use
+       $(HLDFLAGS) before $(CFLAGS) and $(LDFLAGS).
+       (BFDLIB_DEP): New variable.  Replace all occurrences of $(BFD) as
+       a dependency with $(BFDLIB_DEP).  Remove $(BFD) as a dependency if
+       there is also a dependency on $(ADDL_DEPS).
+       (BFDLIB): Rename from BFD; change all uses; set to -L../bfd -lbfd.
+       (OPCODES_DEP): New variable.  Replace all occurrends of $(OPCODES)
+       as a dependency with $(OPCODES_DEP).
+       (OPCODES): Set to -L../opcodes -lopcodes.
+       (ADDL_DEPS): New variable.  Replace all occurrences of
+       $(ADDL_LIBS) as a dependency with $(ADDL_DEPS).
+       (check): Set LD_LIBRARY_PATH in the environment.
+       (config.status): Depend upon BFD configure.host and config.bfd.
+
+Fri Feb  2 17:02:59 1996  Doug Evans  <dje@charmed.cygnus.com>
+
+       * objdump.c: #include stdarg.h or varargs.h.
+       (objdump_print_value): Change FILE* arg to struct disassemble_info*.
+       All callers updated.  Use fprintf_func.
+       (objdump_print_address): Consistently use fprintf_func.
+       (objdump_sprintf): New function.
+       (disassemble_data): Print insn into a buffer, print raw insn ourselves,
+       then print insn mnemonic.
+
+Fri Feb  2 16:48:55 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure: Regenerate.
+
+Thu Feb  1 09:38:18 1996  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * configure.in (i[3-6]86-*-win32): Becomes i[3-6]86-*-cygwin32.
+       (powerpc*-*-cygwin32): New.
+       * configure: Regenerated.
+
+Wed Jan 31 13:22:03 1996  Richard Henderson  <rth@tamu.edu>
+
+       * Makefile.in (distclean): Remove $(DEMANGLER_PROG).1.
+
+Mon Jan 29 17:36:29 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       Based on patches from H J Lu <hjl@zoom.com>:
+       * objcopy.c (remove_leading_char): New static variable.
+       (OPTION_REMOVE_LEADING_CHAR): Define.
+       (copy_usage): Mention --remove-leading-char.
+       (filter_symbols): If remove_leading_char, and the first character
+       of a global symbol matches the symbol leading char of the BFD,
+       remove the first character.
+       (copy_object): Filter the symbols if remove_leading_char is set.
+       (copy_main): Handle --remove-leading-char.
+       * binutils.texi, objcopy.1: Document --remove-leading-char.
+
+Sat Jan 27 15:40:13 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * objdump.c (fprintf): Add prototype to avoid compiler warning on
+       SunOS.
+
+Fri Jan 26 11:53:42 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils.texi (nm): Improve documentation on symbol types.
+       (objdump): Reference the stabs manual from the discussion of the
+       --stabs option.
+
+Thu Jan 25 11:21:46 1996  Raymond Jou  <rjou@mexican.cygnus.com>
+
+       * mpw-make.sed: Add a "stamps" target.
+
+Thu Jan 25 13:51:44 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (dump_headers, dump_section_header): Change objdump -h
+       output to be simpler and to include section file offsets.
+
+Wed Jan 24 12:06:05 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * stabs.c (parse_stab_members): Don't adjust voffset.
+
+       * ieee.c (ieee_read_cxx_class): Don't multiply voffset by 4.
+       (struct ieee_write_type): Add name field.
+       (struct ieee_type_class): Remove name field.  Change all uses to
+       use new name field in type instead.
+       (struct ieee_name_type): Likewise.
+       (ieee_start_struct_type): Initialize name field of type.
+       (ieee_start_class_type): Don't initialize classdef entry of tag.
+       (ieee_class_method_var): Don't adjust voffset.
+       (ieee_end_class_type): Likewise.
+       (ieee_tag_type): Initialize new name field of type.
+       (ieee_typdef): Set name after copying in type information.
+
+       * debug.c (VOFFSET_STATIC_METHOD): Define as -1, not 1.
+
+       * ieee.c (struct ieee_modified_type): Define.
+       (struct ieee_handle): Add modified and modified_alloc fields.
+       (ieee_get_modified_info): New static function.
+       (ieee_pointer_type): Cache type index.
+       (ieee_const_type): Likewise.
+       (ieee_volatile_type): Likewise.
+
+       * ieee.c (ieee_define_named_type): When creating a tag for an
+       anonymous struct, copy the name into memory.
+       (ieee_tag_type): Likewise.
+       * debug.c (debug_write_type): Only check and set id field for an
+       unnamed object.
+       (debug_write_class_type): Likewise.
+
+       * ieee.c: Various changes to write out types for functions and
+       references, and to not write out unnecessary function types.
+
+       * ieee.c (struct ieee_var): Remove variable field.  Add kind
+       field, and define some enum constants for it.
+       (parse_ieee_ty): Set kind field of variable for 'x' and 'X' types.
+       (parse_ieee_atn): Make an indirect slot for an external variable,
+       although we otherwise don't record it.  Set kind field rather than
+       variable field of pvar.
+       (ieee_read_cxx_class): Try to get the type of a static member.
+       (ieee_read_reference): Check kind field rather than variable
+       field.
+
+Tue Jan 23 15:54:18 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c: Various changes to handle reading C++ reference type
+       information.
+
+       * debug.h (enum debug_var_kind): Add DEBUG_VAR_ILLEGAL.
+       (enum debug_parm_kind): Add DEBUG_PARM_ILLEGAL.
+       * debug.c (debug_get_parameter_types): Handle DEBUG_KIND_FUNCTION.
+
+       * ieee.c: Various changes to write out definitions of C++ classes.
+
+       * debug.c (debug_append_filename): Remove.
+       * debug.h (debug_append_filename): Don't declare.
+
+       * stabs.c (struct stab_handle): Remove last_type field.  Add
+       so_string and so_value fields.
+       (finish_stab): Call stab_emit_pending_vars before calling
+       debug_end_function.  Don't warn about pending variables.
+       (parse_stab): Accumulate N_SO strings until a non N_SO symbol is
+       seen, rather than calling debug_append_filename.  Call
+       stab_emit_pending_vars before calling debug_end_function.  Don't
+       set info->last_type.
+
+Tue Jan 23 09:53:54 1996  Doug Evans  <dje@charmed.cygnus.com>
+
+       * objdump.c (disassemble_data): Handle unknown endianness.
+       Pass fprintf to INIT_DISASSEMBLE_INFO.
+
+Mon Jan 22 16:46:43 1996  Doug Evans  <dje@charmed.cygnus.com>
+
+       Add new option --show-raw-insn.
+       * objdump.c (show_raw_insn): New global.
+       (usage): Update.
+       (long_options): Update.
+       (disassemble_data): Set disasm_info.flags if --show-raw-insn.
+
+       * objdump.c (disassemble_data): Set new arch,mach,endian fields in
+       disasm_info.
+
+Mon Jan 22 19:29:36 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c: Extensive changes to pass a single info argument around
+       in the reading routines, rather than several arguments.  Add code
+       to read C++ debugging records.
+
+       * debug.h (debug_get_type_size): Declare.
+       (debug_get_field_name): Declare.
+       (debug_get_field_bitpos): Declare.
+       (debug_get_field_bitsize): Declare.
+       (debug_get_field_visibility): Declare.
+       (debug_get_field_physname): Declare.
+       * debug.c (debug_get_real_type): Handle DEBUG_KIND_TAGGED.
+       (debug_get_type_size): New function.
+       (debug_get_field_name): New function.
+       (debug_get_field_bitpos): New function.
+       (debug_get_field_bitsize): New function.
+       (debug_get_field_visibility): New function.
+       (debug_get_field_physname): New function.
+       (debug_write_type): Make sure we pass the real kind, not INDIRECT,
+       to tag_type.  Pass the name recursively for INDIRECT.
+
+Fri Jan 19 12:31:57 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * debug.h (struct debug_write_fns): Remove ellipsis_type.  Add int
+       and boolean parameters to function_type.  Add boolean parameter to
+       method_type.
+       (debug_make_ellipsis_type): Don't declare.
+       (debug_make_function_type): Add debug_type * and boolean
+       parameters.  Change all callers.
+       (debug_make_method_type): Add boolean parameter.  Change all
+       callers.
+       (debug_get_parameter_types): Add boolean * parameter.  Change all
+       callers.
+       (debug_get_target_type): Declare.
+       * debug.c (struct debug_function_type): Add fields arg_types and
+       varargs.
+       (struct debug_method_type): Add field varargs.
+       (debug_ellipsis_type, ELLIPSIS_P): Remove.
+       (debug_make_ellipsis_type): Remove.
+       (debug_make_function_type): Add arg_types and varargs parameters.
+       (debug_make_method_type): Add varargs parameter.
+       (debug_get_parameter_types): Add pvarargs parameter.
+       (debug_get_target_type): New function.
+       (debug_write_type): In case DEBUG_KIND_FUNCTION, push argument
+       types and pass count to function_type.  In DEBUG_KIND_METHOD, use
+       a signed int for the count, don't call ellipsis_type, and pass
+       varargs to method_type.
+       * stabs.c (struct stab_demangle_info): Add varargs field.
+       (stab_demangle_argtypes): Add pvarargs parameter.  Change all
+       callers.
+       (stab_demangle_args): Likewise.
+       (stab_demangle_type): In case 'F', pick up argument types.
+       * prdbg.c (pr_ellipsis_type): Remove.
+       (pr_function_type): Add argcount and varargs parameters.
+       (pr_method_type): Add varargs parameter.
+       * ieee.c (ieee_ellipsis_type): Remove.
+       (ieee_function_type): Add argcount and varargs parameters.
+       (ieee_method_type): Add varargs parameter.  Remove most of
+       function body, and just call ieee_function_type.
+
+       * stabs.c: Include "demangle.h".  Added several new static
+       functions not listed below to demangle argument types; they are
+       all called via stab_demangle_argtypes.
+       (finish_stab): If the kind of an undefined tag is
+       DEBUG_KIND_ILLEGAL, use DEBUG_KIND_STRUCT instead.  Warn if there
+       are any pending variable.
+       (parse_stab): Don't close the function when the block depth goes
+       to zero.  Pass value to debug_end_function.
+       (parse_stab_string): In case 'T', pass the name to
+       parse_stab_type.
+       (parse_stab_type): In case 'x', use stab_find_tagged_type.  In
+       case '#', handle functions with variable numbers of arguments.
+       (parse_stab_struct_type): Add tagname parameter.  Change all
+       callers.
+       (parse_stab_members): Add tagname and typenums parameters.  Change
+       all callers.  If the type of a method is a stub, call
+       parse_stab_argtypes to demangle the argument types and get the
+       physical name of the function.
+       (parse_stab_argtypes): New static function.
+       (stab_record_variable): For a DEBUG_GLOBAL or DEBUG_STATIC
+       variable, call debug_record_variable immediately.
+       (stab_find_tagged_type): New static function.
+
+       * debug.h (enum debug_type_kind): Add DEBUG_KIND_ILLEGAL.
+       (struct debug_write_fns): Add field ellipsis_type.  Add id
+       parameter to start_struct_type, start_class_type, and tag_type.
+       (debug_make_ellipsis_type): Declare.
+       (debug_find_named_type): Declare.
+       (debug_get_type_kind): Declare.
+       (debug_get_return_type): Declare.
+       (debug_get_parameter_types): Declare.
+       (debug_get_fields): Declare.
+       (debug_get_field_type): Declare.
+       * debug.c (struct debug_handle): Add fields class_id and base_id.
+       (struct debug_class_type): Add field id.
+       (struct debug_method_variant): Rename argtypes to physname.
+       Change all uses.
+       (debug_ellipsis_type): New static variable.
+       (ELLIPSIS_P): New macro.
+       (debug_make_ellipsis_type): New function.
+       (debug_make_method_variant): Rename argtypes to physname.
+       (debug_make_static_method_variant): Likewise.
+       (debug_name_type): Always put types in the global namespace.
+       (debug_find_named_type): New function.
+       (debug_find_tagged_type): Treat DEBUG_KIND_ILLEGAL specially,
+       rather than DEBUG_KIND_VOID.
+       (debug_get_real_type): New static function.
+       (debug_get_type_kind): New function.
+       (debug_get_return_type): New function.
+       (debug_get_parameter_types): New function.
+       (debug_get_fields): New function.
+       (debug_get_field_type): New function.
+       (debug_write): Initialize base_id.
+       (debug_write_type): Pass new id argument to tag_type.  Handle
+       DEBUG_KIND_ILLEGAL.  Use id for DEBUG_KIND_STRUCT and
+       DEBUG_KIND_UNION.  Handle ellipsis for method arguments.
+       (debug_write_class_type): Don't dereference kclass if it is NULL.
+       Use id.
+       * prdbg.c (pr_fns): Add pr_ellipsis_type.
+       (pr_ellipsis_type): New static function.
+       (pr_pointer_type): If this is a pointer to an array, parenthesize
+       it correctly.
+       (pr_start_struct_type): Add id parameter.
+       (pr_start_class_type): Likewise.
+       (pr_tag_type): Likewise.
+       (pr_fix_visibility): Add the visibility to the top of the stack,
+       not the second element on the stack.
+       (pr_struct_field): Pop the stack before calling pr_fix_visibility.
+       (pr_class_static_member): Likewise.
+       (pr_class_start_method): Don't push a type, just set the method
+       name in the type on the top of the stack.
+       (pr_class_end_method): Don't pop the stack.
+       (pr_class_method_variant): Rename argtypes parameter to physname.
+       Append const and volatile rather than prepending them.  Add a
+       space after the physname.
+       (pr_class_static_method_variant): Likewise.
+       * ieee.c (ieee_fns): Add ieee_ellipsis_type.
+       (ieee_define_named_type): Use DEBUG_KIND_ILLEGAL rather than
+       DEBUG_KIND_VOID.
+       (write_ieee_debugging_info): Likewise.
+       (ieee_typdef): Likewise.
+       (ieee_ellipsis_type): New static function.
+       (ieee_start_struct_type): Add id parameter.
+       (ieee_start_class_type): Likewise.
+       (ieee_tag_type): Likewise.
+       (ieee_class_method_variant): Rename name to physname.
+       (ieee_class_static_method_variant): Likewise.
+
+       * Makefile.in (DEBUG_OBJS): Remove prdbg.o.
+       ($(OBJDUMP_PROG)): Depend upon, and link against, prdbg.o.
+
+Thu Jan 18 17:35:06 1996  Kim Knuttila  <krk@cygnus.com>
+
+       * dlltool.c (make_tail): Changed the order of the sections to avoid
+       an alignment problem.
+
+Wed Jan 17 14:23:00 1996  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * srconv.c (wr_du): Set du.stackfrmt to 0.
+       (wr_un, wr_sc): Emit all sections, even those with 0 size.
+
+Tue Jan 16 16:15:49 1996  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * srconv.c (wr_hd): Space size within segment was being
+       stored in segment identifier field.
+
+Tue Jan 16 12:07:25 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-config.in (BUILD_NLMCONV, BUILD_SRCONV, SYSINFO_PROG,
+       BUILD_DLLTOOL): Put definitions for these into makefile when
+       configuring, instead of always clearing in mpw-make.sed.
+       * mpw-make.sed: Edit out any host_alias or target_alias settings,
+       fix pathname to BFD internal include files, remove dependency
+       calculation rules.
+
+Thu Jan 11 17:31:38 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * objdump.c (dump_section_header): Add new section flags
+       SEC_{EXCLUDE,SORT_ENTRIES}.
+
+Thu Jan 11 11:45:34 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (filter_symbols): NULL terminate the output symbols.
+       (copy_object): Allocate space for a possible extra NULL pointer.
+
+       * debug.c (debug_make_undefined_tagged_type): Make sure we are
+       given a kind of type we can handle.
+       (debug_write_type): Handle undefined enums and structs.
+       (debug_write_class_type): Handle undefined classes.
+       * prdbg.c (pr_enum_type): Handle an undefined enum.
+       * ieee.c (ieee_enum_type): Likewise.
+
+Wed Jan 10 15:33:18 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in: Updated dependencies.
+       (ALLOCA, MALLOC): Remove variables.
+       (ADDL_LIBS): Remove $(MALLOC) from definition.
+       * alloca.c, gmalloc.c: Remove.
+
+Mon Jan  8 18:02:29 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c: Add global function write_ieee_debugging_info and a
+       bunch of static functions and structs used to write out IEEE
+       debugging information.
+       * budbg.h (write_ieee_debugging_info): Declare.
+
+       * ieee.c (struct ieee_type): Add pslot field.
+       (enum builtin_types): Define.
+       (ieee_builtin_type): For a pointer, return a pointer to the named
+       type.  Use enum values rather than numbers.
+       (ieee_alloc_type): New static function.
+       (ieee_read_type_index): Use ieee_alloc_type.
+       (parse_ieee_bb): Likewise.
+       (parse_ieee_ty): Likewise.  Use ieee_builtin_type for array range,
+       rather than making a new integer type.  Store the new type in the
+       slot, if there is one.
+       (parse_ieee_atn): Treat ATN10 as defining a register variable.
+       (ieee_regno_to_genreg): Rename from ieee_regno_to_gen.  Change all
+       callers.
+       (ieee_genreg_to_regno): New static function.
+
+       * stabs.c (parse_stab_type): Add new typename parameter.  Change
+       all callers.
+       (parse_stab_range_type): Add new typename parameter.  Change all
+       callers.
+
+       * debug.h (struct debug_write_fns): Add tag parameter to
+       enum_type, start_struct_type, and start_class_type.
+       * debug.c (debug_write_type): Pass any tag name to
+       start_struct_type, debug_write_class_type, and enum_type.  If
+       DEBUG_KIND_TAGGED, pass the name in the recursive call.
+       (debug_write_class_type): Accept a new tag parameter, and pass it
+       to start_class_type.
+       * prdbg.c (pop_type): Don't remove '+' character.
+       (pr_enum_type): Accept and use tag parameter.
+       (pr_start_struct_type): Likewise.
+       (pr_start_class_type): Likewise.
+       (pr_class_baseclass): Adjust algorithm used to find where to put
+       the baseclass name.
+       (pr_tag): Don't bother to insert the tag name.
+
+       * objcopy.c: Include budbg.h.
+       (convert_debugging): New static variable.
+       (OPTION_DEBUGGING): Define.
+       (copy_options): Add "debugging".
+       (copy_usage): Mention --debugging.
+       (is_strip_section): Skip debugging sections if convert_debugging.
+       (setup_section, copy_section): Likewise.
+       (filter_symbols): Skip debugging symbols if convert_debugging.
+       (copy_object): If convert_debugging, read and write debugging
+       information.
+       (write_debugging_info): New static function.
+       (copy_main): Handle --debugging.
+       * Makefile.in (DEBUG_OBJS): New variable.
+       ($(OBJCOPY_PROG)): Depend upon and link against $(DEBUG_OBJS).
+       ($(STRIP_PROG)): Likewise.
+       (OBJDUMP_OBJS): Remove variable.
+       ($(OBJDUMP_PROG)): Use objdump.o $(DEBUG_OBJS) rather than
+       $(OBJDUMP_OBJS).
+       * binutils.texi, objcopy.1: Document --debugging.
+
+Thu Jan  4 16:31:21 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ieee.c: New file with code to read IEEE debugging information.
+       * budbg.h (parse_ieee): Declare.
+       * rddbg.c (read_debugging_info): Handle IEEE flavour files.
+       (read_ieee_debugging_info): New static function.
+       * Makefile.in: Rebuild dependencies.
+       (CFILES): Add ieee.c.
+       (OBJDUMP_OBJS): Add ieee.o.
+
+       * bucomm.h (xrealloc): Change type of first parameter from char *
+       to PTR.
+
+Tue Jan  2 17:44:07 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in: Add targets to automatically rebuild dependencies.
+       Remove targets which just listed dependencies of .o files.
+       (DEP): New variable.
+       (HFILES, GENERATED_HFILES): New variables.
+       (CFILES, GENERATED_CFILES): New variables.
+       (underscore.c): Don't do anything, just depend upon stamp-under.
+       (stamp-under): New target; do what underscore.c used to do.
+       (nlmconv.o): Depend upon sym.h and ecoff.h.
+       (.dep, .dep1, dep.sed, dep, dep-in): New targets.
+       (stage1, stage2, stage3, against, comparison): Remove.
+       (de-stage1, de-stage2, de-stage3): Remove.
+       (clean, distclean): Remove stamp-under and dep.sed.
+       * dep-in.sed: New file.
+
+       Implement generic debugging support.  Implement a stabs reader and
+       a generic printer.
+       * budbg.h, debug.c, debug.h, prdbg.c, rddbg.c, stabs.c: New files.
+       * objdump.c: Include "debug.h" and "budbg.h".
+       (dump_debugging): New global variable.
+       (usage): Mention --debugging.
+       (long_options): Add "debugging".
+       (display_bfd): Handle --debugging.
+       * Makefile.in (OBJDUMP_OBJS): New variable.
+       ($(OBJDUMP_PROG)): Use $(OBJDUMP_OBJS).
+       * binutils.texi, objdump.1: Document --debugging.
+
+Sat Dec 30 09:59:51 1995  Jeffrey A Law  (law@cygnus.com)
+
+       * nm.c ( long_options): Add "--defined-only" option.
+       (usage): Update for new "--defined-only" option.
+       (filter_symbols): Handle "--defined-only".
+
+Fri Dec 29 16:04:56 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * arparse.y: Include "bucomm.h", not <sysdep.h>.
+       * nlmheader.y: Don't include "sysdep.h".
+
+Tue Dec 26 18:23:18 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * nm.c (print_symdef_entry): Check return value of
+       bfd_get_elt_at_index.
+
+Sat Dec 23 11:03:16 1995  Michael Meissner  <meissner@tiktok.cgynsu.com>
+
+       * configure.in (DLLTOOL_DEFS): Build dlltool for PowerPC if target
+       is powerpc*-*-win* in addition to powerpc*-*-*pe*.
+
+Fri Dec 15 16:30:57 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (endian_string): New static function.
+       (display_target_list): Use it.
+       * nlmconv.c (main): Use new bfd_big_endian macro.
+
+Fri Dec 15 07:51:34 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (fill_ordinals): Start from 1 if no other instructions
+       given.
+
+Tue Dec 12 12:05:21 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (clean): Remove $(DEMANGLER_PROG).1.  From Ronald
+       F. Guilmette <rfg@monkeys.com>.
+
+Mon Dec 11 14:33:05 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mac-binutils.r: Fix copyright and version strings.
+
+       * Makefile.in (version): Remove, no longer used.
+
+Fri Dec  1 14:41:56 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-make.sed (install, install-only): Edit in Mac-specific
+       install procedure.
+
+Thu Nov 30 20:26:02 1995  Kim Knuttila  <krk@cygnus.com>
+
+       * dlltool.c (ppc_jtab): The binary glue for PowerPC dll linkage,
+       including the return instruction.
+       sinfo: added a preferred alignment field.
+       (secdata): section data for the PowerPC version.
+       (make_one_lib_file): More symbols, More sections (pdata, rdata)
+       (make_tail): Use idata$6 instead of idata$7 for ppc. Also added a
+       NULL idata$3 descriptor (temporary).
+
+Tue Nov 28 17:23:44 1995  Doug Evans  <dje@canuck.cygnus.com>
+
+       * dlltool.c (fill_ordinals): Don't reference d_export_vec if
+       there are no exported functions.
+
+Mon Nov 27 13:05:59 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure: Regenerate with autoconf 2.7.
+
+Wed Nov 22 13:17:15 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.c (fill_ordinals): Start assigning ordinals at 1.
+
+       * Makefile.in (EXPECT): Use $$r, not $${rootme}.
+       (check): Set r, not rootme.
+
+Tue Nov 21 18:04:09 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Use BFD_NEED_DECLARATION.
+       * acconfig.h: Put NEED_DECLARATION_FPRINTF in @TOP@ section.
+       * configure, config.in: Rebuild with autoconf 2.6.
+
+Fri Nov 17 10:34:37 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (CC_FOR_TARGET): Use @host@ and @target@, not
+       $(host_canonical) and $(target_canonical).
+
+Thu Nov 16 03:39:20 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       Version 2.6 released.
+       * Makefile.in (VERSION): Update to 2.6.
+
+Wed Nov 15 12:14:17 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (CC_FOR_TARGET): Define.
+       (check): Pass CC and CFLAGS to runtest.
+
+       * nm.c (display_rel_file): Don't require a DYNAMIC object when
+       dumping the dynamic symbol table.
+
+       * objdump.c (compare_symbols): Sort global symbols before local
+       symbols before debugging symbols.
+       (objdump_print_address): Don't futz around looking for a global
+       symbol with the same value.
+
+Tue Nov 14 17:19:11 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dlltool.c: Use FOPEN_* macros rather than "r" or "w".
+
+       * dlltool.c (fill_ordinals): Correct memset call.
+
+Sun Nov 12 12:56:05 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-make.sed (DEMANGLER_PROG): Edit out attempts to do anything
+       with the man page.
+
+Fri Nov 10 11:41:22 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (setup_section): Copy the section lma independently of
+       the vma.
+
+Wed Nov  8 11:33:00 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * arsup.c (ar_open): Cast malloc return value.
+
+Tue Nov  7 09:01:26 1995  Kim Knuttila  <krk@cygnus.com>
+
+       * configure.in, configure (DLLTOOL_DEFS): Added ppc target.
+       * dlltool.c (MPPC): Added basic PPC definitions.
+
+Tue Nov  7 14:02:57 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Don't treat rs6000-*-lynx* specially.
+       * configure: Rebuild.
+       * config/rslynx: Remove.
+       * Makefile.in: Remove @target_makefile_fragment@.
+
+Mon Nov  6 15:00:50 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * bucomm.h: Include <sys/types.h>.
+       * ar.c: Don't include <sys/types.h> or <stdio.h>.
+       * bucomm.c, dlltool.c, nlmconv.c, objcopy.c, objdump.c: Likewise.
+
+Fri Nov  3 12:38:09 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c: Include <sys/types.h>.
+
+       Permit user to override DEMANGLER_PROG from command line.  From
+       Manfred Hollstein <manfred@lts.sel.alcatel.de>.
+       * Makefile.in ($(DEMANGLER_PROG)): Depend upon
+       $(DEMANGLER_PROG).1.
+       (install): Don't depend upon $(DEMANGLER_PROG).1.  Only install
+       $(DEMANGLER_PROG).1 if $(DEMANGLER_PROG) is not empty.
+
+Wed Nov  1 15:04:57 1995  Manfred Hollstein KS/EF4A 60/1F/110 #40283  <manfred@lts.sel.alcatel.de>
+
+       * Makefile.in (syslex.o): add -I$(srcdir) if compiling in a
+       separate directory.
+
+Mon Oct 30 14:24:18 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (objdump_print_value): New static function.
+       (objdump_print_address): Use it.  If we need the right section for
+       the symbol, and we can't find it, print an offset from the section
+       rather than using a symbol from some other section.
+
+Thu Oct 26 10:23:14 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (no_idata4, no_idata5): New.
+       (arm_jtab): Use correct encoding of jump instruction.
+       (usage, main, make_head, make_tail): Act on no_idata4, no_idata5.
+
+Wed Oct 25 12:10:07 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-make.sed: Edit paths to generated y.tab.[ch] files.
+
+Fri Oct 20 18:40:34 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils.texi: Change --with-targets to --enable-targets.
+
+Thu Oct 19 17:47:41 1995  Fred Fish  <fnf@cygnus.com>
+
+       * Makefile.in:  Remove extraneous tab on otherwise empty line,
+       which confuses many non-GNU versions of "make".
+
+Wed Oct 18 16:31:58 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (i386_jtab, arm_jtab): New
+       (gen_lib_file): Rewritten to use bfd.
+
+Fri Oct 13 16:10:07 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * Makefile.in (install): Don't give error message if dlltool
+       wasn't built.
+
+Fri Oct 13 11:04:37 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * deflex.l: Allow quoting of IDs.
+       * defparse.y (%union): string deleted.
+       (command): DESCRIPTION takes ID.
+       * dlltool.c (gen_def_file): Quote outgoing name if
+       necessary.  Preserve NONAME.
+       (gen_lib_file): Run ranlib.
+       (workout_prefix): Deleted.
+       (main, usage, long_options): Add --as, --ranlib, --ar options.
+
+Wed Oct 11 13:36:13 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (mtable): HOW_ALIGN_LONG, new.
+       (d_ord): Deleted.
+       (d_low_ord, d_high_ord, d_named_funcs): New.
+       (gen_exp_file): Create noname entries correctly.
+       (gen_lib_file): Dump exports alphabetically.
+       (process_duplicates):  Count nonamed functions.
+       (fill_ordinals): Keep track of highest ord too.
+       (mangle_defs): Create alphabetically ordered list of names.
+
+Tue Oct 10 09:39:09 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * Makefile.in (TOOL_PROGS): Include DLLTOOL_PROG.
+
+Mon Oct  9 13:06:31 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (add_underscore): New.
+       (xlate): Use new name.
+       (main, usage): Update.
+
+Fri Oct  6 14:08:51 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       * sysinfo.y: Eliminate unused terminals "[" and "]" and unused
+       nonterminal "name".  One s/r conflict remains.
+
+       Mon Sep 25 22:49:32 1995  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * nm.c (print_symname): Don't try to demangle an empty
+       name.
+       * objdump.c (slurp_symtab): Reset symcount if there are
+       no symbols.
+       (slurp_dynamic_symtab): Likewise, for dynsymcount.
+       (disassemble_data): Fix memory leak: free sorted_syms when done.
+       (display_bfd): Likewise, for syms and dynsyms.
+       (dump_relocs): Don't print header before possibly generating an
+       error message.
+       (dump_dynamic_relocs): Likewise.
+
+       * ar.1, nm.1, objdump.1, size.1, strings.1, strip.1: Fix typos and
+       formatting bugs.
+
+Fri Oct  6 12:00:25 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ar.c (do_quick_append): Comment out.
+       (replace_members): Add quick argument.
+       (main): Don't call do_quick_append.
+       (open_inarch): Don't call quick_append to create an empty archive.
+       Instead call bfd_openw/bfd_set_format/bfd_close.
+
+Thu Oct  5 20:53:08 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       * bucomm.c: Always include time.h.
+
+Thu Oct  5 17:25:21 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (compare_symbols): Sort gnu_compiled and gcc2_compiled
+       symbols after other symbols with the same value.  Likewise for
+       symbols which look like file names.
+       (objdump_print_address): Always chose the first reasonable symbol
+       with a given value.
+
+Tue Oct  3 22:38:55 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * arsup.c (ar_save): Use rename, not unlink/link/unlink.
+
+Mon Oct  2 12:10:25 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * strings.c (main): Exit with zero status if no files are given
+       and standard input is read.
+
+Thu Sep 28 20:03:07 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-config.in: Calculate underscore and put into makefile
+       fragment, generate config.h.
+       * mpw-make.sed: New file, sed commands to edit Unix makefile
+       into MPW syntax.
+       * mpw-make.in: Remove.
+       * mac-binutils.r: New file, Mac resources.
+
+Thu Sep 28 15:49:00 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c: (gen_exp_file): Always emit a .reloc section if
+       relocatable.
+       (imp_name_lab): New.
+       (gen_def_file): New.
+       (gen_lib_file): Use imp_name_lab.
+       (main): Initialize imp_name_lab.
+
+Mon Sep 25 12:05:34 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Call AC_HEADER_SYS_WAIT.
+       * configure: Rebuild.
+       * config.in: Rebuild.
+       * dlltool.c: Include "libiberty.h" and "bucomm.h".  Don't include
+       <stdio.h>, <stdlib.h>, or <string.h>.  Don't include <wait.h>.
+       Include <sys/types.h>.  Use HAVE_SYS_WAIT_H to control whether to
+       include <sys/wait.h> or define the wait macros by hand.  Don't
+       declare xmalloc.
+       (gen_lib_file): Don't assume that sprintf returns the number of
+       characters; use strlen instead.
+
+Fri Sep 22 17:16:41 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (disassemble_data): Don't use the old BFD based
+       disassembler interface.  Make info a const pointer.
+
+Wed Sep 13 18:33:44 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (start_address): New variable.
+       (stop_address): New variable.
+       (usage): Mention --start-address and --stop-address.
+       (OPTION_START_ADDRESS, OPTION_STOP_ADDRESS): Define.
+       (long_options): Add "start-address" and "stop-address".
+       (disassemble_data): Handle start_address and stop_address.
+       (dump_data, dump_reloc_set): Likewise.
+       (main): Don't set seenflag for -l.  Handle OPTION_START_ADDRESS
+       and OPTION_STOP_ADDRESS.
+       * objcopy.c (parse_vma): Move to bucomm.c.
+       * bucomm.c (parse_vma): New function, moved in from objcopy.c.
+       * bucomm.h (parse_vma): Declare.
+       * binutils.texi, objdump.1: Document new objdump options.
+
+Tue Sep 12 12:37:39 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (maintainer-clean): New target.
+
+       * ar.c (replace_members): Don't call write_archive if nothing
+       changed.
+
+       * objdump.c (disassemble_data): Add casts to avoid gcc warnings.
+
+Thu Sep  7 12:12:17 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * config.in: Rename from config.h.in.
+       * configure.in: Call AC_CONFIG_HEADER with config.h:config.in.
+       Check for config.h:config.in when creating stamp-h.
+       * configure: Rebuild.
+       * Makefile.in (stamp-h): Depend upon config.in rather than
+       config.h.in.  Set CONFIG_HEADERS to config.h:config.in when
+       calling config.status.
+
+       * Makefile.in (distclean): Remove config.h, stamp-h, and
+        config.log.
+
+       * nm.c (value_format): Initialize based on BFD64 and
+       BFD_HOST_64BIT_LONG.
+       (print_radix): New static variable.
+       (set_print_radix): Set print_radix.  Adjust changes to
+       value_format.
+       (print_value): New static function, to print 64 bit octal and
+       decimal values correctly.
+       (print_symbol_info_bsd): Check BFD64, not BFD_HOST_64_BIT.  Use
+       print_value.
+       (print_symbol_info_sysv): Use print_value.
+       (print_symbol_info_posix): Likewise.
+
+Wed Sep  6 15:02:55 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (*.o): Remove incorrect dependencies on
+       $(BFDDIR)/hosts/std-host.h.
+
+       * Makefile.in (INSTALL_DATA): Add -m 644.
+       (INSTALL_XFORM1): Likewise.
+       (CC_FOR_BUILD): Set to @CC_FOR_BUILD@ rather than $(CC).
+       (mostlyclean): Remove config.log.
+       (distclean): Remove config.cache.
+
+       * configure.in: Call BFD_CC_FOR_BUILD and BFD_BINARY_FOPEN.
+       * configure: Rebuild.
+
+Tue Sep  5 20:22:42 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Rewrite to use autoconf.
+       * aclocal.m4: New file.
+       * configure: New file, built by autoconf.
+       * acconfig.h: New file.
+       * config.h.in: New file, built by autoheader.
+       * Makefile.in: Various changes for new configure script.  Also:
+       (PROGS): Remove $(SYSINFO_PROG).
+       (ALL_CFLAGS): Remove $(TDEFINES).
+       (version.o): Use $(ALL_CFLAGS).
+       (cplus-dem.o, dlltool.o, nlmconv.o): Likewise.
+       (sysdump.o): Depend upon bucomm.h and config.h.
+       (srconv.o, arsup.o, strings.o): Depend upon config.h.
+       (filemode.o): Don't depend upon ../bfd/sysdep.h.
+       (bucomm.o): Depend upon config.h, not ../bfd/sysdep.h.
+       (size.o, objdump.o, nm.o, ar.o, objcopy.o): Likewise.
+       (nlmheader.o, nlmconv.o): Likewise.
+       (distclean): Don't remove sysdep.h.
+       * bucomm.h: Include "ansidecl.h", <stdio.h>, and "config.h".
+       Include "fopen-same.h" or "fopen-bin.h", based on
+       USE_BINARY_FOPEN.  Include <errno.h>, and declare errno if it is
+       not a macro.  Include <unistd.h>, <string.h>, <strings.h>,
+       <stdlib.h>, and <fcntl.h> if they are present.  Declare strchr,
+       strrchr, and strstr if no string header file exists.  Include
+       <sys/file.h> if it exists and <fcntl.h> does not.  Define
+       O_RDONLY and O_RDWR if necessary.
+       * ar.c:  Don't include "sysdep.h".  Do include <sys/types.h> and
+       <sys/stat.h>.  Use HAVE_GOOD_UTIME_H rather than POSIX_UTIME.  Use
+       HAVE_UTIMES rather than !USE_UTIME.  Don't include <errno.h>, and
+       don't declare errno.
+       * arsup.c: Don't include <sysdep.h>.
+       * bucomm.c: Don't include "sysdep.h".  Include <stdio.h>,
+       <sys/types.h>, and <sys/stat.h>.  Include <time.h> if it defines
+       time_t.  Define time_t if necessary.
+       * coffdump.c: Don't include "sysdep.h".
+       * coffgrok.c, filemode.c, nlmconv.c, size.c: Likewise.
+       * srconv.c, strings.c: Likewise.
+       * nm.c: Don't include "sysdep.h".  Don't try to define HAVE_SBRK.
+       * objcopy.c: Don't include "sysdep.h".  Include <sys/types.h> and
+       <sys/stat.h>.
+       (simple_copy): Use creat rather than assuming that O_CREAT is
+       defined.
+       * objdump.c: Don't include "sysdep.h".  Use
+       NEED_DECLARATION_PRINTF rather than !FPRINTF_ALREADY_DECLARED.
+       * sysdump.c: Include "bfd.h" and "bucomm.h".  Don't include
+       "sysdep.h" or <stdlib.h>.
+       (dump_symbol_info): Rename from symbol_info.  Change all callers.
+
+Mon Sep  4 14:30:00 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in (host_makefile_frag): Don't set.  Substitute for
+       @CC@, @CFLAGS@, @HDEFINES@ and @LDFLAGS@ in Makefile.
+       * Makefile.in (AR_FLAGS): Set to rc rather than qv.
+       (CC): Define as @CC@.
+       (CFLAGS): Set to @CFLAGS@.
+       (LDFLAGS): Define as @LDFLAGS@.
+       (ALL_CFLAGS): Use @HDEFINES@ rather than $(HDEFINES).
+
+       * configure.in: Don't bother to call config.bfd for each target.
+       Just call it for the default target, and use the shell variable to
+       decide whether underscores are used.
+
+Thu Aug 31 19:21:48 1995  Jason Molenda    (crash@phydeaux.cygnus.com)
+
+       * configure.in: match i[3-6]86-*-win32, not just i386-*-win32.
+
+Thu Aug 31 16:30:22 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (add_indirect): New.
+       (asm_prefix): New
+       (gen_exp_file): Timestamp should be 0. Insert prefix when
+       needed. New code for indirection.
+       (gen_lib_file): Timestamp should be 0. Insert prefix
+       when needed.
+       (usage): Document --add-indirect.
+       (main): Cope with new option.
+
+       * objdump.c (dump_private_headers): New.
+       (usage): Document new option.
+       (long_option): Add private-headers.
+       (dump_bfd_private_header): New.
+       (main): Cope with new option.
+
+Thu Aug 31 04:09:16 1995  Doug Evans  <dje@canuck.cygnus.com>
+
+       * dlltool.c (run): Add missing 3rd arg to waitpid.
+
+Wed Aug 30 11:02:11 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * Makefile.in (TOOL_PROGS): Include dlltool if needed.
+
+Tue Aug 29 13:25:21 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (rva): Deleted.
+       (rvaafter, rva_before): Use new assembler pseudo.
+       (flush_page, gen_exp_file, gen_lib_file): Use new way of RVAing.
+       (gen_exp_file): Don't generate .edata if no need.
+       (gen_lib_file): Don't make timestamp.
+       Put _iname in idata$7.
+       (workout_prefix): Fix memory initialization bug.
+       (usage): Tidy up, delete many single char options.
+       (main): rva option is gone.
+
+Mon Aug 21 18:41:28 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (options): image-base is a synonym for rva.
+       (gen_lib_file): Put dll name into ibase$7.
+
+Sun Aug 20 09:59:00 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       Modified to generate archives and objects rather than .s files.
+       * dlltool.c (run) New function.
+       (gen_exp_file, gen_lib_file): Use run.
+       (workout_prefix): New.
+       (usage): Document new options.
+       (main): Parse new options.
+
+Wed Aug 16 16:26:52 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (gen_exp_file): Fix RVA handling.
+       (rva_s, rva_n): Delete.
+
+Fri Aug 11 18:27:18 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * nm.c (main): Ignore -e.
+
+Thu Aug 10 17:35:00 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       * Makefile.in (config.texi): New target.  Write out a setting for
+       texinfo variable VERSION.
+       (binutils.dvi, binutils.info): Depend on it.
+       * binutils.texi: Include it, and reference @value{VERSION} instead
+       of explicitly specifying 2.2(!).
+
+Thu Aug 10 16:07:53 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * coffgrok.c (do_type): Handle array dimensions the same way gdb
+       does.
+
+Tue Aug  8 17:10:42 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c (mtable): New fields.
+       (ASM_RVA_BEFORE, ASM_RVA_AFTER): New.
+       (flush_page): Use new macros.
+
+Sat Aug  5 00:16:37 1995  Jeff Law  (law@snake.cs.utah.edu)
+
+       * objcopy.c (mark_symbols_used_in_relocations): Handle sections
+       with no relocations.
+       * coffgrok.c (do_sections_p1): Likewise.
+
+Mon Jul 31 12:51:06 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * strings.c (print_strings): For compatibility with existing
+       strings programs, print strings which are not terminated with a
+       null byte or a newline.
+       * binutils.texi, strings.1: Update documentation accordingly.
+
+       * ar.c (replace_members): For compatibility with existing ar
+       programs, permit users to add the same file multiple times.
+
+Tue Jul 25 11:21:53 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * strings.c (DATA_FLAGS): Remove SEC_DATA.
+       (main): If no file names are given, scan standard input.
+       * binutils.texi, strings.1: strings now scans non-data sections by
+       default.
+
+Mon Jul 24 13:52:28 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * srconv.c (wr_hd): Set afl field to 4 for bfd_arch_sh.
+       (writeINT): When size == -2, use 2 bytes for the h8300 and 4 bytes
+       for the sh.
+
+       * sysdump.c (fillup): Return size - 1, the last byte is a checksum
+       and shouldn't be counted.
+       * sysroff.info (hd): Changed segment identifier from a byte to a 1
+       bit field.  The sysroff 2.0-01 specification seems to be in error
+       here.  Reduce width of following "spare" field from 4 to 3 bits.
+       (rl): Changed order and width of first 4 bitfields to correspond
+       to sysroff specification.
+       (dln_head, dln_inside, dln_tail): Removed.
+
+Tue Jul 18 23:00:03 1995  Fred Fish  <fnf@cygnus.com>
+
+       * nm.c (sort_symbols_by_size):  Enclose expression being casted
+       in parens so result is casted, not just first operand.  Can't
+       do pointer arithmetic on void* pointers.
+
+Fri Jul 14 13:42:42 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * sysdump.c (dh): Changed format of output to be 16 hex digits
+       followed by 16 ascii characters, similar to Emacs' hexl-mode,
+       to make it easier to read.
+       (xcalloc): fix typo.
+
+Thu Jul 13 15:27:44 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * srconv.c (wr_tr): Write out handcrafted tr block.
+       (walk_tree_symbol): Use evallen and evalue instead of
+       vallen & value because of corresponding changes in
+       sysroff.info.
+
+       * sysdump.c (sysroff_swap_tr_in, sysroff_print_tr_out): New
+       functions.
+
+       * sysroff.info (tr): the tr block is a special case --- a block
+       without contents --- which can't be handled by generated code.
+       (den, dpp): only first byte is present for DENend, DPPend.
+       (dsy): describe a conditional portion of block, rename some fields.
+       (dps): describe a conditional portion of block.
+       (dfl): removed.
+
+       * sysinfo.y (yyerror): write error message to standard error.
+
+Thu Jul 13 10:43:59 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (DISTSTUFF): Add arparse.h and sysinfo.h.
+       (mostlyclean): Remove y.output.
+       (clean): Remove sysroff, sysroff.c, sysroff.h, and sysinfo.
+
+       * nlmconv.c (powerpc_mangle_relocs): Cast memset arg to size_t.
+       * objcopy.c (copy_object): Likewise.
+
+       * nm.c (HAVE_SBRK): Define execpt on amigados and WINDOWS_NT.
+       (struct size_sym): Define.
+       (show_stats): New static variable.
+       (long_options): Add undocumented option "stats".
+       (main): Print memory stats if requested.
+       (sort_bfd, sort_dynamic, sort_x, sort_y): New static variables.
+       (numeric_forward): Use minisymbols rather than asymbols.
+       (non_numeric_forward): Likewise.
+       (size_forward1): Rename from size_forward.  Use minisymbols.
+       (size_forward2): New static function.
+       (sort_symbols_by_size): Take new arguments dynamic, size, and
+       symsizep.  Use minisymbols.  Don't store the size back in the
+       symbol; store in a newly allocate struct size_sym array.
+       (display_rel_file): Read minisymbols rather than asymbols.  Set
+       sort_* variables.  Call print_size_symbols if sorting by size.
+       (filter_symbols): Take new arguments dynamic and size.  Use
+       minisymbols.
+       (print_symbols): Likewise.  Call print_symbol for actual printing.
+       (print_size_symbols): New static function.
+       (print_symbol): New static function.
+
+Wed Jul 12 10:43:05 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (dump_section_stabs): Only print each stabs section
+       once.
+       (compare_relocs): Make it clear to gcc that this always returns a
+       value.
+
+Wed Jul 12 10:40:23 1995  H.J. Lu  <hjl@nynexst.com>
+
+       * objcopy.c (simple_copy): Preserve errno on failure.
+       (smart_rename): Print error mesage if simple_copy fails.
+
+Tue Jul 11 13:10:52 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * sysdump.c: re-indented file.
+       (module): read blocks sequentially instead of trying to parse
+       them, as that would require changing the parser recognize the
+       difference between a DPSstart and DPSend block.
+       (getone): Add break's between switch blocks as appropriate.
+       (object_body_list): parse blocks according to sysroff spec.
+
+Mon Jul 10 12:37:25 1995  J.T. Conklin  <jtc@poseidon.cygnus.com>
+
+       * sysroff.info: re-indented file, prior formatting was confusing
+       because it was indentation did not reflect nesting of conditional
+       records.  Change "space size within segment" record in hd record
+       from bit to byte.
+
+       * sysinfo.y (cond_it_field): Use xcalloc instead of calloc.
+
+       * srconv.c (wr_cs): Reformatted cs header array, tag each byte
+       with a comment describing the field.
+       (wr_unit_info): Use SEEK_SET macro instead of constant 0.
+       (main): Use FOPEN_WB macro instead of literal "wb".
+       * sysroff.info: Remove fdl (dfl) field from cs block.  Compare
+       ptr->type with ED_TYPE_CONST instead of constant 2 in ed block.
+
+Tue Jul  4 14:48:42 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * nm.c (size_forward): Check yf against yn, not xn.
+
+       * objcopy.c (copy_archive): Record all output BFD's, and close
+       them before unlinking them and removing the temporary directory,
+       to avoid NFS problems.
+
+       * ar.c (replace_members): In verbose messages, use 'r' when
+        replacing a member, and 'a' when adding one.
+
+       * ar.c (ar_truncate): New static variable.
+       (normalize): Change return type to const char *.  Add abfd
+       argument.  Change all callers.  If ar_truncate, chop the filename
+       to abfd->ar_max_namelen.
+       (main): For the 'f' modifier, set ar_truncate to true.  Don't
+       change quick_append to replace if ar_truncate is true.
+       (do_quick_append): If ar_truncate, set BFD_TRADITIONAL_FORMAT.
+       (write_archive): Likewise.
+       * binutils.texi, ar.1: Document 'f' modifier.
+
+       * objcopy.c (enum strip_action): Define strip_unneeded.
+       (OPTION_STRIP_UNNEEDED): Define.
+       (strip_options): Add "strip-unneeded".
+       (copy_options): Likewise.
+       (copy_usage): Mention --strip-unneeded.
+       (strip_usage): Likewise.
+       (is_strip_section): Strip debugging sections if strip_unneeded.
+       (filter_symbols): If strip_unneeded, only keep BSF_KEEP symbols.
+       (copy_object): If strip_all, discard symbols without checking
+       discard_locals.
+       (copy_object): Call filter_symbols if strip_unneeded.
+       (setup_section): Strip debugging sections if strip_unneeded.
+       (copy_section): Likewise.
+       (strip_main): Handle OPTION_STRIP_UNNEEDED.
+       (copy_main): Likewise.
+       * binutils.texi, objcopy.1, strip.1: Document --strip-unneeded.
+
+Mon Jul  3 14:16:47 1995  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * configure.in (i386-*-win32): New configuration.
+       * dlltool.c (killat, xlate, usage, long_options, main):
+       Understand and cope with -k option.
+
+Sat Jul  1 12:25:15 1995  Fred Fish  <fnf@cygnus.com>
+
+       * ar.c: (extract_file):  Change "#if POSIX_UTIME" to
+       "#ifdef POSIX_UTIME" to match other tests of POSIX_UTIME
+       and avoid lossage when POSIX_UTIME is not defined at all.
+
+Wed Jun 28 17:51:24 1995  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * ar.c: (print_contents.c, extract_file, do_quick_append):
+       Malloc buffers rather than allocate on stack (so it works
+       on NT).
+       * deflex.l: Names can have an @ in them.
+       * dlltool.c: Loads of stuff. Can now generate .imp files which
+       work with NT .dlls.
+
+Thu Jun 22 19:10:50 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-make.in (demangle.c.o): Remove.
+       (arparse.h): Depend on arparse.c instead of arparse.y.
+
+Wed Jun 21 17:32:45 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in (DISTSTUFF): Don't include info here.
+       (diststuff): Include it here.
+       (realclean): Remove *.info.
+
+       * objdump.c (compare_relocs): If relocation entries have the same
+       address, keep them in file order.
+
+Mon Jun 19 09:06:49 1995  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * dlltool.c: Change names of generated files. .*.s-> -*.s
+
+       * objdump.c (dump_section_stabs):  Check for names
+       which are supersets of selected names.
+
+Wed Jun 14 19:43:52 1995  Doug Evans  <dje@canuck.cygnus.com>
+
+       * dlltool.c (mtable, ARM jump): Must redirect via pc offsetable ptr.
+
+Wed Jun 14 13:27:22 1995  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * deflex.l, defparse.y, dlltool.c: New files.
+       * Makefile.in, configure.in: Support for them.
+
+Mon Jun 12 11:27:54 1995  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * sysdump.c: Include sysdep.h
+       (main): Open input with FOPEN_RB.
+
+Fri Jun  9 17:26:11 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * objdump.c (wide_output): New flag variable.
+       (usage): Print new -w, --wide options.
+       (long_options): Add --wide support.
+       (dump_section_header): If --wide, don't print a newline between
+       the section's first line and the flags.
+       (objdump_print_address): Use unsigned comparisons for the binary
+       search, not signed.
+       (disassemble_data): If --wide, don't put a \n between the
+       disassembly output and relocation information.
+       (main): Support -w option being the same as --wide.
+
+Thu Jun  1 17:09:27 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       Sat May  6 08:52:24 1995  H.J. Lu (hjl@nynexst.com)
+
+       * objcopy.c (smart_rename): make it smarter, clean up
+         if rename () fails.
+
+Tue May 30 14:24:15 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in: Delete lines with lots of #### because four or more
+       indicate a point for makefile fragment substitution.
+
+Tue May  9 17:17:05 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * configure.in: Don't build nlmconv on PowerPC eabi any more, it
+       is not needed.
+
+Thu Apr 27 20:21:24 1995  Doug Evans  <dje@canuck.cygnus.com>
+
+       * Makefile.in (EXPECT): Define.
+       (RUNTEST): Use one in source tree if present.
+       (check): Set `rootme' for $(EXPECT).
+
+Wed Apr 26 18:26:21 1995  Steve Chamberlain  <sac@slash.cygnus.com>
+
+       * srconv.c (main): Add support for -n option which disables
+       prescan of common symbols.
+       (wr_ob): If reading past the end of a section, fill with zeros.
+
+Tue Apr 25 19:14:37 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * objdump.c (dump_section_header): Display load address after
+       virtual memory (run-time) address.
+
+Wed Apr 19 09:44:06 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * Makefile.in (cplus-dem.o): Pass -DVERSION='"$(VERSION)"' to the
+        compile.
+       (DEMANGLER_PROG): No longer uses version.o.
+
+Mon Apr 10 13:29:49 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       Merge in support for Mac MPW as a host.
+       (Old change descriptions retained for informational value.)
+
+       * mpw-config.in (TDEFINES): Define as empty in makefile frag.
+
+       * mpw-config.in: Create mk.tmp, define ARCHDEFS in it.
+
+       * mpw-config.in: New file, MPW configure fragment for binutils.
+       * mpw-make.in (install-only): New target.
+       (install): Also depend on install-only.
+
+       * mpw-make.in (cplusfilt): Renamed from c++filt.
+       (INCLUDES): Add more paths.
+
+       * mpw-make.in: New file, MPW makefile fragment for binutils.
+       (Normally automatically generated from Makefile.in.)
+
+Mon Mar 27 11:52:57 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ar.c (write_archive): Call make_tempname to get output file
+       name, rather than using a fixed name based on the input file.
+
+       * objcopy.c (make_tempname): Copy from here...
+       * bucomm.c (make_tempname): ...to here, and make global.
+       * bucomm.h (make_tempname): Declare.
+
+Fri Mar 24 11:47:42 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * strings.c: Include "bfd.h" before other headers.  Include
+       "sysdep.h".
+       * bucomm.c (print_arelt_descr): Cast st_uid and st_gid to long,
+       and print them with %ld.
+
+Fri Mar 10 13:09:42 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (strip_options): Add --keep-symbol.
+       (copy_options): Likewise.
+       (copy_usage): Mention --keep-symbol and -K.
+       (strip_usage): Likewise.
+       (keep_symbols): New static variable.
+       (is_strip_symbol): Adjust the return value according to
+       keep_symbols.
+       (strip_main): Handle -K.  For -N, check that -K was not given.
+       (copy_main): Likewise.
+       * binutils.texi, objcopy.1, strip.1: Document -K.
+
+Mon Mar  6 13:33:47 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * objcopy.c (copy_archive): Check result of mkdir.
+       (copy_main): Cast an xmalloc result.
+
+       * objdump.c (usage): Break long format string into shorter ones.
+
+Mon Mar  6 13:46:12 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * bucomm.c (list_supported_targets): New function.
+       * bucomm.h (list_supported_targets): Declare.
+       * ar.c (usage): Call list_supported_targets.
+       * nm.c (usage): Likewise.
+       * objcopy.c (copy_usage, strip_usage): Likewise.
+       * objdump.c (usage): Likewise.
+       * size.c (usage): Likewise.
+       * strings.c (usage): Likewise.
+
+Tue Feb 28 15:13:58 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * bucomm.c (print_arelt_descr): Cast st_size to long before
+       passing it to fprintf.
+
+Fri Feb 17 13:36:45 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (struct section_list): Add fields remove, set_flags,
+       and flags.  Change adjust from boolean to enum.
+       (remove_sections): Remove static variable.
+       (sections_removed): New static variable.
+       (copy_options): Add --set-section-flags.
+       (copy_usage): Mention --set-section-flags.
+       (parse_flags): New static function.
+       (find_section_list): New static function.
+       (is_strip_symbol): Change return type from int to boolean.
+       (is_strip_section): New static function.
+       (filter_symbols): Call is_strip_section.
+       (copy_object): When adding sections, check for specified flags or
+       VMA.  Call filter_symbols if any sections are being removed.
+       (setup_section): Use find_section_list function rather than
+       looking through remove_sections and adjust_sections.  Handle
+       --set-section-flags.
+       (copy_section): Use find_section_list rather than looking through
+       remove_sections.
+       (strip_main): Use find_section_list instead of adding items to
+       sections_removed.
+       (copy_main): Use find_section_list instead of adding items to
+       sections_removed and adjust_sections.  Handle --set-section-flags.
+       * binutils.texi, objcopy.1: Document --set-section-flags.
+
+Tue Feb 14 18:03:03 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (with_source_code): New global variable.
+       (usage): Mention -S/--source.
+       (long_options): Add --source.
+       (prev_functionname, prev_line): New static variables.
+       (struct print_file_list): Define.
+       (print_files): New static variable.
+       (skip_to_line, show_line): New static functions.
+       (disassemble_data): Call show_line to handle -l and -S.
+       (main): Handle -S.
+       * binutils.texi, objdump.1: Document -S/--source.
+
+Thu Feb  9 16:11:53 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objcopy.c (copy_usage): Rename parameter to avoid shadowing.
+       (strip_usage): Likewise.
+
+       * objcopy.c (struct section_add): Define.
+       (add_sections): New static variable.
+       (copy_options): Accept --add-section.
+       (copy_usage): Mention --add-section.
+       (copy_object): Add sections from the add_sections list.
+       (copy_main): Handle --add-section.
+       * binutils.texi, objcopy.1: Document --add-section.
+
+Wed Feb  1 15:04:57 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * objdump.c (disassemble_data): Pass section offset, not absolute
+       address, to bfd_find_nearest_line.
+
+       * nlmconv.c (powerpc_mangle_relocs): Don't use const with
+       reloc_howto_type.
+
+Thu Jan 26 18:50:06 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * objdump.c (compare_symbols): Use bfd_asymbol_value (VAR) rather
+       than VAR->value.
+       (objdump_print_address): Likewise.
+       (disassemble_data): Don't change the symbol values.  It can
+       confuse bfd_canonicalize_reloc.
+
+Thu Jan 26 12:03:56 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * configure.in: Add support for powerpc-*-ebai.
+
+Wed Jan 18 10:02:12 1995  Steve Chamberlain  <sac@splat>
+
+       * coffdump.c: Include sysdep.h.
+       (dump_coff_type): Handle coff_secdef_type.
+       * coffgrok.c : Include sysdep.h.
+       * srconv.c: Include libiberty.h
+       (absolute_p, dty_start, dty_end, dump_tree_structure): Remove.
+
+Wed Jan 18 12:24:14 1995  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * coffdump.c (dump_coff_scope): Cast pointer to unsigned long for
+       printf.
+       * coffgrok.c: Include bucomm.h.  Don't declare xmalloc.
+       (push_scope): Declare type of parameter link.
+       * size.c: Include libiberty.h.
+       * srconv.c: Include bucomm.h.
+       (find_base): Declare at top of file.
+       (wr_hd): Add default case to architecture switch.
+       (wr_dps_start): Declare type of parameter nest.
+       (wr_du): Comment out variables used only in commented out blocks.
+       (wr_dus): Remove unused variable i.
+       (wr_sc): Remove unused variables myinfo, low, and high.
+       * strings.c: Include libiberty.h.
+       * sysdump.c: Include <ctype.h>.
+
+Tue Dec 20 19:13:44 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * ar.c (main): Ignore 'f' modifier used on HP/UX 9.
+
+Thu Dec 15 17:34:12 1994  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * ar.c, nm.c, objcopy.c, objdump.c: Include progress.h.
+       * ar.c, nm.c, objcopy.c, objdump.c (main): Add START_PROGRESS
+       and END_PROGRESS.
+       * ar.c (map_over_members, open_inarch): Call PROGRESS.
+       * nm.c (main, display_archive, filter_symbols, print_symbols):
+       Call PROGRESS.
+
+       * objcopy.c (copy_usage): Break up long usage string.
+
+Wed Dec 14 15:51:56 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * objcopy.c (copy_object): Don't bother setting status after
+       nonfatal() "call", because it won't return.
+
+Fri Dec  9 00:22:54 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (powerpc_mangle_relocs): Don't switch a reloc to use
+       the section symbol if the symbol is undefined.
+
+Thu Dec  8 14:45:50 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * objcopy.c (add_strip_symbol): Cast return value of xmalloc.
+
+Wed Nov 30 11:05:43 1994  Ian Lance Taylor  <ian@rtl.cygnus.com>
+
+       * ar.c (replace_members): Pass current->filename to normalize when
+       checking for duplicates, because the filename of a newly added
+       file will not have been normalized yet.
+
+Thu Nov 17 15:00:13 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * ar.c (main): Don't call do_quick_append if any of the archive
+       names are longer than 14 characters.
+
+       * objcopy.c (main): Fix is_strip test.  From
+       pirker@eiunix.tuwien.ac.at (Martin Pirker).
+
+Thu Nov 17 15:37:19 1994  Mark W. Eichin  <eichin@cygnus.com>
+
+       * objcopy.c (add_strip_symbol): New function, adds a name to an
+       explicit list of symbols to strip.
+       (is_strip_symbol): New function, reports whether the name argument
+       is in the explicit list.
+       (filter_symbols): Check against is_strip_symbol above all.
+       (strip_main): Recognize -N option. If used, don't default to
+       strip_all.
+       (copy_main): Recognize -N option.
+       (strip_usage): Document -N and --strip-symbol options.
+       (copy_usage): Ditto.
+       * objcopy.1, strip.1, binutils.texi: Document -N and
+       --strip-symbol options.
+
+Tue Nov  8 13:12:54 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * objdump.c (display_target_list, display_info_table): Pass an
+       array to tmparg, rather than NULL, since some systems can't handle
+       NULL.
+
+       * objcopy.c (copy_archive): Keep a list of the names of the
+        temporary files we created.  Close each input BFD after we open
+        its successor.
+
+Mon Nov  7 15:48:39 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in (VERSION): Bump to 2.5.3.
+
+Thu Nov  3 19:04:34 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in (install-info): Install info files from whatever
+       directory they were found in.
+
+       Patch from DJ Delorie:
+       * configure.bat: do c++filt -> cxxfilt right
+
+       * sysinfo.y: Include system header files early, so any potential
+       declaration of abort() occurs before its use.
+
+       * strings.c (strings_file): Try opening the file in binary mode
+       first.
+
+Wed Nov  2 15:44:13 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * ar.c (main): Treat ar qs like ar rs.
+
+Tue Oct 25 16:19:25 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * objcopy.c (gap_fill): Explicitly initialize, for clarity.
+       (pad_to_set, pad_to): New static variables.
+       (copy_options): Accept --pad-to.
+       (copy_usage): Mention --pad-to.
+       (copy_object): Support --pad-to.
+       (compare_section_vma): Sort non loadable sections to the front.
+       Sort sections with the same VMA by size.
+       (copy_main): Handle --pad-to.
+       * binutils.texi, objcopy.1: Document --pad-to.
+
+Thu Oct 20 13:51:31 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objcopy.c (gap_fill_set, gap_fill): New static variables.
+       (copy_options): Accept --gap-fill.
+       (copy_usage): Mention --gap-fill.
+       (copy_object): Support --gap-fill.
+       (get_sections, compare_section_vma): New static functions.
+       (copy_main): Handle --gap-fill.
+       * binutils.texi, objcopy.1: Document --gap-fill.
+
+Wed Oct 19 14:09:16 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * Makefile.in (check): Add a dummy else clause to the if
+       statement.
+
+       * objcopy.c (copy_object): Revert yesterday's change.
+       * binutils.texi, objcopy.1: Remove special mention of --set-start
+       and `binary' output format.
+
+Tue Oct 18 11:12:01 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * objcopy.c (copy_object): If the output file format is `binary',
+       and the start address was not set using --set-start, default the
+       start address to zero.  This hack is because the `binary' output
+       file format uses the start address to set the virtual address of
+       the first byte in the file.
+       * binutils.texi, objcopy.1: Add some notes on generating S-records
+       and binary files.
+
+       * nm.c (print_symdef_entry): Call print_symname to print the
+       symbol name, so that --demangle works.
+
+       * Makefile.in (mostlyclean): Remove tmpdir.
+
+       * objcopy.c (struct section_list): Add fields used, adjust, val.
+       (adjust_start, set_start_set, set_start): New static variables.
+       (adjust_section_vma, adjust_sections): New static variables.
+       (copy_options): Add --adjust-start, --adjust-vma,
+       --adjust-section-vma, --adjust-warnings, --no-adjust-warnings,
+       --set-start.
+       (parse_vma): New static function.
+       (copy_usage): Mention new options.
+       (copy_object): Handle --set-start and --adjust-start.
+       (setup_section): Correct type of last argument to PTR.  Set used
+       field if section is removed.  Handle --adjust-vma and
+       --adjust-section-vma.
+       (copy_section): Correct type of last argument to PTR.
+       (mark_symbols_used_in_relocations): Likewise.
+       (strip_main): Clear used field when handling -R.
+       (copy_main): Handle new options.
+       * binutils.texi (objcopy): Document new options.
+       * objcopy.1: Document new options.
+
+Fri Oct 14 14:38:13 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * configure.in (configdirs): Remove definition--testsuite is no
+       longer configured.
+       * Makefile.in (testsuite): Remove target.
+       (site.exp): New target.
+       (check): Rewrite.
+       (clean, distclean): Don't recur into testsuite directory.
+
+Thu Oct 13 19:24:09 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in (VERSION): Updated to 2.5.
+       * Version 2.5 released.
+
+Tue Oct 11 15:26:42 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * Makefile.in (sysdump.o): Depends upon sysroff.c.
+
+Mon Oct 10 13:50:30 1994  J.T. Conklin  (jtc@rtl.cygnus.com)
+
+       * nlmconv.c (link_inputs): Pass -Ur flag to ld so that the
+         ctor/dtor tables needed by C++ programs are built.
+
+Sun Oct  9 18:04:00 1994  Jim Wilson  (wilson@sphagnum.cygnus.com)
+
+       * Makefile.in (srconv.o): Add dependence on sysroff.c.
+
+Tue Oct  4 12:19:51 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * configure.in: Use ${config_shell} when running config.bfd.
+
+       * Makefile.in (sysroff.h): Split target away from sysroff.c.
+       (srconv.o, sysdump.o): New targets.
+       (srconv, sysdump): Don't depend upon sysroff.c.
+
+Wed Sep 28 13:04:34 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * Makefile.in (arparse.c): Don't ignore errors from mv.
+       (sysinfo.c): Likewise.  Also, depend upon arparse.c, to prevent a
+       parallel make from trying to build both arparse.c and sysinfo.c
+       simultaneously.
+       (nlmheader.c): Similar change.
+       (arparse.h): Separate target from arparse.c, so that a parallel
+       make does not try to build both at once.  Depend upon arparse.c.
+       (sysinfo.h): Similar change.
+
+       * objdump.c (disassemble_data): Pass the reloc buffer to free, not
+       the pointer used to loop over the relocs.
+
+Sat Sep 24 16:16:57 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * objdump.c (disassemble_data): Cast result of xmalloc.
+
+Wed Sep 21 19:30:35 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * objdump.c (sorted_syms, sorted_symcount): New global variables.
+       (objdump_print_address): Use sorted_syms and sorted_symcount
+       instead of syms and symcount.
+       (disassemble_data): Don't bother to get the relocs before looping
+       over the sections.  Before filtering and sorting the symbol table,
+       copy it into sorted_syms.
+
+Fri Sep 16 11:27:39 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * objdump.c (struct objdump_disasm_info): Add field require_sec.
+       (objdump_print_address): If aux->require_sec, require that the
+       symbol be in aux->sec even if HAS_RELOC is not set.  If we can't
+       find a smaller symbol in the right section, look for a larger one.
+       (disassemble_data): Set aux.require_sec around the
+       objdump_print_address call for the instruction address.
+
+Thu Sep 15 21:43:17 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * ar.c: Call xexit rather than exit.
+       (output_filename, output_file, output_bfd): New static variables.
+       (remove_output): New static function.
+       (main): Call xatexit (remove_output).  Call xexit rather than
+       returning.
+       (extract_file): Set output_filename and output_file while output
+       file is open.
+       (write_archive): Likewise, but use output_bfd, not output_file.
+       * arsup.c: Include libiberty.h.  Call xexit rather than exit.
+       * bucomm.c: Likewise.
+
+       * objdump.c (disassemble_all): New global variable.
+       (usage): Document --disassemble-all.
+       (long_options): Add disassemble-all as a synonym for -D.
+       (compare_symbols): Make pointers const.
+       (compare_relocs): New static function.
+       (disassemble_data): Rename disassemble to disassemble_fn to avoid
+       shadowing.  If dump_reloc_info, print relocs along with
+       disassembly.  Skip sections which are not SEC_CODE unless
+       disassemble_all or only is set.
+       (display_bfd): Don't call dump_relocs if disassemble is set.
+       (main): Accept and handle -D.
+       * binutils.texi: Document -D/--disassemble-all.
+       * objdump.1: Likewise.
+
+Wed Sep 14 12:19:07 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * objdump.c (disassemble_data): Initialize prevline to 0.  Make
+       prev_function non const.  Copy functionname into an malloc buffer
+       when setting prev_function, instead of assuming that the string
+       will last forever.
+
+       * nm.c: Include libiberty.h.
+       (sort_by_size): New static variable.
+       (long_options): Add --size-sort.
+       (usage): Mention --size-sort.
+       (numeric_forward): Make static.  Change from void * to PTR.
+       (numeric_reverse): Likewise.
+       (non_numeric_forward, non_numeric_reverse): Likewise.
+       (sorters): Change declaration from void * to PTR.
+       (size_forward, sort_symbol_by_size): New static functions.
+       (display_rel_file): Handle sort_by_size.
+       (filter_symbols): If sort_by_size, discard absolute and undefined
+       symbols.
+       * binutils.texi (nm): Document --size-sort.
+       * nm.1: Document --size-sort.
+
+Tue Sep 13 21:06:06 1994  Jeff Law  (law@snake.cs.utah.edu)
+
+       * objcopy.c (copy_main): Initialize input_filename and
+       output_filename to NULL.
+
+Tue Sep 13 14:17:24 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * Makefile.in (version.o): Depend upon Makefile, so that version.o
+       gets rebuilt when make variable VERSION is changed.
+
+       * objdump.c (dump_section_header): Print the SEC_NEVER_LOAD flag.
+
+Wed Aug 24 12:40:09 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * configure.in: Change i[34]86 to i[345]86.
+
+Tue Aug 23 11:00:40 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * ar.c (ranlib_touch): Don't update the archive map if there isn't
+       one.
+
+Mon Aug 22 16:02:18 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * ar.c: Include libiberty.h.
+       (inarch): Remove variable.
+       (map_over_members): Make static.  Add arch argument, and use it
+       instead of inarch.  Change all callers.
+       (main): Treat --version as -v.  Accept -t argument.  Accept any
+       number of archive arguments.  Catch and use open_inarch return
+       value, rather than using inarch.
+       (open_inarch): Return newly opened BFD, rather than using inarch.
+       (do_quick_append): Make archive_filename const.
+       (write_archive): Add iarch argument, and use it instead of inarch.
+       Change all callers.
+       (delete_members, move_members, replace_members): Likewise.
+       (ranlib_only): Don't exit on success.  Catch and use open_inarch
+       return value.
+       (ranlib_touch): New function.
+       * arsup.h (map_over_members): Don't declare.
+       (ar_end, ar_extract): Declare.
+       (open_inarch): Change return value in declaration to bfd *.
+       * arsup.c (map_over_list): Make static. Always pass two arguments
+       to function.  Add arch argument, and use it instead of inarch.
+       Change all callers.
+       (ar_directory_doer): Make static.  Add ignored second argument.
+       Change all callers.
+       (ar_directory): Use open_inarch return value rather than inarch.
+       (ar_addlib_doer): Make static.
+       (ar_addlib): Use open_inarch return value rather than inarch.
+       (ar_extract): Remove unused local variable abfd.
+
+Thu Aug 11 14:55:57 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       Add support for removing named sections to objcopy and strip.
+       * objcopy.c (struct section_list): Define.
+       (remove_sections): New static variable.
+       (strip_options, copy_options): Add remove-section.
+       (copy_usage, strip_usage): Mention -R and --remove-section.
+       (setup_section): If section is in remove_sections list, ignore it.
+       (copy_section): Likewise.
+       (strip_main, copy_main): Handle -R.
+       * binutils.texi, objcopy.1, strip.1: Document new options.
+
+Wed Aug 10 10:19:55 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * nlmconv.c (powerpc_mangle_relocs): Rename symvalue to sym_value,
+       so as not to conflict with the symvalue typedef in bfd.h.
+
+Mon Aug  1 13:19:09 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * nlmheader.y: Per current NetWare docs, accept a revision number
+       of 0 and treat a revision number greater than 26 as 0.
+
+Mon Jul 25 12:58:36 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * objdump.c (objdump_print_address): Correct handling of end of
+       symbols when looking for next symbol with a different value.
+
+Fri Jul 22 16:48:34 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * nm.c (numeric_forward): Treat undefined symbols as "less than"
+       defined symbols with zero values.  If numeric values are equal, or
+       both symbols are undefined, sort alphabetically.  Don't assume
+       that the difference of two bfd_vma values will truncate to "int"
+       and still have the same sign.
+       (numeric_reverse): Call numeric_forward and negate the result.
+       (print_symbol_info_bsd): For undefined symbols, print leading
+       spaces equivalent to the width of a printed bfd_vma, rather than
+       assuming that 8 will look right.
+
+Fri Jul 22 10:36:50 1994  Steve Chamberlain  (sac@jonny.cygnus.com)
+
+       * coffgrok.c (doit):  Zero all fields of new structure.
+       * srconv.c (sysroff_swap_*_out): Remove redundant trailing arg.
+       * sysinfo.y: Generate sysroff_swap_*_out without requiring extra
+       arg.
+
+Fri Jul 22 10:09:53 1994  J.T. Conklin  (jtc@phishhead.cygnus.com)
+
+       * nlmheader.y: Make "stack" and "stacksize" synonyms in the lexer
+         rather than the parser.
+
+Thu Jul 21 10:25:09 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * config/mh-alphaosf, config/mh-apollo68v, config/mh-delta88:
+       Remove; obsolete.
+
+Sat Jul 16 22:34:39 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * objdump.c (slurp_dynamic_symtab): Try to get the dynamic symbols
+       even if the bfd is not marked DYNAMIC.  ELF executables are not
+       marked DYNAMIC, but do have dynamic symbols.
+
+Fri Jul 15 01:41:35 1994  Steve Chamberlain  (sac@jonny.cygnus.com)
+
+       * coffgrok.c (do_where): Make data with no type 'int'.
+       (do_define):  Keep info on source file of a symbol.
+       * coffgrok.h (coff_symbol): New field.
+       * srconv.c (PROGRAM_VERSION): Now 1.3
+       (wr_rl): Use external ref number for symbol.
+       (wr_dus): Only keep one source file per debug unit.
+       (wr_dln): Always emit line numbers for first source file,
+       (wr_globals):  Emit globals in the du of their owning source file.
+
+Mon Jul 11 15:59:03 1994  J.T. Conklin  (jtc@phishhead.cygnus.com)
+
+       * nlmheader.y: Null terminate var_hdr->threadName.
+
+Fri Jul  8 17:33:22 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * Makefile.in (syslex.o, sysinfo.o): Permit C source files to be
+       in $(srcdir), as they will be for FSF releases.
+
+Wed Jul  6 01:13:14 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (setup_sections): Preserve existing section flags when
+       copying in flags from a new section.
+
+Tue Jul  5 15:56:01 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * objcopy.c: Include libiberty.h.
+       (copy_file): If output_target is NULL, set it to the target of the
+       input file.
+
+Wed Jun 29 17:17:14 1994  J.T. Conklin  (jtc@phishhead.cygnus.com)
+
+       * nlmconv.c (link_inputs): Fixed memory allocation bug.
+
+Thu Jun 23 12:52:46 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * configure.in: Change --with-targets to --enable-targets.
+
+Tue Jun 21 12:53:21 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * Makefile.in (sysinfo): Does not depend upon $(ADDL_LIBS).
+
+       * nlmconv.c (powerpc_build_stubs): Don't generate the PowerPC
+       NetWare custom header; no longer needed.
+       (powerpc_mangle_relocs): Convert relocs against the uninitialized
+       data section into relocs against the data section.
+
+       * configure.in: Set nlmconv_defs to -DNLMCONV_cputype for all the
+       netware targets.  Write it into Makefile as NLMCONV_DEFS.
+       * Makefile.in (nlmconv.o): Pass $(NLMCONV_DEFS) to $(CC).
+       * nlmconv.c: Only compile code for specific CPU types if
+       NLMCONV_cputype is defined.
+
+       * nlmconv.c (main): Change uses of bfd_abs_section, etc., to use
+       bfd_abs_section_ptr or bfd_is_abs_section, etc.
+       (i386_mangle_relocs, alpha_mangle_relocs): Likewise.
+       (powerpc_build_stubs): Likewise.
+       * nm.c (filter_symbols, print_symbols): Likewise.
+       * objcopy.c (filter_symbols): Likewise.
+       (mark_symbols_used_in_relocations): Likewise.
+       * objdump.c (remove_useless_symbols, dump_relocs): Likewise.
+       * size.c (sysv_internal_printer): Likewise.
+
+Mon Jun 20 16:43:03 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * Makefile.in (MANPAGES): Remove $(DEMANGLER_PROG).
+       (install): Install it explicitly, from build dir, not srcdir.
+
+Mon Jun 20 16:29:54 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * objdump.c: Don't include elf/internal.h.
+       (bfd_elf_find_section): Don't declare.
+       (read_section_stabs): No special handling for ELF.  Always read
+       using BFD sections.
+
+Thu Jun 16 17:25:20 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * configure.in: Set UNDERSCORE in Makefile based on result of
+       invoking config.bfd with a second argument of ``_''.
+       * Makefile.in (underscore.c): Depend upon Makefile.  Don't try to
+       run $(CC) and $(NM), just use $(UNDERSCORE).  Create via temporary
+       file.
+       (demangle.o): Remove target.
+       ($(NM_PROG)): Don't depend upon demangle.o, and don't link against
+       demangle.o.  It's in libiberty anyhow.
+       (cplus-dem.o): Don't depend upon demangle.o.
+       * binutils.texi: Mention -n and --no-strip-underscores arguments
+       to c++filt.
+
+Wed Jun 15 12:10:31 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nm.c (long_options): Add --no-demangle to turn off --demangle,
+       and --no-cplus for Linux compatibility.
+       (usage): Mention --no-demangle.
+       * binutils.texi: Document --no-demangle.
+
+Fri Jun 10 15:41:25 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nm.c: HOST_64_BIT was renamed to BFD_HOST_64_BIT.
+
+       * objcopy.c (copy_archive): Make the temporary directory in the
+       same directory as the output BFD, since we may not have write
+       permission on the current directory.  Set the permissions of the
+       new directory to 0700, not 0777.
+
+Mon Jun  6 21:36:43 1994  D. V. Henkel-Wallace  (gumby@cygnus.com)
+
+       * configure.in: if this is an rs6000 (and we're not building for
+       any other bfd targets) then build only nm (collect needs it on
+       rs6000-lynx).
+
+       * Makefile.in: define TOOL_PROGS which the list of programes to
+       install in $tooldir -- replaces a hard-coded list.
+
+Fri Jun  3 10:59:18 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (display_target_list): Remove unused local ok.
+
+Thu May 26 18:05:52 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * config/mh-alphaosf (CFLAGS): Don't specify both -g and -O;
+       they're not compatible under native cc.  Use -O1 instead.
+
+       * Makefile.in (VERSION): Updated to cygnus-2.4.1.
+
+       Changes from binutils-2.4 net release:
+
+       * Makefile.in (MANPAGES): Use $(DEMANGLER_PROG).
+       ($(DEMANGLER_PROG).1): Build from cxxfilt.man, using sed.
+       * cxxfilt.man: Renamed from c++filt.1, replaced "c++filt" with
+       magic token to be replaced by sed.
+
+       Wed May 11 22:32:00 1994  DJ Delorie (dj@ctron.com)
+
+       * configure.bat: update for latest makefile.in
+
+Fri May 13 23:25:13 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * bucomm.c: Check ANSI_PROTOTYPES rather than __STDC__.
+
+Tue May 10 18:22:06 1994  Jason Molenda    (crash@sendai.cygnus.com)
+
+       * objcopy.c (copy_section): Set section size correctly if using
+       interleave.
+
+Sat May  7 16:49:36 1994  Steve Chamberlain  (sac@cygnus.com)
+
+       * Makefile.in: Add rule for sysinfo.h
+
+Fri May  6 12:18:33 1994  Steve Chamberlain  (sac@cygnus.com)
+
+       * Makefile.in (SRCONV_PROG): Define.
+       (PROGS): Use $(SRCONV_PROG) too.
+
+Thu May  5 19:41:43 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * Makefile.in (DISTSTUFF): Add sysinfo.c, syslex.c, in case
+       someone configures with `targets=all'.
+       (distclean): Remove y.*.
+       (syslex.o): Depend on sysinfo.h.
+       (sysinfo.c): Rename y.tab.h to sysinfo.h.
+       (install-info): Don't try to install into $(infodir)/$(srcdir).
+       * syslex.l: Include sysinfo.h, not y.tab.h.
+
+Thu May  5 11:50:55 1994  Ken Raeburn  (raeburn@kr-pc.cygnus.com)
+
+       * syslex.l (yywrap): Define as function if not defined as a macro.
+
+       * Makefile.in (objdump.o): Deleted special rule.
+       * configure.in: Don't bother building ARCHDEFS variable for
+       Makefile.
+       * objdump.c (ARCH_*): Deleted handling.
+       (disassemble_data): Call `disassembler' from opcodes library.
+
+Thu May  5 13:28:42 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * Makefile.in (install): Correct handling of $(tooldir) and
+       $(bindir) being on different devices.
+
+Fri Apr 29 09:50:38 1994  Steve Chamberlain  (sac@cygnus.com)
+
+       * sysdump.c (h8300, sh): Add declarations.
+
+Wed Apr 27 11:25:18 1994  Steve Chamberlain  (sac@cygnus.com)
+
+       * Makefile.in (syslex, sysinfo): Use CC_FOR_BUILD.
+       * coffdump.c, coffgroc.c, coffgrog.h, srconv.c, sysdump.c,
+       sysroff.info: Major changes.
+
+Tue Apr 26 18:18:24 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * objdump.c (print_section_stabs): Indicate the stab header symbol
+       more clearly, print numbers of unrecognized stab n_type values.
+
+Tue Apr 26 16:22:55 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (copy_sections): Copy arelent pointers, not arelents.
+
+Mon Apr 25 16:14:32 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * Makefile.in (distclean): Remove $(PROGS) and underscore.c.
+
+Fri Apr 22 11:14:19 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (setup_sections): Remove special handling of .reginfo
+       section.
+       (copy_sections): Likewise.
+       (alpha_mangle_relocs): Use bfd_ecoff_get_gp_value rather than the
+       special ECOFF .reginfo section.
+
+       * objcopy.c (copy_object): Call bfd_copy_private_bfd_data after
+       copying everything else, to let it fiddle with the file in its
+       final state.
+
+       * objdump.c: Include libiberty.h.
+       (display_target_list): If a format fails, just go on to the next
+       one.  Check return value of bfd_set_format.
+       (display_info_table): Likewise.  Don't increment loop variable in
+       for loop test, since that skips the first element.
+       (display_target_tables): Rewrite loop for clarity.  Ensure that it
+       always prints at least one element.
+
+       * nlmconv.c (main): Use CyGnUsEx rather than CyGnUsSeCs for
+       sections header.  Rename from cygnus_sections to cygnus_ext.
+
+Thu Apr 21 12:12:26 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (_DUMMY_NAME_): Don't define.
+       (display_target_list): Use tmpnam to get a file name rather than
+       using _DUMMY_NAME_.  Unlink it when done.
+       (display_info_table): Likewise.
+
+       * nlmconv.c (secsec): New static variable.
+       (main): Create .nlmsections section in output BFD.  Store
+       information about it in sections header.
+       (setup_sections): Allocate space in sections header.
+       (copy_sections): Copy zero sized sections.  Put information about
+       each section in the sections header.
+
+Wed Apr 20 14:34:51 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (powerpc_build_stubs): Take new outbfd argument.
+       Change caller.  Create custom header for new PowerPC NetWare
+       format.
+
+       * Makefile.in (nlmheader.o, nlmconv.o): Update dependencies.
+       * nlmconv.c: Include bfd.h and libiberty.h with "", not <>.
+       * nlmheader.y: Include bfd.h with "", not <>.
+
+Wed Apr 13 10:52:50 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c: Do an ifdef on __GO32__, not unix.
+
+Wed Apr  6 21:54:49 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       Added -D (--dynamic) option to nm and -T (--dynamic-syms) and -R
+       (--dynamic-reloc) arguments to objdump.
+       * nm.c (dynamic): New static variable.
+       (long_options): Added "dynamic".
+       (usage): Mention -D and --dynamic.
+       (main): Add D to getopt string.  Handle -D by setting dynamic.
+       (display_rel_file): If dynamic is non-zero, read dynamic symbols
+       rather than normal symbols.
+       * nm.1: Updated for -D (--dynamic) option.
+       * objdump.c (dump_dynamic_symtab): New global variable.
+       (dump_dynamic_reloc_info): New global variable.
+       (dynsyms, dynsymcount): New global variables.
+       (usage): Mention -R, -T, --dynamic-syms and --dynamic-reloc.
+       (long_options): Added "dynamic-reloc" and "dynamic-syms".
+       (slurp_symtab): If no symbols, return rather than exit.
+       (slurp_dynamic_symtab): New function.
+       (display_bfd): Handle dump_dynamic_symtab and
+       dump_dynamic_reloc_info.
+       (dump_symbols): Take new dynamic argument, indicating whether to
+       display dynamic symbols.
+       (dump_relocs): Move most printing into dump_reloc_set.
+       (dump_dynamic_relocs): New function.
+       (dump_reloc_set): New function, extracted from dump_relocs.
+       (main): Add R and T to getopt string.  Handle -T by setting
+       dump_dynamic_symtab and -R by setting dump_dynamic_reloc_info.
+       * objdump.1: Updated for -R (--dynamic-reloc) and -T
+       (--dynamic-syms) options.
+       * binutils.texi: Updated for new nm and objdump options.
+
+Wed Mar 30 15:52:40 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       Update for recent BFD changes to symbol and reloc reading.  Rename
+       all uses of get_symtab_upper_bound to bfd_get_symtab_upper_bound.
+       Also:
+       * coffgrok.c (symcount): Change to long.
+       (do_sections_p1): Check for error return from
+       bfd_get_reloc_upper_bound.  Change relcount to long, and check for
+       error from bfd_canonicalize_reloc.
+       (coff_grok): Change storage to long.  Check for error from
+       bfd_get_symtab_upper_bound and bfd_canonicalize_symtab.
+       * nlmconv.c (main): Change symcount, newsymalloc, newsymcount, and
+       i to long.  Check for error from bfd_get_symtab_upper_bound and
+       bfd_canonicalize_symtab.
+       (copy_sections): Change reloc_size and reloc_count to long.  Check
+       for error from bfd_get_reloc_upper_bound and
+       bfd_canonicalize_reloc.
+       (mangle_relocs, i386_mangle_relocs, alpha_mangle_relocs): Change
+       reloc_count_ptr argument to long *.  Make corresponding changes to
+       variables loaded from *reloc_count_ptr.
+       * nm.c (display_rel_file): Change storage and symcount to long.
+       Check for errors from bfd_get_symtab_upper_bound and
+       bfd_canonicalize_symtab.
+       * objcopy.c (filter_symbols): Change symcount, src_count and
+       dst_count to long.
+       (copy_object): Change symcount to long.  Pass another argument to
+       fprintf.  Check for errors from bfd_get_symtab_upper_bound and
+       bfd_canonicalize_symtab.
+       (copy_section): Change relcount to long.  Check for errors from
+       bfd_get_reloc_upper_bound and bfd_canonicalize_reloc.
+       (mark_symbols_used_in_relocations): Change relcount and i to long.
+       Check for errors form bfd_get_reloc_upper_bound and
+       bfd_canonicalize_reloc.
+       * objdump.c (storage): Remove global variable.
+       (symcount): Changed to long.
+       (slurp_symtab): New local variable storage.  Check for errors from
+       bfd_get_symtab_upper_bound and bfd_canonicalize_symtab.
+       (remove_useless_symbols): Change return value and count to long.
+       (objdump_print_address): Change min, max, thisplace and i to long.
+       (disassemble_data): Change i to long.
+       (dump_symbols): Change count to long.
+       (dump_relocs): Change relcount to long.  Check for errors from
+       bfd_ret_reloc_upper_bound and bfd_canonicalize_reloc.
+       (display_info_table): Add casts when passing LONGEST_ARCH for
+       printf %* argument.
+
+Tue Mar 29 14:59:04 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nm.c (display_archive): Close each archive element after it has
+       been displayed.
+       * objdump.c (display_file): Likewise.
+
+Mon Mar 28 13:04:08 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * configure.in: Change error message to refer to bfd/config.bfd
+       rather than bfd/configure.in.
+
+Sun Mar 27 16:23:39 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * More fixes for object formats which allow multiple sections
+       with the same name:
+       * objcopy.c (setup_section): Make a new output section even if
+       one already exists with the given name.
+       (copy_section): Use isection->output_section rather than trying
+       to look the output section up by its (possibly non-unique) name.
+
+       * Makefile.in (install-info): Look for binutils.info in the
+       current directory, then in $(srcdir).  Don't use $<.
+
+Mon Mar 21 12:55:45 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (objdump_print_address): Make static.  Declare with
+       prototype.  Change vardiff from int to bfd_signed_vma.  Correct
+       binary search termination condition.  When looking for same
+       section symbol in relocatable file, handle final symbol correctly.
+
+Sun Mar 20 11:26:36 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * Makefile.in: Avoid bug in hpux sed.
+
+       * objcopy.c: Changes to keep it from stripping symbols used
+       in output relocations.
+       (mark_symbols_used_in_relocations): New function.  Mark symbols
+       used in output relocations with BSF_KEEP.
+       (filter_symbols): Do not strip symbols marked with BSF_KEEP.
+       (copy_object): Reorder actions.  First setup sections, then
+       build the output symbol table, then copy the section contents.
+
+Fri Mar 18 10:53:55 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * ar.c (write_archive): Allocate space for the null byte.  From
+       Robert Lipe <robertl@arnet.com>.
+
+Thu Mar 17 16:20:28 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * Makefile.in: Built nm.new and strip.new to avoid problems with
+       collect when . is in PATH.
+       (STRIP_PROG): Change from strip to strip.new.
+       (NM_PROG): Change from nm to nm.new.
+       (install): Remove the .new when installing.
+
+Wed Mar 16 16:27:05 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (powerpc_build_stubs): Set BSF_DYNAMIC flag for each
+       symbol for which we build a stub.
+       (powerpc_mangle_relocs): Only reset TOC pointer for a call to a
+       symbol with BSF_DYNAMIC flag set.
+
+Tue Mar 15 23:04:13 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * objcopy.c (filter_symbols): Use bfd_is_local_label to determine
+       if a symbol represents a compiler-generated local label.
+       (copy_object): Give the BFD backends a chance to copy any private
+       bfd data from the input BFD to the output BFD.
+       (setup_section): Give the BFD backends a chance to copy any private
+       section data from the input section to the output section.
+
+Mon Mar 14 11:15:58 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * objcopy.c (mangle_section): Delete unused function.
+       (setup_section): Set osection here instead of calling
+       mangle section to do it.
+
+Mon Mar 14 12:11:01 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * ar.c (write_archive): Close inarch before unlinking it.
+
+Fri Mar 11 22:20:48 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (main): For PowerPC, call powerpc_build_stubs and
+       powerpc_resolve_stubs.  Use __GOT0, not __toc_start.  Handle it if
+       the start and end symbols are not in the text section.
+       (struct powerpc_stub): New struct definition.
+       (powerpc_stubs, powerpc_stub_insns): New static variables.
+       (powerpc_initial_got_size): New static variable.
+       (powerpc_build_stubs): New function.
+       (powerpc_resolve_stubs): New function.
+       (powerpc_mangle_relocs): Clear extraneous data in .got section.
+       Rearrange reloc handling to handle ELF relocs that are not
+       partial_inplace.  Resolve PC relative relocs.
+
+Wed Mar  9 13:48:11 1994  Steve Chamberlain  (sac@jonny.cygnus.com)
+
+       * ar.c (move_members): Fix it so that the abi positional modifiers
+       don't delete all archive members following the insert point.
+
+Tue Mar  8 13:14:43 1994  Steve Chamberlain  (sac@jonny.cygnus.com)
+
+       * coffgrok.[ch]: New files, understand coff objects.
+       * coffdump.c: Uses coffgrok to dump out the debug info of a coff
+       file.
+       * sysroff.info: Description of a SYSROFF object file.
+       * sysinfo.y, syslex.l: Parse info file, generate a reader, writer,
+       header files and a printer.
+       * srconv.c: Uses coffgrok.c and sysroff.info to convert a coff
+       file to a SYSROFF file.
+
+Sat Feb 26 13:35:26 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * ar.c (do_quick_append): Pad with a genuine character 10,
+       rather than whatever '\n' might happen to be.
+
+Tue Feb 22 18:25:52 1994  Ian Lance Taylor  (ian@cygnus.com)
+
+       * nlmconv.c (main): Ignore debugging symbols when looking for
+       special symbols by name.
+
+Sun Feb 20 18:47:42 1994  Ian Lance Taylor  (ian@lisa.cygnus.com)
+
+       * nlmconv.c: Include libiberty.h.
+
+       Support for PowerPC NetWare.
+       * nlmconv.c (main): For PowerPC NetWare, automatically define the
+       special symbols __toc_start.
+       (select_output_format): Handle bfd_arch_powerpc.
+       (mangle_relocs): Likewise.
+       (powerpc_mangle_relocs): New function.
+
+Thu Feb 17 09:28:23 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * ar.c, bucomm.c, nlmconv.c, nm.c, objcopy.c, objdump.c,
+       size.c: Use bfd_get_error and bfd_set_error and new error names.
+
+Fri Feb 11 15:54:51 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * objcopy.c (strip_main, copy_main): Add missing 'break' in switch.
+
+Mon Feb  7 19:45:52 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (disassemble_data): Handle bfd_arch_powerpc.
+
+Sun Feb  6 22:08:20 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * strings.c objdump.c nlmconv.c objcopy.c nm.c ar.c size.c (main):
+       Call xmalloc_set_program_name.
+
+Fri Feb  4 10:46:01 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * objcopy.c (filter_bytes): Make MEMHUNK a char *, not PTR, so we
+       can do arithmetic on it.
+
+Thu Feb  3 14:06:41 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * objdump.c (dump_section_stabs, read_section_stabs,
+       print_section_stabs): Functions broken out of dump_stabs_1.
+       Free the stabs and strings when done with them.
+
+Wed Feb  2 13:42:23 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * nlmconv.c (main): Use bfd_get_flavour instead of struct member.
+       * ar.c (print_contents, extract_file), size.c
+       (print_berkeley_format, print_sysv_format): Use bfd_get_filename and
+       bfd_my_archive instead of dereferencing the structs directly.
+
+       * ar.c: Use bfd_fatal and bfd_nonfatal instead of bfd_perror and exit.
+       Indent.  Remove DEFUNs.
+
+       * nlmconv.c (main), objcopy.c (copy_file): Print matching formats
+       if ambiguous match.
+       * nm.c (display_file, display_archive), size.c (display_bfd):
+       Eliminate gotos.
+       Print matching formats if there is an ambiguous match.  Use
+       bfd_nonfatal instead of hardcoded error message if nothing matches.
+
+       * arsup.c, ar.c, objdump.c: Use bfd_get_filename instead of
+       abfd->filename.
+
+       * nm.c (display_archive): New function, from code in display_file.
+       (display_rel_file): Renamed from do_one_rel_file.
+
+       * size.c: Indent.
+       (display_archive): New function from code in display_file.
+       (display_file): Check bfd_close error return.
+
+       * strings.c (strings_object_file): Check bfd_check_format
+       error return.
+
+       * strings.c, objdump.c, size.c: Use bfd_nonfatal instead of bfd_perror.
+
+       * bucomm.c: Delete references to exit_handler.  It wasn't set
+       anywhere, and now that we're using the libiberty xmalloc, it
+       wouldn't always get called before exiting.
+       (list_matching_formats): Function moved from objdump.c.
+       * bucomm.h: Declare it.
+
+       * objdump.c (disassemble_data): Move some variable decls closer to
+       their use.  Add some comments.  Replace a nested block with a
+       return.
+
+Mon Jan 31 18:50:41 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * objdump.c (display_target_list, display_info_table): Check that
+       the bfd of the dummy output file is not null.
+
+Wed Jan 26 13:13:18 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * objcopy.c (filter_bytes): New function.
+       (copy_section): Call it.
+       (copy_options, copy_usage, copy_main): Add --byte option to
+       activate it.  Appropriate the -b option (which was an undocumented
+       synonym for -F) for it, also.  Add --interleave, -i option for
+       additional control.
+       (setup_section, copy_section, mangle_section): Renamed with no `s'
+       on the end.
+       * objcopy.1, binutils.texi: Document the new options.
+
+       * objdump.c (display_target_tables, display_target_list):
+       New functions broken out of display_info.
+       Eliminate some magic constants.  Use more meaningful variable names.
+       (dump_bfd_header): New function broken out of display_bfd.
+       (dump_section_header): New function broken out of dump_headers.
+       (remove_useless_symbols): Don't shadow global variable name with
+       parameter.
+       (objdump_print_address): Fix backward test.
+
+Tue Jan 25 19:40:54 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * bucomm.c (print_arelt_descr): Change decl of `when' to time_t.
+       * objdump.h: Removed.
+
+Mon Jan 24 13:29:02 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * objdump.c (display_file): Remove call to list_matching_formats.
+       It would never be called.
+       (list_matching_formats): Take an arg giving the list of matching
+       formats.
+       (display_bfd): Pass the arg, and get it filled in by calling
+       bfd_check_format_matches instead of bfd_check_format.
+       (display_info, display_info_table): target_vector was renamed to
+       bfd_target_vector.
+
+       * binutils.texi (objdump): Note some limitations of -h section
+       address printing.
+
+Sat Jan 22 16:20:46 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * Makefile.in (MALLOC): Set to emptiness by default.
+       (ALL_CFLAGS): Add and use.
+       (arparse.h): Make it depend on arparse.y.
+       * ar.c (libbfd.h): Don't require to be in ../bfd.
+       * objdump.c (comp): Rename to compare_symbols.
+
+Fri Jan 21 20:22:30 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * objdump.c (list_matching_formats): If the file format is ambiguous,
+       print the matching names so the user can choose one.
+       (display_bfd): Call it.
+       (display_file): Call it.
+
+Fri Jan 21 19:17:25 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (disassemble_data): Support bfd_arch_rs6000.
+
+Mon Jan 17 13:57:25 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * objdump.c (stab_name): Allocate dynamically.
+       (stab_print): Use pointers to strings instead of char arrays.
+       (dump_stabs): Change alloc and init of arrays appropriately.
+       (dump_stabs_1): Always decide whether to print stab_name or
+       the stab's type number, if unnamed.
+
+Fri Jan 14 14:42:48 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objcopy.c (strip_main, copy_main): Don't clobber the input file
+       if copy_file fails.
+
+       * nlmconv.c (main): Warn about an attempt to use a shared library
+       with uninitialized data.
+
+       * nlmconv.c (setup_sections): Make sure that we align the
+       output_offset of each input section appropriately.
+
+Thu Jan 13 17:32:44 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (dump_relocs): Don't crash if section name is NULL.
+
+Tue Jan 11 19:46:33 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * filemode.c (filemodestring): Commented out; not used.
+       (mode_string): Use POSIX definitions.
+       (ftypelet): Likewise.
+       (rwx): Removed; no longer used.
+       * bucomm.c: Include bucomm.h.
+       (bfd_nonfatal, bfd_fatal): Argument is const.
+       (fatal): Make __STDC__ version.
+       * bucomm.h (mode_string): Declare.
+       * Makefile.in (bucomm.o): Depend upon bucomm.h
+
+Sun Jan  9 12:03:20 1994  Ken Raeburn  (raeburn@rtl.cygnus.com)
+
+       * bucomm.c (xmalloc, xrealloc): Deleted.
+       * bucomm.h (xmalloc, xrealloc): Fix prototypes, to correspond to
+       libiberty version of functions.
+
+Thu Jan  6 06:18:15 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * binutils.texi: Add a chapter summarizing the ways to select
+       aspects of the target for each program.
+
+       * objdump.c (long_options, usage): Add long equivalents for all
+       remaining short options that lacked them.
+       * binutils.texi objdump.1: Document them.
+
+       * size.c (usage): Tweak usage message.
+       * size.1: Add missing `=' in examples.
+
+       * binutils.texi strip.1 objcopy.1 nlmconv.1 objcopy.c nlmconv.c:
+       Use "--target=bfdname" as the option to select the BFD target,
+       like nm and size already do.
+       Reserve "--format=format" for textual output selection options, but
+       for now keep old option names as obsolete for backward compatibility.
+
+       * strings.c (main, strings_object_file, usage): Add --target option.
+       * binutils.texi strings.1: Document it.
+
+Sat Jan  1 13:58:24 1994  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * ar.c (main): Add \n in error message.
+
+Thu Dec 23 12:23:11 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       gcc -Wall lint:
+       * ar.c (main): Put parens around assignment used as truth value.
+       * objcopy.c (strip_main): Remove unused variables.  Return 0.
+       (copy_main): Remove unused variables.  Return 0.
+       * objdump.c (display_bfd): Declare return value as void.
+       (stab_print): Use "" instead of 0 to initialize array.
+       (dump_stabs_1): Print vma using printf_vma.
+       (display_info): Put parens around assignment used as truth value.
+       * strings.c (print_strings): Cast printf arguments.
+
+       * objcopy.c (copy_main): Use copy_options, not strip_options.
+
+       * nlmheader.y (command): Warn about illegal date values.
+
+Wed Dec 15 11:18:03 1993  David J. MacKenzie  (djm@frosty.eng.umd.edu)
+
+       * bucomm.c bucomm.h: Run through indent.  De-ansidecl-ify.
+       (bfd_nonfatal): New function.
+       (bfd_fatal): Call it.
+
+       * objcopy.c (smart_rename): Do a copy if the dest file has
+       multiple hard links.  Remove source file on successful copy.
+       Try to preserve mode and owner on successful rename.
+
+       * objcopy.c: Run through indent.  Clean up a bit.
+       Make global variables static.
+       Make {input,output}_{target,filename}, show_version local
+       to various functions.
+       New global variable `status' for exit status.
+       (strip_main, copy_main): New functions with code from main.
+       (nonfatal): New macro.  Use it globally instead of bfd_perror and
+       bfd_fatal.
+
+       (copy_object): Call mangle_sections with bfd_map_over_sections.
+       (mangle_sections): Adjust for new calling convention.
+
+Fri Dec 10 11:28:11 1993  Ian Lance Taylor  (ian@deneb.cygnus.com)
+
+       * nlmheader.y (command): Accept MAP and FULLMAP without arguments.
+       * nlmconv.c (main): Change error message for MAP and FULLMAP.
+
+Thu Dec  9 17:47:19 1993  Ian Lance Taylor  (ian@deneb.cygnus.com)
+
+       * nlmconv.c (main): Warn about imported symbols that are not in
+       the IMPORT list even if the IMPORT keyword is not used.
+
+       * nlmconv.c (debug, unlink_on_exit): New static variables.
+       (long_options): Add "debug" and "linker".
+       (main): Handle -d and -l arguments.  Make command line input and
+       output files optional.  Parse the command file before opening the
+       BFD's, which requires storing more information in local variables.
+       If INPUT names multiple files, link them together.  Use OUTPUT for
+       the output file name if not named on command line.
+       (show_usage): Changed for new options.
+       (link_inputs): New function to automatically invoke linker to
+       handle multiple INPUT files.
+       (choose_temp_base_try, choose_temp_base, pexecute): New functions,
+       mostly copied from gcc/gcc.c.
+       * nlmconv.h (input_files, output_file): Declare.
+       * nlmheader.y (input_files, output_file): Define.
+       (command): Support INPUT with a string_list argument.  Support
+       OUTPUT.
+       (string_list): Renamed from module_list.
+       * Makefile.in (nlmconv.o): Define LD_NAME based on
+       program_transform_name.
+
+Wed Dec  8 10:09:04 1993  Ian Lance Taylor  (ian@deneb.cygnus.com)
+
+       * nlmheader.y (nlmheader_identify): New function.  Use it to print
+       the program name just once, instead of with every error message.
+
+Mon Dec  6 16:11:32 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (long_options): Changed --header-info to --header-file
+       to match documentation and usage message.
+
+Sun Dec  5 01:31:01 1993  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * objdump.c (dump_relocs): Avoid dereferencing a NULL sym_ptr_ptr
+       in a relocation.
+
+Thu Dec  2 16:00:06 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (main): Change various types from bfd_size_type to
+       size_t, since they have to be arguments to fread and fwrite.
+       Change set from char * to unsigned char *.
+       (select_output_format): Make mach argument unsigned.  Handle
+       bfd_arch_alpha.
+       (setup_sections): Don't copy the .reginfo section of an ECOFF
+       file.  Call bfd_set_reloc to initialize the relocation fields.
+       (copy_sections): Don't copy the .reginfo section of an ECOFF file.
+       Combine all relocs for a section.
+       (mangle_relocs): Change type of relocs to permit specific
+       functions to change it.  Call alpha_mangle_relocs for alpha,
+       default_mangle_relocs for other architectures.
+       (default_mangle_relocs): New function.  Adjust the address of all
+       relocs by the output_offset.
+       (i386_mangle_relocs): Change type of relocs argument.  Cast length
+       argument to memmove to size_t.
+       (alpha_mangle_relocs): New function.
+
+Wed Nov 17 17:38:58 1993  Sean Eric Fagan  (sef@cygnus.com)
+
+       * nlmconv.c (select_output_format): Use nlm32-sparc for
+       bfd_arch_sparc.
+
+Wed Nov 17 14:41:35 1993  Jeffrey Osier  (jeffrey@thepub.cygnus.com)
+
+        * nlmconv.1:   added man page
+       * objcopy.1:   fixed format errors
+
+Wed Nov 17 12:03:41 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * Makefile.in: Use CFLAGS as well as LDFLAGS when linking.
+
+Wed Nov 17 04:50:55 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * strings.1: Fix typo.
+
+Mon Nov 15 12:03:20 1993  Ken Raeburn  (raeburn@rtl.cygnus.com)
+
+       * Makefile.in (DISTSTUFF): Build "info".
+       (VERSION): Updated to cygnus-2.3.1; 2.3 has gone out.
+
+Sun Nov 14 00:27:24 1993  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * objdump.c (dump_stabs): Handle stabs-in-som as implemented
+       by the new BFD SOM assembler.
+
+Sat Nov 13 07:14:05 1993  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * ar.1 c++filt.1 nm.1 objcopy.1 objdump.1 ranlib.1 size.1
+       strings.1 strip.1: Replace \(em in NAME section with \- so
+       makewhatis can grok it.
+
+Tue Nov  9 15:22:12 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (i386_mangle_relocs): Adjust reloc address by
+       section output_offset.
+
+Fri Nov  5 12:11:52 1993  Jeffrey Osier  (jeffrey@thepub.cygnus.com)
+
+       * binutils.texi:  added nlmconv chapter
+
+Wed Nov  3 16:10:50 1993  Jeffrey Wheat  (cassidy@cygnus.com)
+
+       * Makefile.in: Change RUNTESTFLAGS to RUNTEST_FLAGS
+
+Wed Nov  3 15:09:23 1993  Ken Raeburn  (raeburn@rover.cygnus.com)
+
+       * Makefile.in (distclean): Don't get rid of dvi or info files.
+
+Tue Nov  2 13:29:59 1993  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * objcopy.c (S_ISLNK): Define as 0 if there's no S_IFLNK.
+
+Fri Oct 29 16:02:34 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * binutils.texi: Move objcopy docs into alphabetical order.
+
+       * objdump.c: Use xmalloc instead of malloc.
+
+Fri Oct 29 11:11:14 1993  Stan Shebs  (shebs@rtl.cygnus.com)
+
+       * objdump.c (info): Rename to formats_info.
+       (dump_stabs_1): Better comments and formatting.
+
+Thu Oct 28 19:43:16 1993  Stan Shebs  (shebs@rtl.cygnus.com)
+
+       * ar.c (main): Always create the archive when quick appending,
+       even if no input files have been given.
+
+Wed Oct 27 12:03:06 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (main): Set sharedDebugRecordOffset and
+       sharedDebugRecordCount fields in extended header.
+
+       * nlmconv.c (main): Force moduleName field to upper case.
+
+Mon Oct 25 16:45:42 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objcopy.c (main): Give a usage message if there are too many
+       arguments.
+
+Mon Oct 25 10:37:08 1993  Ken Raeburn  (raeburn@rover.cygnus.com)
+
+       * Makefile.in (install-info): Rewrite to take advantage of VPATH,
+       so FSF distributions (with info files in $(srcdir)) install
+       properly.
+       (DISTSTUFF): Build nlmheader.c too.
+
+Fri Oct 22 11:43:23 1993  Ken Raeburn  (raeburn@rover.cygnus.com)
+
+       * ar.c (program_name): Don't define here.
+       * objdump.c: Include "bucomm.h".
+       (xmalloc): Don't declare here.
+       (program_name): Don't define here.
+       (program_version): Fixed type in declaration.
+       * size.c: Include "bucomm.h".
+       (program_name): Don't declare here.
+
+Fri Oct 22 14:10:41 1993  Mark Eichin  (eichin@cygnus.com)
+
+       * objdump.c (fprintf): hide declaration in FPRINTF_ALREADY_DECLARED
+
+Fri Oct  1 12:43:00 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (i386_mangle_relocs): Resolve and remove PC relative
+       relocs against defined symbols in the same section.
+
+Thu Sep 30 16:46:26 1993  Roland H. Pesch  (pesch@fowanton.cygnus.com)
+
+       * Makefile.in (binutils.dvi): use TEXIDIR to find texinfo.tex
+
+Sat Sep 25 18:09:29 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * objcopy.c (simple_copy, smart_rename): New functions.
+       (main): Use them.
+
+Fri Sep 24 15:38:29 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * Makefile.in (clean, distclean): Recurse into testsuite.
+
+Thu Sep 23 01:05:06 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objcopy.c (setup_sections, copy_sections): If stripping, don't
+       copy SEC_DEBUGGING sections.
+       * objdump.c (dump_headers): Print SEC_DEBUGGING flag.
+
+       * objdump.c (usage): Mention --stabs.
+
+       * objcopy.c (copy_object): Copy all applicable file flags.
+       (copy_file): Don't copy EXEC_P specially here.
+
+Mon Sep 20 19:28:57 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (main): Adjust data section size to correspond to bss
+       alignment adjustment.  Clear BSF_SECTION_SYM if symbol is moved to
+       a different section.  Use time_t for time variable.
+       (setup_sections): Only put sections with contents in output NLM.
+       (i386_mangle_relocs): No symbols are common at this point.  Add
+       casts to avoid warnings.
+
+Fri Sep 10 11:00:40 1993  Stan Shebs  (shebs@rtl.cygnus.com)
+
+       * objdump.c: Made the --stabs option work for stabs-in-coff.
+       (ELF_STAB_DISPLAY): Removed.
+       (dump_elf_stabs): Renamed to dump_stabs, changed to run for
+       any object file format.
+       (dump_elf_stabs_1): Renamed to dump_stabs_1, added calls to
+       generic BFD routines for non-ELF case, changed format of message
+       for no-section-found case.
+       (display_bfd): Always call dump_stabs if requested.
+       (dump_data): Call bfd_section_size to get section size.
+
+Fri Sep 10 08:12:23 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * Makefile.in (install): Don't put strings in tooldir/bin.
+
+Mon Sep  6 15:39:04 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (total_bss_size): Removed.
+       (main): Set the bss vma to always follow the data section.  Move
+       symbols into new sections, and adjust values by output_offset.
+       (setup_sections): Don't copy all sections, but instead point all
+       text sections to .text, all data sections to .data, and all bss
+       sections to .bss.
+       (copy_sections): Adjust accordingly.
+
+Thu Sep  2 12:34:03 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       Only build nlmconv if configured for a NetWare target.
+       * configure.in: If we have some *-*-netware* target, or are using
+       all targets, set BUILD_NLMCONV to $(NLMCONV_PROG) in Makefile.
+       * Makefile.in (PROGS): Use $(BUILD_NLMCONV) rather than
+       $(NLMCONV_PROG).
+
+Tue Aug 31 14:13:35 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
+
+       * objdump.c (ARCH_all): Define ARCH_hppa too.
+       (dump_headers): Don't test for SEC_BALIGN if it's not defined by
+       bfd.h.
+
+Tue Aug 31 13:29:12 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * nlmconv.c (main): Force creation of .bss section.  Set up the
+       sections before looking at the symbols.  Move all common symbols
+       into .bss section.  Automatically define _edata and _end.  Only
+       export symbols in the export list, with multiple prefixes if
+       necessary.  Warn if no version.  Always create extended header.
+       Set date automatically if not already set.
+       (setup_sections): Count size of bss sections.
+       (mangle_relocs, i386_mangle_relocs): Accept section argument, and
+       take reloc_count as a changeable pointer; changed callers.
+       (i386_mangle_relocs): Remove PC relative relocs within a section,
+       as they require no adjustment.
+       * nlmheader.y: Fixed memory allocation throughout: token STRING is
+       now allocated on the heap, and freed if not needed.  Null
+       terminated copyright message.  Accept version with only two
+       strings.
+       (symbol_list_opt): New nonterminal, either symbol_list or empty.
+       (symbol_list): Use left recursion to avoid overflowing parser
+       stack.
+       (yylex): Rearranged beginning of line check.  Accept quoted
+       strings using single quotes.  End generic argument at comment
+       character or parentheses.
+       (string_list_append): Fixed.
+       (string_list_append1): New function.
+
+       * bucomm.h: The first argument to xrealloc is PTR, not char *.
+       * bucomm.c (xrealloc): Use PTR rather than char *.
+       * Makefile.in (objdump.o): Depend upon config.status to notice
+       --with-targets changes.
+       (nlmconv.o): Depend upon bucomm.h.
+
+Tue Aug 17 09:46:01 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * configure.in: Don't pass cpu to config.bfd.
+
+Thu Aug 12 16:43:04 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * Makefile.in ($(NM_PROG)): Depend on demangle.o.
+       (demangle.o): New target.
+       (cplus-dem.o): Depend on it, to force compilation order when doing
+       parallel compiles.
+
+       * nm.c (print_symbol_info_{bsd,sysv,posix}): Take a bfd arg.
+       (struct output_fns print_symbol_info): Ditto.
+       (long_options, usage, main): Add -C --demangle option.
+       (print_symname): New function, demangling if requested.
+       (print_symbols, print_symbol_info_{bsd,sysv,posix}): Use it.
+
+Wed Aug 11 22:57:23 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * Makefile.in: Put CFLAGS last in compilation rules and omit from
+       linking rules.  Use ARCHDEFS to compile objdump.c.
+       Update dependencies.
+       * configure.in: Construct ARCHDEFS based on the BFD target makefile
+       fragments.
+       * objdump.c: Conditionalize calls to the print_insn_ARCH functions
+       according to ARCHDEFS.
+
+Thu Aug 12 08:06:15 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * ar.c: Removed obsolete and non-functional GNU960 code.
+
+Wed Aug 11 13:08:26 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * size.c (berkeley_sum): New function.
+       (bsssize, datasize, textsize): New global variables.
+       (bss_section_name, data_section_name, text_section_name): Removed.
+       (print_berkeley_format): Map berkeley_sum over all the sections,
+       rather than only reporting sizes of specifically named sections.
+       * Makefile.in ($(OBJDUMP_PROG)): Removed dependency on size.o.
+
+Tue Aug 10 10:46:01 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * nlmconv.c, nlmconv.h, nlmheader.y: New files for program to
+       convert object files into NetWare Loadable Modules.
+       * Makefile.in (NLMCONV_PROG): New macro, define to be nlmconv.
+       (PROGS): Add NLMCONV_PROG.
+       (nlmheader.c, nlmheader.o, nlmconv.o, $(NLMCONV_PROG)): New
+       targets.
+
+Thu Aug  5 15:48:32 1993  david d `zoo' zuhn  (zoo@rtl.cygnus.com)
+
+       * Makefile.in: define MAKEOVERRIDES to an empty string
+
+Wed Aug  4 17:08:08 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * objcopy.c (copy_file): Make failures to process a file nonfatal.
+
+Mon Aug  2 11:28:23 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * nm.c: Add -B option, like --format=bsd.
+
+Tue Jul 27 16:29:54 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objcopy.c (copy_file): If the file is neither an object nor an
+       archive, give an error rather than returning success.
+
+Mon Jul 19 16:13:40 1993  Ken Raeburn  (raeburn@rtl.cygnus.com)
+
+       * objdump.c (objdump_print_address): Prefer non-local symbols over
+       local ones, and especially discriminate against debugging symbols.
+       Also, for relocateable files, try to find a symbol in the current
+       section, instead of picking one from some random section with a
+       convenient value (read, section offset).
+       (disassemble_data): Cast argument to malloc to size_t first.
+       (dump_data): Likewise.
+       (dump_relocs): If a single section name is specified, show relocs
+       only for that section.  Otherwise, silently omit sections without
+       relocs.  Format table nicely even if values are printed using 16
+       digits instead of 8.
+
+Fri Jul 16 15:19:59 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * nm.c: Changes for final version of POSIX.2.
+       (print_symbol_filename_{bsd,sysv,posix}): New functions.
+       (formats): Add an element for a pointer to them.
+       (print_symbols): Call it.
+       (print_object_filename_posix, print_archive_member_posix): Produce
+       output according to new POSIX.2 spec.
+
+       * strings.c (print_strings): Handle STREAM being NULL.
+       (strings_a_section): Pass a NULL.
+       (main): Don't open /dev/null.
+
+Thu Jul 15 12:44:09 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (disassemble_data): Handle the m88k.
+       (display_bfd): Use bfd_errmsg, rather than just claiming that the
+       bfd is not an object file.
+
+Mon Jul 12 17:55:34 1993  K. Richard Pixley  (rich@cygnus.com)
+
+       * Makefile.in (TAGS): make work again by naming directories
+         explicitly rather than depending on undefined macros.
+         (INSTALL_XFORM): correct bad install target.
+
+Fri Jul  2 16:58:34 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * strings.c: Doc fixes.
+
+Sun Jun 27 13:35:24 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * Makefile.in: Note dependencies on bucomm.h.
+       (cplus-dem.o): Link c++filt with version.o.
+
+       * strings.c: Include bucomm.h and add prototypes to other decls.
+       Remove -h option.
+
+       * bucomm.h: Declare xrealloc.
+
+       * nm.c, objcopy.c, objdump.c, size.c, strings.c (main, usage): Add
+       --help option.  Put "GNU" in the version message.
+       (usage): Take stream and exit status as args.
+       (main): Pass new args to usage.
+
+Fri Jun 25 23:12:12 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * strings.c, strings.1: New files.
+       * binutils.texi: Document strings.
+       * Makefile.in: Add rules for it.
+
+Fri Jun 25 20:44:43 1993  Ken Raeburn  (raeburn@poseidon.cygnus.com)
+
+       * objdump.c: Use size-independent bfd elf section names.
+
+Sun Jun 20 23:09:06 1993  Ken Raeburn  (raeburn@poseidon.cygnus.com)
+
+       * objdump.c (objdump_print_address): Handle wide offsets by
+       calling sprintf_vma.
+
+Fri Jun 18 14:29:12 1993  Per Bothner  (bothner@deneb.cygnus.com)
+
+       * objdump.c (syms2):  Removed unused variable.
+       * objdump.c (remove_useless_symbols):  New function.
+       * objdump.c (comp):  Simplify.
+       * objdump.c (dis-assemble_data):  Make simpler and more
+       efficient how we filter out useless symbols:  Just filter
+       BEFORE the sort (using remove_useless_symbols).
+       * objdump.c (objdump_print_address):  Simplify.
+       Change output syntax to match gdb.
+
+Thu Jun 17 16:53:56 1993  david d `zoo' zuhn (zoo@cygnus.com)
+
+       * Makefile.in: canonicalize install.sh; for use within
+       this directory (and subdirs)
+
+Mon Jun 14 12:13:22 1993  david d `zoo' zuhn  (zoo at rtl.cygnus.com)
+
+       * Makefile.in (install, install-info): remove parentdir support,
+       use INSTALL_XFORM; define INSTALL_XFORM
+
+Thu Jun 10 17:29:21 1993  Per Bothner  (bothner@cygnus.com)
+
+       * objcopy.c (copy_object):  Fix bad size passed to xmalloc().
+
+Mon Jun  7 12:41:12 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in (INCLUDES):  Add -I../bfd for sysdep.h and bfd.h.
+       * configure.in:  No longer need to configure to get sysdep.h.
+       * objcopy.c (copy_object):  Fix symbol table handling.
+
+Fri Jun  4 17:20:03 1993  Per Bothner  (bothner@cygnus.com)
+
+       * objcopy.c (filter_symbols):  Cannot filter the symbols
+       in place, because that confuses the relocs, so take separate
+       parameter for output array.
+       * objcopy.c (sympp):  Make two variables: isympp and osympp.
+       * objcopy.c (copy_object):  Allocate separate array (osympp)
+       for filtered symbols.
+
+Fri Jun  4 10:51:44 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: change recursion test to presence of a configured
+       testsuite directory
+
+Thu Jun  3 14:05:57 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
+
+       * Makefile.in (underscore.c): Hack the backquoted command so it
+       doesn't cause Solaris make to bomb.
+
+Thu Jun  3 10:40:19 1993  Jeffrey Osier  (jeffrey@cygnus.com)
+
+       * Makefile.in:  added c++filt and objcopy to MANPAGES variable
+
+Thu Jun  3 00:32:52 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: rename LOADLIBES to EXTRALIBS
+
+Wed Jun  2 18:30:24 1993  Jeffrey Osier  (jeffrey@cygnus.com)
+
+       * c++filt.1, objcopy.1:  new man pages
+
+Fri May 28 15:01:24 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in (install):  Also install ar and ranlib in
+       $(tooldir)/bin;  needed for building libgcc.a.
+       * objdump.c (objdump_print_address):  Fix the check
+       "coincidental" label matches by dis-allowing undefined
+       or com symbols.
+
+Thu May 27 16:58:31 1993  Jeffrey Osier  (jeffrey@cygnus.com)
+
+        * biutils.texi:  revised c++filt chapter
+
+Wed May 26 17:24:17 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in (FLAGS_TO_PASS): Pass down CC and CFLAGS.
+
+Tue May 25 00:26:47 1993  Ken Raeburn  (raeburn@cygnus.com)
+
+       * objdump.c (slurp_symtab): Print warning for bad symbol table.
+       (bfd_elf32_find_section, Elf32_Internal_Shdr): Updated
+       declarations and uses.
+
+       * Makefile.in (DISTSTUFF): Don't build binutils.mm.
+
+Fri May 21 10:51:19 1993  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * nm.c: Add -f/--format, -P/--portability, -t/--radix options.
+       Make global variables static.
+       (main): Make -v like -n, not -V, and make -A like -o, for POSIX.2.
+       (set_print_radix, set_output_format,
+       print_{object_filename,archive_filename,archive_member,symbol_info}
+       {bsd,sysv,posix}): New functions.
+       (display_file, print_symbols): Call them.
+
+       * ar.c: Improve error messages.
+
+       * nm.c (main): Handle long options that just set a flag.
+
+       * nm.c (main), ar.c (do_show_version), objcopy.c (main), size.c
+       (main): Exit after printing the version number, per the GNU coding
+       standards.
+
+Mon May 17 13:20:25 1993  Per Bothner  (bothner@cygnus.com)
+
+       * README, Makefile.in:  Minor updates for 2.2.
+
+Fri May 14 11:12:26 1993  Per Bothner  (bothner@cygnus.com)
+
+       * Makefile.in (underscore.c):  Automatically generate
+       (using nm) a file with the variable prepends_underscore.
+       * Makefile.in (c++filt):  Link underscore.o with cplus-dem.o
+       so that initial underscores get removed iff appropriate.
+       * binutils.texi:  Preliminary documentation for c++filt.
+       * Makefile.in, binutils.texi:  Set to version 2.2.
+
+       * NEWS:  Mention copy->objcopy renaming and new c++filt program.
+
+Wed May 12 12:05:36 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in (cplus-dem.o, $(DEMANGLER_PROG)): Build the
+       demangler via cplus-dem.o, rather than directly from the .c file.
+
+       * objcopy.c: Renamed from copy.c, updated comments accordingly.
+       * Makefile.in, binutils.texi: Renamed copy to objcopy.
+       * is-strip.c, maybe-strip.c, not-strip.c: Updated comments for
+       rename of copy to objcopy.
+
+Mon May 10 17:20:18 1993  Per Bothner  (bothner@cygnus.com)
+
+       * binutils.texi (strip, -v option):  Fix typo.
+
+Fri May  7 13:57:50 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in (RUNTEST): Define.
+       (FLAGS_TO_PASS): Pass down RUNTEST.
+
+Tue May  4 10:06:50 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in (DEMANGLER_PROG): Name it c++filt.
+       (PROG): Also build and install COPY_PROG.
+
+Mon May  3 19:11:48 1993  Per Bothner  (bothner@cygnus.com)
+
+       * Makefile.in:  Change definition of $(tooldir) to match FSF.
+
+Wed Apr 28 23:41:32 1993  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * size.c (usage): Add missing options.
+       (main): Clean up option parser.
+
+       * objdump.c (usage): Add missing options.
+       (display_file): Print program name before calling
+       bdf_perror.
+
+       * nm.c (usage): Add missing options.
+       (main): Clean up option parser.
+       (display_file): Print program name before calling
+       bdf_perror.
+
+       * copy.c (copy_usage, strip_usage): Add missing options.
+
+       * ar.c (usage): New function.
+       (main): Call it.
+       (open_inarch, do_quick_append): Print program name before calling
+       bdf_perror.
+
+Thu Apr 22 15:01:35 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * nm.c (main): Accept and ignore -A and -B for MIPS compatibility.
+
+Mon Apr 19 14:06:59 1993  Rob Savoye  (rob@cygnus.com)
+
+       * Makefile.in: Added FLAGS_TO_PASS so tests get run on freshly
+       built binaries if they exist. (otherwise the path)
+
+Wed Apr  7 22:22:50 1993  Rob Savoye  (rob@cygnus.com)
+
+       * Makefile.in: Changed check target to use DejaGnu.
+
+Thu Apr  1 12:37:13 1993  Jim Kingdon  (kingdon@cygnus.com)
+
+       * Makefile.in: Remove am29k-pinsn.c, i960-pinsn.c.
+       objdump.c: a29k and i960 are `disassemble' not `print'.
+
+       * objdump.c: Rename print_address to objdump_print_address
+       and change parameters.
+       (disassemble_data): Use objdump_print_address.
+
+Wed Mar 31 10:25:29 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * objdump.c (disassemble_data): print_insn_sparc is now a
+       `disassemble' not a `print'.
+       Makefile.in: Remove sparc-pinsn.c (now in libopcodes.a).
+
+       * objdump.c (disassemble_data): Use new read_memory_func stuff.
+
+Thu Mar 25 10:38:11 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
+
+       * objdump.c (fprintf): Declaration of variadic function had better
+       be a prototype for ANSI C systems.
+
+Mon Mar 22 23:19:46 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: rename test-install to install-check
+
+Fri Mar 19 14:40:08 1993  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * objdump.c (disassemble_data): Add H8500.
+
+Fri Mar 19 10:56:51 1993  Jim Kingdon  (kingdon@cygnus.com)
+
+       * objdump.c (usage): Mention long options.
+
+Thu Mar 18 14:22:17 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * nm.c:  Modify behavior of -o flag for archives to match
+       BSD4.4 and Sunos 4:  Prefix archive name before each line.
+
+       * m68k-pinsn.c:  Removed.  Subsumed by ../opcodes/m68k-dis.c.
+       * i386-pinsn.c:  Removed.  Subsumed by ../opcodes/i386-dis.c.
+       * Makefile.in:  Adjust accordingly.
+       * objdump.c:  Support new-style disassemblers (ones that use
+       the interface of ../include/dis-asm.h).
+
+Thu Feb 25 15:57:00 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in:  When making tar file, remove texinfo/*,
+       except for texinfo/texinfo.tex.
+       * ardup.c:  Add extern declaration of strdup.
+       * Makefile.in (testsuite):  Add 'else true' since otherwise
+       Ultrix /bin/sh complains.
+
+Wed Feb 24 19:44:18 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in:  Set VERSION to 2.1.
+       * README, NEWS: Updates.
+       * nm.c:  Add -v as a synonym for -V.
+
+Tue Feb 23 19:00:50 1993  Mike Werner  (mtw@poseidon.cygnus.com)
+
+       * configure.in: added testsuite to configdirs.
+       * Makefile.in: added support for building testsuite.
+
+Mon Feb 22 22:52:10 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * objdump.c (disassemble_data):  Print function names when
+       given by bfd_find_nearest_line.  If not - still print
+       line numbers.
+
+Mon Feb 22 07:54:03 1993  Mike Werner  (mtw@poseidon.cygnus.com)
+
+       * binutils/testsuite: made modifications to testcases, etc., to allow
+        them to work properly  given the reorganization of deja-gnu and the
+       relocation of the testcases from deja-gnu to a "tool" subdirectory.
+
+Mon Feb 22 10:27:24 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
+
+       * objdump.c (dump_data): Free up section contents each time
+       through the loop.  Reported by minyard@bnr.ca.
+
+Sun Feb 21 10:55:55 1993  Mike Werner  (mtw@poseidon.cygnus.com)
+
+       * binutils/testsuite: Initial creation of binutils/testsuite.
+       Migrated dejagnu testcases and support files for testing nm to
+       binutils/testsuite from deja-gnu.  These files were moved "as is"
+       with no modifications.  This migration is part of a major overhaul
+       of dejagnu.  The modifications to these testcases, etc., which
+       will allow them to work with the new version of dejagnu will be
+       made in a future update.
+
+Fri Feb 12 10:05:20 1993  Fred Fish  (fnf@cygnus.com)
+
+       * Makefile.in (LIBIBERTY_SRC_DIR, LIBIBERTY_BIN_DIR): New macros.
+       * Makefile.in (LIBIBERTY):  Use LIBIBERTY_BIN_DIR.
+       * Makefile.in (DEMANGLER_PROG):  New program to build.  Add macro
+       and rule.
+       * Makefile.in (PROGS):  Add DEMANGLER_PROG.
+
+Tue Jan 26 11:56:33 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * copy.c, nm.c, objdump.c, size.c: Use new bfd_is_com_section
+       macro rather than checking for equality to bfd_com_section.
+
+Fri Jan  8 15:50:05 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (disassemble_data): Fix code to find first useless
+       symbol.
+
+Thu Jan  7 13:13:31 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objdump.c (disassemble_data): Use mips_print_insn for MIPS.
+       Don't core dump if bfd_find_nearest_line returns false.
+
+Wed Jan  6 17:14:01 1993  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * objdump.c (disassemble_data): know how to disassemble z8000s
+       too.
+
+Wed Jan  6 15:16:27 1993  Per Bothner  (bothner@cygnus.com)
+
+       * arsup.h (interactive), bucomm.h (program_name):  Prefix
+       with 'extern', to avoid warnings from some compilers.
+
+Wed Jan  6 15:14:11 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * arparse.y: fix unnecessary shift/reduce
+
+Tue Dec 22 15:46:56 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in:  Make check depend on all.
+       * Makefile.in (distclean): Remove sysdep.h.
+       * size.c:  Use %u format where appropriate.
+       * objdump.c:  Standardize:  L_SET -> SEEK_SET.
+       * objdump.c:  Use new macro bfd_asymbol_bfd.
+       * configure.in:  Allow std-host as the default ${mys_host}.
+
+Thu Dec 17 19:38:19 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: added dvi target, define and use TEXI2DVI
+
+Tue Dec 15 18:05:07 1992  Per Bothner  (bothner@cygnus.com)
+
+       * Makefile.in (dist):  Fix permissions before release.
+       * size.c:  Use bfd_size_type (and long) where appropriate.
+       * ar.c:  Make writing a map the default, to be compatible
+       with SYSV and Posix.2.  Remove some bogus kludges that
+       handled __.SYMDEF directly.
+       * NEWS:  New file.
+
+Mon Nov  9 13:36:53 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: flex no longer needs the -S flag
+
+Sat Nov  7 15:06:13 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+        * ar.c (extract_file): utime needs a pointer to a utimbuf
+
+       * Makefile.in: handle -I includes better, adding $(BASEDIR)/bfd to
+       the list (since some of the bfd/hosts/*.h files include other
+       files from that directory)
+
+Fri Nov  6 00:12:51 1992  John Gilmore  (gnu@cygnus.com)
+
+       * i960-pinsn.c (MEM_MAX, MEM_SIZ):  Set upper bound properly.
+
+Thu Nov  5 03:37:15 1992  John Gilmore  (gnu@cygnus.com)
+
+       Clean up some old BFD ansification macros.
+
+       * arsup.h, bucomm.h, objdump.h:  Remove EXFUN from binutils.
+       It still remains as a local macro in gmalloc.c, which is derived
+       from some other copy of GNU Malloc somewhere (FIXME).
+
+       * ar.c, objdump.c, size.c:  Replace EXFUN with PROTO.  Make static
+       fns really static.
+       * arsup.h:  Declare extract_files.
+
+Mon Nov  2 12:42:11 1992  Ian Lance Taylor  (ian@cygnus.com)
+
+       * ar.c (extract_file): instead of checking USG: if POSIX_UTIME,
+       use utime and utimbuf structure, otherwise if USE_UTIME use utime
+       and array of two longs, otherwise use utimes.
+
+Thu Oct 15 13:57:35 1992  Per Bothner  (bothner@cygnus.com)
+
+       * binutils.tex:  Document yesterday's changes to strip and copy.
+
+Wed Oct 14 13:22:14 1992  Per Bothner  (bothner@cygnus.com)
+
+       * copy.c:  Re-do command-line parsing to use getopt_long().
+       Add long option names.  Re-think option letters to be more
+       consistent.
+       * copy.c:  New function filter_symbols() for stripping only
+       debug-symbols and/or local symbols.  Use these to support
+       the previously-missing options of the old FSF strip.
+
+Tue Oct 13 01:24:20 1992  John Gilmore  (gnu@cygnus.com)
+
+       * configure.in (host):  Use ${srcdir}/../bfd/configure.host rather
+       than repeating a copy of it here.
+
+Wed Oct  7 12:53:52 1992  Ken Raeburn  (raeburn@cygnus.com)
+
+       * copy.c (main): Even if is_strip, accept -d argument indicating
+       alternate output format.  Needed by gdb for Nindy.
+
+       * m68k-pinsn.c (print_insn_arg): Handle new "`" operand type.
+
+Tue Oct  6 16:33:56 1992  Jeffrey Osier  (jeffrey@cygnus.com)
+
+       * binutils.texi:  added documentation for "copy"
+
+Tue Oct  6 14:22:56 1992  Per Bothner  (bothner at PersSony)
+
+       * Makefile.in (*clean rules): Some cleaning up.
+       * Makefile.in (dist): Make diststuff in gprof for a dist.
+
+       * ar.c (do_show_version):  New function.
+       * ar.c (main):  Fix so "ar -V" works.
+
+Thu Oct  1 22:44:45 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * configure.in: now uses the cpu-vendor-os triple instead of
+       nested cases.
+
+Fri Sep 25 22:41:08 1992  John Gilmore  (gnu@cygnus.com)
+
+       * i960-pinsn.c:  Change bzero to memset.
+       * sparc-pinsn.c:  Change index to strchr.
+
+Mon Sep 21 14:39:56 1992  Ian Lance Taylor  (ian@cygnus.com)
+
+       * m68k-pinsn (print_insn_arg, fetch_arg): added support for
+       operands to memory management instructions, from WRS.
+
+Tue Sep 15 15:26:38 1992  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in (install): if $(tooldir) exists, install nm and
+       strip in $(tooldir)/bin.
+
+Thu Sep  3 11:57:40 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in:  Let's call it version 2.0.
+
+Wed Sep  2 00:25:13 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in:  Bump to version 0.98.
+       * TODO, README:  Minor updates.
+
+       * Makefile.in:  Added mostlyclean, distclean rules,
+       and cleaned up clean, realclean.
+
+Sun Aug 30 21:18:59 1992  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in: map program names through program_transform_name
+       when installing.
+
+Sun Aug 30 18:09:03 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in:  Bump to versions 1.97.90.
+       * cplus-dem.c:  Removed.  Was nowhere used - and if some
+       programs are changed to to demangling should now use the
+       versions in libiberty.
+
+Thu Aug 27 12:58:09 1992  Brendan Kehoe  (brendan@cygnus.com)
+
+       * configure.in: add we32k
+
+Mon Aug 24 14:53:42 1992  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * ar.c (map_over_members): if the element of the archive has a
+       null name, fill it in.
+
+       * nm.c (do_one_rel_file): only warn if a bfd's flags say there
+       will be symbols and there aren't any.
+
+Wed Aug 19 11:20:25 1992  Ian Lance Taylor  (ian@cygnus.com)
+
+       * m68k-pinsn.c: handle new operand type 'r', introduced for cas2.
+
+Tue Aug 18 20:45:48 1992  Rob Savoye  (rob@cygnus.com)
+
+       * nm.c objdump.c: Added support for a +version (-V)
+       to print the version number.
+
+       * ar.c, copy.c: Added support for a -V option to print
+       the version number.
+
+Tue Aug 18 13:28:44 1992  Ian Lance Taylor  (ian@cygnus.com)
+
+       * config/mh-apollo68v: removed -g from CC definition.
+
+       * Makefile.in: always create installation directories.
+
+Mon Aug 17 18:33:41 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * m68k-pinsn.c:  Minor fix in style of output (don't use
+       range to indicate floating point control registers).
+
+Tue Aug 11 23:42:21 1992  Per Bothner  (bothner@cygnus.com)
+
+       * ar.c (main):  Don't *always* set the verbose flag!
+
+Wed Aug  5 11:25:27 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * copy.c:  When is_strip (because it is invoked as the strip
+       program), follow traditional argv processing:
+       'strip file1 file2' now strips file1 and file2, rather
+       than stripping file1 (as input), leaving output in file2.
+
+Mon Jul 27 16:28:08 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * objdump.c (display_info, display_info_table):  Call
+       bfd_set_format() on dummy bfd before using it (twice).
+       * ar.c:  Make sure archive is created on command 'r'
+       even when no elements are inserted.  (Clean up and
+       simplify some non-working related code.)
+
+Mon Jul 20 02:48:38 1992  D. V. Henkel-Wallace  (gumby@cygnus.com)
+
+       * configure.in: hppa support doesn't assume hp OS (from sef).
+
+Sat Jul 18 14:35:22 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * configure.in: recognize hppa hosts (bsd & hpux), error messages
+       to stderr, not stdout
+
+Fri Jul 17 18:39:44 1992  K. Richard Pixley  (rich@rtl.cygnus.com)
+
+       * ar.1, binutils.texi, i960-pinsn.c, nm.1, objdump.1, ranlib.1,
+         size.1, sparc-pinsn.c, strip.1: removed rcsid's.
+
+Thu Jul 16 16:55:24 1992  K. Richard Pixley  (rich@rtl.cygnus.com)
+
+       * Makefile.dos: removed rcsid.
+
+Thu Jul 16 08:23:07 1992  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * objdump.c (display_bfd): print state of BFD_IS_RELAXABLE too
+
+Tue Jun 30 20:26:15 1992  D. V. Henkel-Wallace  (gumby@cygnus.com)
+
+       * Makefile.in: Add program_suffix (parallel to program_prefix)
+
+Thu Jun 25 04:52:45 1992  John Gilmore  (gnu at cygnus.com)
+
+       * nm.c (sorters):  Lint.  Remove excess whitespace.
+
+Wed Jun 24 13:48:07 1992  Per Bothner  (bothner@cygnus.com)
+
+       * nm.c (valueof macro):  Add missing parentheses.
+       (Their lack screwed up numeric_forward().)
+
+Sun Jun 14 10:33:27 1992  John Gilmore  (gnu at cygnus.com)
+
+       * objdump.c (dump_elf_stabs):  Also dump .stab.index and
+       .stab.excl sections.
+       (dump_elf_stabs_1):  Split out main body of old dump_elf_stabs.
+       * objdump.1, binutils.texi:  Document new sections dumped.
+
+Fri Jun 12 22:23:35 1992  John Gilmore  (gnu at cygnus.com)
+
+       * size.c, objdump.c, bucomm.c:  Lint.
+
+Thu Jun 11 01:19:06 1992  John Gilmore  (gnu at cygnus.com)
+
+       * objdump.c (dump_elf_stabs): New feature: --stabs prints out a
+       .stab section from an ELF file.  Installed under #ifdef
+       ELF_STAB_DISPLAY so it can be easily disabled, since it requires
+       bfd-internals header files and such.
+       * objdump.1, binutils.texi:  Update for --stabs.  Also fix
+       objdump's doc to use -- rather than + for long options.
+       (FIXME:  Not yet fixed everywhere in binutils.texinfo.)
+
+Wed Jun 10 07:53:24 1992  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * objdump.c(display_info), patches from
+       mohring@informatik.tu-muenchen.de to print the table much more
+       nicely.
+
+Thu May 28 13:36:16 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * objdump.c:  Add another enum->int cast, for the sake of
+       old compilers (such as PCC).
+
+Wed May 27 13:01:44 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * arlex.l:  Don't include <sysdep.h> (unneeded conflicts).
+       Add declaration of strdup().
+
+Fri May 22 13:40:37 1992  Per Bothner  (bothner@cygnus.com)
+
+       * Makefile.in:  Use srcdir instead of VPATH in ldgram/ldlex
+       rules, since these are used when building a distribution.
+       * Makefile.in (arlex.c):  Don't re-direct output, since that
+       leaves a bogus output files if it fails.
+
+       * arlex.l:  Make work with lex, for what it's worth.
+       * Makefile.in:  Better lex support.
+       * Makefile.in (dist):  Generate flex and bison outputs
+       for distribution.
+
+Thu May 14 17:17:59 1992  K. Richard Pixley  (rich@rtl.cygnus.com)
+
+       * Makefile.in: get BISON definition right.
+
+Fri May  8 07:47:08 1992  K. Richard Pixley  (rich@cygnus.com)
+
+       * sanity.sh: default TMPDIR to ".".
+
+Thu May  7 12:34:50 1992  Roland H. Pesch  (pesch@fowanton.cygnus.com)
+
+       * binutils.texi: add doc for ar command language.
+
+Wed May  6 18:05:36 1992  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * arparse.y: make END call ar_end
+       * arsup.c (ar_end): added, deletes temp file if archive session
+       aborted.
+
+
+Wed May  6 11:08:53 1992  K. Richard Pixley  (rich@rtl.cygnus.com)
+
+       * Makefile.in: use bison & flex from ../ if they exist.  Also,
+         FLEX->LEX.
+
+       * sanity.sh: remove temporary directory when finished.
+
+Tue May  5 12:00:58 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in:  Bump to version 1.97.
+       * ar.c:  Declare errno for machines that need it.
+
+Mon May  4 23:29:51 1992  John Gilmore  (gnu@cygnus.com)
+
+       * objdump.c (display_info):  Handle error cases without coredump.
+       Close the dummy temporary file we open in the loop.
+       * Makefile.in (arsup.o):  Add kludge to build with Sun Make.
+
+Fri May  1 16:20:23 1992  K. Richard Pixley  (rich@cygnus.com)
+
+       * Makefile.in: added test-install target.
+
+       * sanity.sh: new file.
+
+       * Makefile.in: use sanity test on make check.
+
+Tue Apr 21 13:38:37 1992  K. Richard Pixley  (rich@cygnus.com)
+
+       * Makefile.in: rework CFLAGS so that they can be passed on the
+         command line to make.  Remove MINUS_G.  Default CFLAGS to -g.
+
+Wed Apr 15 14:33:07 1992  Steve Chamberlain  (sac@thepub.cygnus.com)
+
+       * arsup.c, arsup.h, arparse.y, arlex.l: support for archive
+       scripting language.
+
+Fri Mar  6 21:54:53 1992  K. Richard Pixley  (rich@cygnus.com)
+
+       * Makefile.in: added check target.
+
+Thu Mar  5 21:35:49 1992  K. Richard Pixley  (rich@cygnus.com)
+
+       * Makefile.in: added clean-info target.
+
+Tue Mar  3 15:36:37 1992  K. Richard Pixley  (rich@rtl.cygnus.com)
+
+       * Makefile.in: remove $(COPY_PROG) from PROGS.  It shouldn't be
+         installed. added tooldir and program_prefix.
+
+Wed Feb 26 18:04:40 1992  K. Richard Pixley  (rich@cygnus.com)
+
+       * Makefile.in, configure.in: removed traces of namesubdir,
+         -subdirs, $(subdir), $(unsubdir), some rcs triggers.  Forced
+         copyrights to '92, changed some from Cygnus to FSF.
+
+Sun Feb 16 12:53:02 1992  Per Bothner  (bothner at cygnus.com)
+
+       * Makefile.in:  Bump version to 1.96, and remove -beta
+       suffix from distribution name.
+       * m68k-pinsn.c:  New macro COERCE_SIGNED_CHAR to extract
+       the signed value of a character (even if chars are unsigned).
+       * sparc-pinsn.c:  Add new operand types.
+
+Thu Feb  6 12:14:19 1992  Steve Chamberlain  (sac at rtl.cygnus.com)
+
+       * objdump.c (disassemble_data): don't print a section's contents
+       if it's not loadable (eg bss)
+
+Tue Jan 28 11:11:06 1992  Steve Chamberlain  (sac at rtl.cygnus.com)
+
+       * m68k-pinsn.c (print_insn_arg): fixed so that -ve branch
+       displacements don't get printed as large +ve ones.
+
+Fri Jan 24 14:47:53 1992  Steve Chamberlain  (sac at rtl.cygnus.com)
+
+       * copy.c, nm.c, objdump.c, size.c : changed to use the
+       new reloc scheme.
+
+
+Mon Dec 30 18:34:41 1991  Per Bothner  (bothner at cygnus.com)
+
+       * bucomm.c (print_arelt_descr):  Tweek the output format
+       so that 'ar tv' output follows Posix 1003.2/D11.
+       Output is now also identical to Sun's (except __.SYMDEF).
+
+Mon Dec 30 06:09:53 1991  John Gilmore  (gnu at cygnus.com)
+
+       * Makefile.in:  Make `make' output more readable.
+
+Wed Dec 18 15:04:45 1991  Per Bothner  (bothner at cygnus.com)
+
+       * Makefile.in:  Bump to version 1.94.
+
+Wed Dec 11 16:48:09 1991  Steve Chamberlain  (sac at cygnus.com)
+
+       * ar.c: added "b" to fopens for dos
+       * configdj.bat, makefile.dos new files from DJ
+
+Tue Dec 10 04:07:26 1991  K. Richard Pixley  (rich at rtl.cygnus.com)
+
+       * Makefile.in: infodir belongs in datadir.
+
+Sat Dec  7 17:09:37 1991  Steve Chamberlain  (sac at rtl.cygnus.com)
+
+       * bucomm.h: created to hold prototypes of bucomm.c
+       * objdump.h: created to hold prototyes of objdump.c
+       * am29k-pinsn.c: include objdump.h
+       * ar.c: include bucomm.h, get ar.h from the right place and
+       include libbfd.h
+       * bucomm.c: defunize bfd_fatal
+       * copy.c: include bucomm.h, lint.
+       * i960-pinsn.h: include bucomm.h
+       * m68k-pinsn.h: lint
+       * nm.c: include bucomm.h, lint
+       * objdump.c: lint
+       * sparc-pinsn.c: include objdump.h
+
+
+
+Fri Dec  6 23:02:14 1991  K. Richard Pixley  (rich at rtl.cygnus.com)
+
+       * Makefile.in: added standards.text support.  install using
+         INSTALL_PROGRAM and INSTALL_DATA.
+
+       * configure.in: configure now does all of it's work from objdir so
+         make file existence tests against ${srcdir}.
+
+Thu Dec  5 22:46:22 1991  K. Richard Pixley  (rich at rtl.cygnus.com)
+
+       * Makefile.in: idestdir and ddestdir go away.  Added copyrights
+         and shift gpl to v2.  Added ChangeLog if it didn't exist. docdir
+         and mandir now keyed off datadir by default.
+
+Wed Dec  4 22:42:03 1991  Per Bothner  (bothner at cygnus.com)
+
+       * Makefile.in:  Bump to version 1.93.
+       * Makefile.in:  Add make-strip.o:maybe-strip.c dependency
+       for make versions that provide half-baked VPATH-support (e.g. Sun's).
+       * size.c:  Improvements suggested by
+       "david d [zoo] zuhn" <zoo@aps1.spa.umn.edu>:
+       - Don't emit (Berkeley) headers if no files were found.
+       - Return a non-zero return code on failure.
+
+Sat Nov 30 21:34:19 1991  Steve Chamberlain  (sac at rtl.cygnus.com)
+
+       Changes due to include file renaming:
+       * am29k-pinsn.c: a29k-opcode.h  -> opcode/a29k.h
+       * sparc-pinsn.c: sparc-opcode.h -> opcode/sparc.h
+       * m68k-pinsn.c:  m68k-opcode.h  -> opcode/m68k.h
+       * nm.c:          stab.gnu.h     -> aout/stab_gnu.h
+
+Tue Nov 19 19:20:43 1991  Per Bothner  (bothner at cygnus.com)
+
+       * README:  Mention MINIMIZE flag for bfd's make.
+
+Mon Nov 18 12:05:37 1991  Per Bothner  (bothner at cygnus.com)
+
+       * README:  Various improvements.
+
+Sun Nov 17 23:40:59 1991  Per Bothner  (bothner at cygnus.com)
+
+       * Makefile.in:  Bump to version 1.92.
+       * version.c, Makefile.in:  Get version string from Makefile.
+       * copy.c, is-strip.c, not-strip.c, maybe-strip.c, Makefile.in:
+       Make the same change that we earlier did for ar/ranlib:
+       Generate two different binaries for strip and copy and use
+       a global variable with different values to distinguish
+       ostrip from copy.  (-1 means to use argv[0] to decide,
+       so you can get the old behavior, but it is no longer the default).
+       * copy.c (copy_file):  Set EXEC_P of output bfd if input is so.
+       * copy.c (main):  If is_strip==-1, compare last 5 chars
+       of argv[0], not the whole path.
+       * copy.c (main): Return 0, not 1.
+       * copy.c (setup_sections):  Fix due to change in bfd_make_section
+       now failing if asked for a duplicate section.
+       * strip.c, ostrip.c:  Removed obsolete files.
+       * ar.c, not-ranlib.c, maybe-ranlib.c:
+       Change encoding of is_ranlib variable to be consistent
+       with is_strip for strip.copy (i.e -1 to means use argv[0]).
+
+Thu Nov 14 20:11:02 1991  Per Bothner  (bothner at cygnus.com)
+
+       * version.c (program_version): Update to version 1.92.
+
+Tue Nov 12 16:17:53 1991  Per Bothner  (bothner at cygnus.com)
+
+       * ar.c (get_pos_bfd):  Previous fix was missing a "break".
+
+Thu Nov  7 08:55:56 1991  Steve Chamberlain  (sac at cygnus.com)
+
+       * am29k-pinsn.c: Fixed bug in mtacc, dmac and fmac instruction
+       encodings. (Thaks to David Wood)
+
+Sun Nov  3 14:50:23 1991  Per Bothner  (bothner at cygnus.com)
+
+       * Makefile.in ($(DIST_NAME).tar.Z), TODO:  Various fixes.
+       * ar.c (get_pos_bfd): Fix to handling of before/after
+       positioning options.
+       * bucomm.c (fatal):  MISSING_VFPRINTF is no longer an issue,
+       since libiberty contains vfprintf etc if otherwise missing.
+       * m68k-pinsn.c (print_insn_arg):  Support BB/BW/BL
+       type operands, as used by branch instructions.
+       * nm.c:  Delegate printing of symbols to BFD,
+       by using bfd_print_symbol to do the formatting.
+
+Mon Oct 28 11:20:47 1991  Steve Chamberlain  (steve at cygnus.com)
+
+       * ar.c (write_archive.c): added unlink before rename since some
+       systems can't rename onto an existant file.
+
+Mon Oct 21 09:47:23 1991  Steve Chamberlain  (steve at rtl.cygnus.com)
+
+       * nm.c: now doesn't crash if a symbol with no section and no
+       SEC_ABS appears.
+
+Thu Oct 17 15:25:50 1991  Per Bothner  (bothner at cygnus.com)
+
+       * Makefile.in, version.c:  Bump to version 1.91.
+
+Wed Oct 16 11:45:36 1991  Per Bothner  (bothner at cygnus.com)
+
+       * Makefile.in, ar.c, bucomm.c, copy.c, cplus-dem.c, filemode.c,
+       i960-pinsn.c, m68k-pinsn.c, nm.c, objdump.c, size.c, sparc-pinsn.c,
+       * strip.c: Add or update Copyright notice.
+       * TODO:  Add note on 'nm -a'.
+       * version.c: Update version number to 1.90.
+       * Makefile.in: Fix making of documentation for dist.
+
+Tue Oct 15 00:17:17 1991  Per Bothner  (bothner at cygnus.com)
+
+       * README: New file.
+       * Makefile.in: New kludgy rules for making a tarfile.
+       * Makefile.in: Fix bindir path.
+
+Mon Oct 14 17:34:29 1991  Roland H. Pesch  (pesch at cygnus.com)
+
+       * Makefile.in: add targets binutils.mm, binutils.me
+
+Fri Oct 11 22:44:21 1991  John Gilmore  (gnu at cygnus.com)
+
+       * Makefile.in:  Avoid Sun Make VPATH bugs by adding dependencies.
+
+Fri Oct 11 12:51:33 1991  Roland H. Pesch  (pesch at cygnus.com)
+
+       * Makefile.in: add target "binutils.ms"
+
+       * binutils.texinfo: minor restructuring for texi2roff comfort.
+
+Fri Oct 11 04:12:28 1991  John Gilmore  (gnu at cygnus.com)
+
+       Restructure configuration scheme for bfd, binutils, ld.
+
+       * include/sys/h-*.h:  Move to bfd/hosts/h-*.h.
+       * configure.in:  Revise to symlink sysdep.h to ../bfd/hosts/h-xxx.h.
+       Change some config names to match other dirs.
+       * *.c:  Include bfd.h before sysdep.h, so ansidecl and PROTO()
+       get defined first.
+       * Makefile.in:  Use -I. to get sysdep.h.
+
+Wed Oct  9 22:42:56 1991  Per Bothner  (bothner at cygnus.com)
+
+       * nm.c (print_symbols):  Handle NULL name field of symbol.
+       * Makefile.in: Removed spurious comment.
+
+Tue Oct  8 16:55:03 1991  Roland H. Pesch  (pesch at cygnus.com)
+
+       * binutils.texinfo: minor typos, phrasing, formatting fixes.
+
+Tue Oct  8 15:13:20 1991  Per Bothner  (bothner at cygnus.com)
+
+       * configure.in: Get host file from ../bfd/config, not config.
+       * config/*: Remove config directory and its files.
+
+Tue Oct  8 13:58:59 1991  Roland H. Pesch  (pesch at cygnus.com)
+
+       * Makefile.in: new targets binutils.dvi, binutils.info
+
+       * binutils.texinfo: remove most remaining FIXME's, delete
+       references to __.SYMDEF by name
+
+
+Tue Oct  8 10:23:44 1991  Steve Chamberlain  (steve at cygnus.com)
+
+       * objdump.c (print_address) Print addresses nicely.
+
+Mon Oct  7 11:31:05 1991  Per Bothner  (bothner at cygnus.com)
+
+       * ar.c, Makefile.in, new files {is,not,maybe}-ranlib.c:
+       Make two different binaries for ar and ranlib, instead of
+       distinguishing them at run time using argv[0].
+       (Old behavior is still available if you "make ar_with_ranlib",
+       but it is not the default.)
+       * ranlib.sh (new):  An alternative one-line
+       shell implementation of ranlib.
+
+Fri Oct  4 21:49:44 1991  John Gilmore  (gnu at cygnus.com)
+
+       * objdump.c:  Cope with renames of a few BFD types & enums.
+
+Fri Oct  4 19:08:09 1991  Roland H. Pesch  (pesch at cygnus.com)
+
+       * binutils.texinfo: add new file (rudimentary docn)
+
+Mon Sep 30 12:30:39 1991  Per Bothner  (bothner at cygnus.com)
+
+       * config/hmake-news: Add new file (for Sony NEWSOS3).
+       * bucomm.c (fatal):  Conditionally compile fatal() depending on
+       MISSING_VFPRINTF, and don't confuse the issue with NO_VARARGS.
+       * objdump.c (dump_headers):  Trivial output format change.
+       * objdump.c (display_info): Loop over integers, not enums,
+       to appease old compilers.
+
+Mon May 20 16:14:07 1991  Steve Chamberlain  (steve at cygint.cygnus.com)
+
+        *objdump.c *nm.c *copy.c :hanged some types to work with 64 bit object files
+
+Thu May 16 16:06:55 1991  Steve Chamberlain  (steve at cygint.cygnus.com)
+     from bother
+       * objdump.c (print_address): Make disasembled output more
+       consistent with gdb and as: Add 0x when printing hex.
+       Don't print extra leading zeros.
+       Attempt to not print "filename.o".
+       * objdump.c: Add some enum-to-int casts to accomodate old compilers.
+
+
+Fri May  3 22:21:44 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * copy.c:  Change =& constructs to = &, since they confuse older
+       C compilers.
+
+\f
+Local Variables:
+mode: change-log
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/binutils/Makefile.am b/binutils/Makefile.am
new file mode 100644 (file)
index 0000000..4f3014f
--- /dev/null
@@ -0,0 +1,495 @@
+## Process this file with automake to generate Makefile.in
+
+## FIXME: Work around apparent bug in automake.
+INTLLIBS = @INTLLIBS@
+
+AUTOMAKE_OPTIONS = cygnus dejagnu
+
+SUBDIRS = po
+
+tooldir = $(exec_prefix)/$(target_alias)
+
+## These aren't set by automake, because they appear in
+## bfd/acinclude.m4, which is included by binutils/acinclude.m4, and
+## thus is not seen by automake.
+CC_FOR_BUILD = @CC_FOR_BUILD@
+EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@
+
+YACC = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L$(srcdir)/../bison/ ; else echo bison -y ; fi`
+YFLAGS = -d
+LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi`
+
+# these two are almost the same program
+AR_PROG=ar
+RANLIB_PROG=ranlib
+
+# objcopy and strip should be the same program
+OBJCOPY_PROG=objcopy
+STRIP_PROG=strip-new
+
+STRINGS_PROG=strings
+
+READELF_PROG=readelf
+
+# These should all be the same program too.
+SIZE_PROG=size
+NM_PROG=nm-new
+OBJDUMP_PROG=objdump
+
+# This is the demangler, as a standalone program.
+# Note: This one is used as the installed name too, unlike the above.
+DEMANGLER_PROG=c++filt
+
+ADDR2LINE_PROG=addr2line
+
+NLMCONV_PROG=nlmconv
+DLLTOOL_PROG=dlltool
+WINDRES_PROG=windres
+DLLWRAP_PROG=dllwrap
+
+SRCONV_PROG=srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) 
+
+man_MANS = ar.1 nm.1 objdump.1 ranlib.1 size.1 strings.1 strip.1 objcopy.1 \
+       addr2line.1 nlmconv.1 $(DEMANGLER_PROG).1
+
+PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@
+
+bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@
+
+## We need a special rule to install the programs which are built with -new
+noinst_PROGRAMS = $(NM_PROG) $(STRIP_PROG)
+
+EXTRA_PROGRAMS = $(NLMCONV_PROG) srconv sysdump coffdump $(DLLTOOL_PROG) $(WINDRES_PROG) $(DLLWRAP_PROG)
+
+# Stuff that goes in tooldir/ if appropriate
+TOOL_PROGS = nm-new strip-new ar ranlib dlltool
+
+BASEDIR = $(srcdir)/..
+BFDDIR = $(BASEDIR)/bfd
+INCDIR = $(BASEDIR)/include
+
+DEP = mkdep
+
+INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) @HDEFINES@ -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
+
+HFILES = arsup.h bucomm.h budbg.h coffgrok.h debug.h nlmconv.h dlltool.h \
+       windres.h winduni.h dyn-string.h
+
+GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h
+
+CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \
+       dlltool.c filemode.c ieee.c is-ranlib.c is-strip.c maybe-ranlib.c \
+       maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \
+       objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \
+       stabs.c strings.c sysdump.c version.c wrstabs.c \
+       windres.c resrc.c rescoff.c resbin.c winduni.c readelf.c \
+       resres.c dyn-string.c dllwrap.c rename.c
+
+GENERATED_CFILES = \
+       underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
+       defparse.c deflex.c nlmheader.c rcparse.c rclex.c
+
+DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
+WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
+
+# Code shared by all the binutils.
+BULIBS = bucomm.c version.c filemode.c
+
+BFDLIB = ../bfd/libbfd.la
+
+OPCODES = ../opcodes/libopcodes.la
+
+LIBIBERTY = ../libiberty/libiberty.a
+
+POTFILES = $(CFILES) $(DEBUG_SRCS) $(HFILES)
+po/POTFILES.in: @MAINT@ Makefile
+       for file in $(POTFILES); do echo $$file; done | sort > tmp \
+         && mv tmp $(srcdir)/po/POTFILES.in
+
+EXPECT = `if [ -f $$r/../expect/expect ] ; then \
+          echo $$r/../expect/expect ; \
+          else echo expect ; fi`
+RUNTEST = `if [ -f ${srcdir}/../dejagnu/runtest ] ; then \
+           echo ${srcdir}/../dejagnu/runtest ; \
+           else echo runtest ;  fi`
+
+CC_FOR_TARGET = ` \
+  if [ -f $$r/../gcc/xgcc ] ; then \
+    if [ -f $$r/../newlib/Makefile ] ; then \
+      echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \
+    else \
+      echo $$r/../gcc/xgcc -B$$r/../gcc/; \
+    fi; \
+  else \
+    if [ "@host@" = "@target@" ] ; then \
+      echo $(CC); \
+    else \
+      echo gcc | sed '$(transform)'; \
+    fi; \
+  fi`
+
+check-DEJAGNU: site.exp
+       srcdir=`cd $(srcdir) && pwd`; export srcdir; \
+       r=`pwd`; export r; \
+       EXPECT=$(EXPECT); export EXPECT; \
+       if [ -f $(top_builddir)/../expect/expect ]; then \
+         TCL_LIBRARY=`cd $(top_srcdir)/../tcl/library && pwd`; \
+         export TCL_LIBRARY; \
+       fi; \
+       runtest=$(RUNTEST); \
+       if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+         $$runtest --tool $(DEJATOOL) --srcdir $${srcdir}/testsuite \
+               CC_FOR_TARGET="$(CC_FOR_TARGET)" \
+               CFLAGS_FOR_TARGET="$(CFLAGS)" $(RUNTESTFLAGS); \
+       else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+       fi
+
+installcheck:
+       /bin/sh $(srcdir)/sanity.sh $(bindir)
+
+info_TEXINFOS = binutils.texi
+
+LDADD = $(BFDLIB) $(LIBIBERTY) $(INTLLIBS)
+
+size_SOURCES = size.c $(BULIBS)
+
+objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
+
+strings_SOURCES = strings.c $(BULIBS)
+
+readelf_SOURCES = readelf.c version.c
+readelf_LDADD   = $(INTLLIBS) $(LIBIBERTY)
+
+strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
+
+nm_new_SOURCES = nm.c $(BULIBS)
+
+objdump_SOURCES = objdump.c prdbg.c $(DEBUG_SRCS) $(BULIBS)
+objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(INTLLIBS)
+
+underscore.c: stamp-under ; @true
+
+stamp-under: Makefile
+       echo '/*WARNING: This file is automatically generated!*/' >underscore.t
+       echo "int prepends_underscore = @UNDERSCORE@;" >>underscore.t
+       $(SHELL) $(srcdir)/../move-if-change underscore.t underscore.c
+       touch stamp-under
+
+cplus-dem.o: $(BASEDIR)/libiberty/cplus-dem.c $(INCDIR)/getopt.h
+       $(COMPILE) -c -DMAIN -DVERSION='"$(VERSION)"' $(BASEDIR)/libiberty/cplus-dem.c
+
+c__filt_SOURCES =
+c__filt_LDADD = cplus-dem.o underscore.o $(LIBIBERTY) $(INTLLIBS)
+
+ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c $(BULIBS)
+ar_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
+
+ranlib_SOURCES = ar.c is-ranlib.c arparse.y arlex.l arsup.c rename.c $(BULIBS)
+ranlib_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
+
+addr2line_SOURCES = addr2line.c $(BULIBS)
+
+# The following is commented out for the convertion to automake.
+# This rule creates a single binary that switches between ar and ranlib
+# by looking at argv[0].  Use this kludge to save some disk space.
+# However, you have to install things by hand.
+# (That is after 'make install', replace the installed ranlib by a link to ar.)
+# Alternatively, you can install ranlib.sh as ranlib.
+# ar_with_ranlib: $(ADDL_DEPS) ar.o maybe-ranlib.o
+#      $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(AR_PROG) ar.o maybe-ranlib.o $(ADDL_LIBS) $(EXTRALIBS)
+#      -rm -f $(RANLIB_PROG)
+#      -ln $(AR_PROG) $(RANLIB_PROG)
+#
+# objcopy and strip in one binary that uses argv[0] to decide its action.
+#
+#objcopy_with_strip: $(ADDL_DEPS) objcopy.o maybe-strip.o
+#      $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o maybe-strip.o $(ADDL_LIBS) $(EXTRALIBS)
+#      -rm -f $(STRIP_PROG)
+#      -ln $(OBJCOPY_PROG) $(STRIP_PROG)
+
+sysroff.c: sysinfo$(EXEEXT_FOR_BUILD) sysroff.info 
+       ./sysinfo$(EXEEXT_FOR_BUILD) -c <$(srcdir)/sysroff.info >sysroff.c
+       ./sysinfo$(EXEEXT_FOR_BUILD) -i <$(srcdir)/sysroff.info >>sysroff.c
+       ./sysinfo$(EXEEXT_FOR_BUILD) -g <$(srcdir)/sysroff.info >>sysroff.c
+
+sysroff.h: sysinfo$(EXEEXT_FOR_BUILD) sysroff.info
+       ./sysinfo$(EXEEXT_FOR_BUILD) -d <$(srcdir)/sysroff.info >sysroff.h
+
+sysinfo$(EXEEXT_FOR_BUILD): sysinfo.o syslex.o
+       $(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o $@ sysinfo.o syslex.o 
+
+syslex.o: syslex.c sysinfo.h
+       if [ -r syslex.c ]; then \
+         $(CC_FOR_BUILD) -c -I. $(CFLAGS)  syslex.c  ; \
+       else \
+         $(CC_FOR_BUILD) -c -I. -I$(srcdir) $(CFLAGS) $(srcdir)/syslex.c ;\
+       fi
+
+sysinfo.o: sysinfo.c
+       if [ -r sysinfo.c ]; then \
+         $(CC_FOR_BUILD) -c -I. $(CFLAGS)  sysinfo.c  ; \
+       else \
+         $(CC_FOR_BUILD) -c -I. $(CFLAGS) $(srcdir)/sysinfo.c ; \
+       fi
+
+srconv_SOURCES = srconv.c coffgrok.c $(BULIBS)
+
+dlltool_SOURCES = dlltool.c defparse.y deflex.l $(BULIBS)
+dlltool_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
+
+dlltool.o:dlltool.c
+       $(COMPILE) -c $(DLLTOOL_DEFS) $(srcdir)/dlltool.c
+
+coffdump_SOURCES = coffdump.c coffgrok.c $(BULIBS)
+
+sysdump_SOURCES = sysdump.c $(BULIBS)
+
+# coff/sym.h and coff/ecoff.h won't be found by the automatic dependency
+# scripts, since they are only included conditionally.
+nlmconv.o: nlmconv.c $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+       ldname=`echo ld | sed '$(transform)'`; \
+       $(COMPILE) -c -DLD_NAME="\"$${ldname}\"" @NLMCONV_DEFS@ $(srcdir)/nlmconv.c
+
+nlmconv_SOURCES = nlmconv.c nlmheader.y $(BULIBS)
+
+windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.l \
+       winduni.c resres.c $(BULIBS)
+windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
+
+dllwrap_SOURCES = dllwrap.c dyn-string.c 
+dllwrap_LDADD = $(LIBIBERTY)
+
+
+DISTSTUFF = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \
+       syslex.c deflex.c defparse.h defparse.c rclex.c rcparse.h rcparse.c
+
+diststuff: $(DISTSTUFF) info
+
+DISTCLEANFILES = stamp-under sysinfo underscore.c sysroff.c sysroff.h \
+       site.exp site.bak
+
+# Targets to rebuild dependencies in this Makefile.
+# Have to get rid of .dep1 here so that "$?" later includes all of $(CFILES).
+.dep: dep.sed $(CFILES) $(HFILES) $(GENERATED_CFILES) $(GENERATED_HFILES) config.h
+       rm -f .dep1
+       $(MAKE) DEP=$(DEP) .dep1
+       sed -f dep.sed <.dep1 >.dep
+
+# This rule really wants a mkdep that runs "gcc -MM".
+.dep1: $(CFILES) $(GENERATED_CFILES)
+       rm -f .dep2
+       echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep2
+       $(DEP) -f .dep2 $(INCLUDES) $?
+       $(SHELL) $(srcdir)/../move-if-change .dep2 .dep1
+
+dep.sed: dep-in.sed config.status
+       objdir=`pwd`; \
+       sed <$(srcdir)/dep-in.sed >dep.sed      \
+               -e 's!@INCDIR@!$(INCDIR)!'      \
+               -e 's!@BFDDIR@!$(BFDDIR)!'      \
+               -e 's!@SRCDIR@!$(srcdir)!'      \
+               -e "s!@OBJDIR@!$${objdir}!"
+
+dep: .dep
+       sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile
+       cat .dep >> tmp-Makefile
+       $(SHELL) $(srcdir)/../move-if-change tmp-Makefile Makefile
+
+dep-in: .dep
+       sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in
+       cat .dep >> tmp-Makefile.in
+       $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in
+
+dep-am: .dep
+       sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.am > tmp-Makefile.am
+       cat .dep >> tmp-Makefile.am
+       $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.am $(srcdir)/Makefile.am
+
+.PHONY: dep dep-in dep-am
+
+###
+# DOCUMENTATION TARGETS
+config.texi: Makefile
+       rm -f config.texi
+       echo '@set VERSION $(VERSION)' > config.texi
+
+binutils.dvi: $(srcdir)/binutils.texi config.texi
+
+binutils.info: $(srcdir)/binutils.texi config.texi
+
+MAINTAINERCLEANFILES = config.texi
+
+$(DEMANGLER_PROG).1: cxxfilt.man Makefile
+       sed -e 's/@PROGRAM@/$(DEMANGLER_PROG)/' < $(srcdir)/cxxfilt.man \
+               > $(DEMANGLER_PROG).1
+
+MOSTLYCLEANFILES = sysinfo $(DEMANGLER_PROG).1 binutils.log binutils.sum \
+       abcdefgh*
+mostlyclean-local:
+       -rm -rf tmpdir
+
+CLEANFILES = dep.sed .dep .dep1
+
+.PHONY: install-exec-local
+
+install-exec-local: $(bin_PROGRAMS) $(noinst_PROGRAMS)
+       @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+           $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+         else :; fi; \
+       done
+       $(mkinstalldirs) $(tooldir)/bin
+       for i in $(TOOL_PROGS); do \
+         if [ -f $$i$(EXEEXT) ]; then \
+           j=`echo $$i | sed -e 's/-new//'`; \
+           k=`echo $$j | sed '$(transform)'`; \
+           if [ "$(bindir)/$$k$(EXEEXT)" != "$(tooldir)/bin/$$j$(EXEEXT)" ]; then \
+             rm -f $(tooldir)/bin/$$j$(EXEEXT); \
+             ln $(bindir)/$$k$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT) >/dev/null 2>/dev/null \
+               || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$i$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT); \
+           fi; \
+         else true; \
+         fi; \
+       done
+
+# What appears below is generated by a hacked mkdep using gcc -MM.
+
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+addr2line.o: addr2line.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/getopt.h $(INCDIR)/libiberty.h $(INCDIR)/demangle.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h
+ar.o: ar.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
+  $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/aout/ar.h $(BFDDIR)/libbfd.h arsup.h
+arsup.o: arsup.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  arsup.h $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h
+bucomm.o: bucomm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h
+coffdump.o: coffdump.c coffgrok.h bucomm.h config.h \
+  $(INCDIR)/fopen-same.h
+coffgrok.o: coffgrok.c bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+  coffgrok.h
+debug.o: debug.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h
+dlltool.o: dlltool.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/getopt.h $(INCDIR)/demangle.h dlltool.h
+filemode.o: filemode.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h
+ieee.o: ieee.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/ieee.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h budbg.h
+is-ranlib.o: is-ranlib.c
+is-strip.o: is-strip.c
+maybe-ranlib.o: maybe-ranlib.c
+maybe-strip.o: maybe-strip.c
+nlmconv.o: nlmconv.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(BFDDIR)/libnlm.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \
+  $(INCDIR)/nlm/external.h nlmconv.h
+nm.o: nm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/progress.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h \
+  $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ranlib.h \
+  $(INCDIR)/demangle.h $(INCDIR)/libiberty.h
+not-ranlib.o: not-ranlib.c
+not-strip.o: not-strip.c
+objcopy.o: objcopy.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/getopt.h $(INCDIR)/libiberty.h budbg.h
+objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/getopt.h $(INCDIR)/progress.h bucomm.h config.h \
+  $(INCDIR)/fopen-same.h $(INCDIR)/dis-asm.h $(INCDIR)/libiberty.h \
+  $(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h
+prdbg.o: prdbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h budbg.h
+rdcoff.o: rdcoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/coff/internal.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/libiberty.h $(INCDIR)/demangle.h debug.h \
+  budbg.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+rddbg.o: rddbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h budbg.h
+size.o: size.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/getopt.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h
+srconv.o: srconv.c bucomm.h config.h $(INCDIR)/fopen-same.h \
+  sysroff.h coffgrok.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \
+  $(INCDIR)/bfdlink.h sysroff.c
+stabs.o: stabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  $(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h \
+  $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
+strings.o: strings.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h
+sysdump.o: sysdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h sysroff.h \
+  sysroff.c
+version.o: version.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h
+wrstabs.o: wrstabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h budbg.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+  $(INCDIR)/aout/stab.def
+windres.o: windres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/getopt.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/libiberty.h $(INCDIR)/obstack.h windres.h \
+  winduni.h
+resrc.o: resrc.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h
+rescoff.o: rescoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \
+  $(INCDIR)/bfdlink.h
+resbin.o: resbin.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h
+winduni.o: winduni.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h winduni.h
+readelf.o: readelf.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/dwarf2.h $(INCDIR)/elf/i386.h $(INCDIR)/elf/reloc-macros.h \
+  $(INCDIR)/elf/v850.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/mips.h \
+  $(INCDIR)/elf/alpha.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/m68k.h \
+  $(INCDIR)/elf/sparc.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/d10v.h \
+  $(INCDIR)/elf/d30v.h $(INCDIR)/elf/sh.h $(INCDIR)/elf/mn10200.h \
+  $(INCDIR)/elf/mn10300.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/arc.h \
+  $(INCDIR)/elf/fr30.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/getopt.h
+resres.o: resres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h
+dyn-string.o: dyn-string.c config.h $(INCDIR)/ansidecl.h \
+  dyn-string.h
+dllwrap.o: dllwrap.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/getopt.h dyn-string.h
+rename.o: rename.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h
+underscore.o: underscore.c
+arparse.o: arparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h arsup.h
+arlex.o: arlex.c $(INCDIR)/libiberty.h arparse.h
+sysroff.o: sysroff.c
+sysinfo.o: sysinfo.c
+syslex.o: syslex.c sysinfo.h
+defparse.o: defparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h dlltool.h
+deflex.o: deflex.c $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
+  defparse.h dlltool.h
+nlmheader.o: nlmheader.c ../bfd/bfd.h bucomm.h config.h \
+  $(INCDIR)/fopen-same.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \
+  nlmconv.h
+rcparse.o: rcparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h
+rclex.o: rclex.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h rcparse.h
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/binutils/Makefile.in b/binutils/Makefile.in
new file mode 100644 (file)
index 0000000..c32ae4d
--- /dev/null
@@ -0,0 +1,1358 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AR = @AR@
+AS = @AS@
+BUILD_DLLTOOL = @BUILD_DLLTOOL@
+BUILD_DLLWRAP = @BUILD_DLLWRAP@
+BUILD_MISC = @BUILD_MISC@
+BUILD_NLMCONV = @BUILD_NLMCONV@
+BUILD_SRCONV = @BUILD_SRCONV@
+BUILD_WINDRES = @BUILD_WINDRES@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+DATADIRNAME = @DATADIRNAME@
+DLLTOOL = @DLLTOOL@
+DLLTOOL_DEFS = @DLLTOOL_DEFS@
+EXEEXT = @EXEEXT@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GT_NO = @GT_NO@
+GT_YES = @GT_YES@
+HDEFINES = @HDEFINES@
+INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
+INSTOBJEXT = @INSTOBJEXT@
+INTLDEPS = @INTLDEPS@
+INTLOBJS = @INTLOBJS@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+NLMCONV_DEFS = @NLMCONV_DEFS@
+NM = @NM@
+PACKAGE = @PACKAGE@
+POFILES = @POFILES@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+UNDERSCORE = @UNDERSCORE@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+USE_SYMBOL_UNDERSCORE = @USE_SYMBOL_UNDERSCORE@
+VERSION = @VERSION@
+l = @l@
+
+INTLLIBS = @INTLLIBS@
+
+AUTOMAKE_OPTIONS = cygnus dejagnu
+
+SUBDIRS = po
+
+tooldir = $(exec_prefix)/$(target_alias)
+
+CC_FOR_BUILD = @CC_FOR_BUILD@
+EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@
+
+YACC = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L$(srcdir)/../bison/ ; else echo bison -y ; fi`
+YFLAGS = -d
+LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi`
+
+# these two are almost the same program
+AR_PROG = ar
+RANLIB_PROG = ranlib
+
+# objcopy and strip should be the same program
+OBJCOPY_PROG = objcopy
+STRIP_PROG = strip-new
+
+STRINGS_PROG = strings
+
+READELF_PROG = readelf
+
+# These should all be the same program too.
+SIZE_PROG = size
+NM_PROG = nm-new
+OBJDUMP_PROG = objdump
+
+# This is the demangler, as a standalone program.
+# Note: This one is used as the installed name too, unlike the above.
+DEMANGLER_PROG = c++filt
+
+ADDR2LINE_PROG = addr2line
+
+NLMCONV_PROG = nlmconv
+DLLTOOL_PROG = dlltool
+WINDRES_PROG = windres
+DLLWRAP_PROG = dllwrap
+
+SRCONV_PROG = srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) 
+
+man_MANS = ar.1 nm.1 objdump.1 ranlib.1 size.1 strings.1 strip.1 objcopy.1 \
+       addr2line.1 nlmconv.1 $(DEMANGLER_PROG).1
+
+
+PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@
+
+bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@
+
+noinst_PROGRAMS = $(NM_PROG) $(STRIP_PROG)
+
+EXTRA_PROGRAMS = $(NLMCONV_PROG) srconv sysdump coffdump $(DLLTOOL_PROG) $(WINDRES_PROG) $(DLLWRAP_PROG)
+
+# Stuff that goes in tooldir/ if appropriate
+TOOL_PROGS = nm-new strip-new ar ranlib dlltool
+
+BASEDIR = $(srcdir)/..
+BFDDIR = $(BASEDIR)/bfd
+INCDIR = $(BASEDIR)/include
+
+DEP = mkdep
+
+INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) @HDEFINES@ -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
+
+HFILES = arsup.h bucomm.h budbg.h coffgrok.h debug.h nlmconv.h dlltool.h \
+       windres.h winduni.h dyn-string.h
+
+
+GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h
+
+CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \
+       dlltool.c filemode.c ieee.c is-ranlib.c is-strip.c maybe-ranlib.c \
+       maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \
+       objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \
+       stabs.c strings.c sysdump.c version.c wrstabs.c \
+       windres.c resrc.c rescoff.c resbin.c winduni.c readelf.c \
+       resres.c dyn-string.c dllwrap.c rename.c
+
+
+GENERATED_CFILES = \
+       underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \
+       defparse.c deflex.c nlmheader.c rcparse.c rclex.c
+
+
+DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
+WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
+
+# Code shared by all the binutils.
+BULIBS = bucomm.c version.c filemode.c
+
+BFDLIB = ../bfd/libbfd.la
+
+OPCODES = ../opcodes/libopcodes.la
+
+LIBIBERTY = ../libiberty/libiberty.a
+
+POTFILES = $(CFILES) $(DEBUG_SRCS) $(HFILES)
+
+EXPECT = `if [ -f $$r/../expect/expect ] ; then \
+          echo $$r/../expect/expect ; \
+          else echo expect ; fi`
+
+RUNTEST = `if [ -f ${srcdir}/../dejagnu/runtest ] ; then \
+           echo ${srcdir}/../dejagnu/runtest ; \
+           else echo runtest ;  fi`
+
+
+CC_FOR_TARGET = ` \
+  if [ -f $$r/../gcc/xgcc ] ; then \
+    if [ -f $$r/../newlib/Makefile ] ; then \
+      echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \
+    else \
+      echo $$r/../gcc/xgcc -B$$r/../gcc/; \
+    fi; \
+  else \
+    if [ "@host@" = "@target@" ] ; then \
+      echo $(CC); \
+    else \
+      echo gcc | sed '$(transform)'; \
+    fi; \
+  fi`
+
+
+info_TEXINFOS = binutils.texi
+
+LDADD = $(BFDLIB) $(LIBIBERTY) $(INTLLIBS)
+
+size_SOURCES = size.c $(BULIBS)
+
+objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
+
+strings_SOURCES = strings.c $(BULIBS)
+
+readelf_SOURCES = readelf.c version.c
+readelf_LDADD = $(INTLLIBS) $(LIBIBERTY)
+
+strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
+
+nm_new_SOURCES = nm.c $(BULIBS)
+
+objdump_SOURCES = objdump.c prdbg.c $(DEBUG_SRCS) $(BULIBS)
+objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(INTLLIBS)
+
+c__filt_SOURCES = 
+c__filt_LDADD = cplus-dem.o underscore.o $(LIBIBERTY) $(INTLLIBS)
+
+ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c $(BULIBS)
+ar_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
+
+ranlib_SOURCES = ar.c is-ranlib.c arparse.y arlex.l arsup.c rename.c $(BULIBS)
+ranlib_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
+
+addr2line_SOURCES = addr2line.c $(BULIBS)
+
+srconv_SOURCES = srconv.c coffgrok.c $(BULIBS)
+
+dlltool_SOURCES = dlltool.c defparse.y deflex.l $(BULIBS)
+dlltool_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
+
+coffdump_SOURCES = coffdump.c coffgrok.c $(BULIBS)
+
+sysdump_SOURCES = sysdump.c $(BULIBS)
+
+nlmconv_SOURCES = nlmconv.c nlmheader.y $(BULIBS)
+
+windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.l \
+       winduni.c resres.c $(BULIBS)
+
+windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS)
+
+dllwrap_SOURCES = dllwrap.c dyn-string.c 
+dllwrap_LDADD = $(LIBIBERTY)
+
+DISTSTUFF = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \
+       syslex.c deflex.c defparse.h defparse.c rclex.c rcparse.h rcparse.c
+
+
+DISTCLEANFILES = stamp-under sysinfo underscore.c sysroff.c sysroff.h \
+       site.exp site.bak
+
+
+MAINTAINERCLEANFILES = config.texi
+
+MOSTLYCLEANFILES = sysinfo $(DEMANGLER_PROG).1 binutils.log binutils.sum \
+       abcdefgh*
+
+
+CLEANFILES = dep.sed .dep .dep1
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = 
+bin_PROGRAMS =  size$(EXEEXT) objdump$(EXEEXT) ar$(EXEEXT) \
+strings$(EXEEXT) ranlib$(EXEEXT) c++filt$(EXEEXT) objcopy$(EXEEXT) \
+@BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ \
+addr2line$(EXEEXT) readelf$(EXEEXT) @BUILD_DLLWRAP@ @BUILD_MISC@
+noinst_PROGRAMS =  nm-new$(EXEEXT) strip-new$(EXEEXT)
+PROGRAMS =  $(bin_PROGRAMS) $(noinst_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I.
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+nlmconv_OBJECTS =  nlmconv.o nlmheader.o bucomm.o version.o filemode.o
+nlmconv_LDADD = $(LDADD)
+nlmconv_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+nlmconv_LDFLAGS = 
+srconv_OBJECTS =  srconv.o coffgrok.o bucomm.o version.o filemode.o
+srconv_LDADD = $(LDADD)
+srconv_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+srconv_LDFLAGS = 
+sysdump_OBJECTS =  sysdump.o bucomm.o version.o filemode.o
+sysdump_LDADD = $(LDADD)
+sysdump_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+sysdump_LDFLAGS = 
+coffdump_OBJECTS =  coffdump.o coffgrok.o bucomm.o version.o filemode.o
+coffdump_LDADD = $(LDADD)
+coffdump_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+coffdump_LDFLAGS = 
+dlltool_OBJECTS =  dlltool.o defparse.o deflex.o bucomm.o version.o \
+filemode.o
+dlltool_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+dlltool_LDFLAGS = 
+windres_OBJECTS =  windres.o resrc.o rescoff.o resbin.o rcparse.o \
+rclex.o winduni.o resres.o bucomm.o version.o filemode.o
+windres_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+windres_LDFLAGS = 
+dllwrap_OBJECTS =  dllwrap.o dyn-string.o
+dllwrap_DEPENDENCIES =  ../libiberty/libiberty.a
+dllwrap_LDFLAGS = 
+size_OBJECTS =  size.o bucomm.o version.o filemode.o
+size_LDADD = $(LDADD)
+size_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+size_LDFLAGS = 
+objdump_OBJECTS =  objdump.o prdbg.o rddbg.o debug.o stabs.o ieee.o \
+rdcoff.o bucomm.o version.o filemode.o
+objdump_DEPENDENCIES =  ../opcodes/libopcodes.la ../bfd/libbfd.la \
+../libiberty/libiberty.a
+objdump_LDFLAGS = 
+ar_OBJECTS =  arparse.o arlex.o ar.o not-ranlib.o arsup.o rename.o \
+bucomm.o version.o filemode.o
+ar_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+ar_LDFLAGS = 
+strings_OBJECTS =  strings.o bucomm.o version.o filemode.o
+strings_LDADD = $(LDADD)
+strings_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+strings_LDFLAGS = 
+ranlib_OBJECTS =  ar.o is-ranlib.o arparse.o arlex.o arsup.o rename.o \
+bucomm.o version.o filemode.o
+ranlib_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+ranlib_LDFLAGS = 
+c__filt_OBJECTS = 
+c__filt_DEPENDENCIES =  cplus-dem.o underscore.o \
+../libiberty/libiberty.a
+c__filt_LDFLAGS = 
+objcopy_OBJECTS =  objcopy.o not-strip.o rename.o rddbg.o debug.o \
+stabs.o ieee.o rdcoff.o wrstabs.o bucomm.o version.o filemode.o
+objcopy_LDADD = $(LDADD)
+objcopy_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+objcopy_LDFLAGS = 
+addr2line_OBJECTS =  addr2line.o bucomm.o version.o filemode.o
+addr2line_LDADD = $(LDADD)
+addr2line_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+addr2line_LDFLAGS = 
+readelf_OBJECTS =  readelf.o version.o
+readelf_DEPENDENCIES =  ../libiberty/libiberty.a
+readelf_LDFLAGS = 
+nm_new_OBJECTS =  nm.o bucomm.o version.o filemode.o
+nm_new_LDADD = $(LDADD)
+nm_new_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+nm_new_LDFLAGS = 
+strip_new_OBJECTS =  objcopy.o is-strip.o rename.o rddbg.o debug.o \
+stabs.o ieee.o rdcoff.o wrstabs.o bucomm.o version.o filemode.o
+strip_new_LDADD = $(LDADD)
+strip_new_DEPENDENCIES =  ../bfd/libbfd.la ../libiberty/libiberty.a
+strip_new_LDFLAGS = 
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LEXLIB = @LEXLIB@
+YLWRAP = $(top_srcdir)/../ylwrap
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+TEXI2DVI = `if test -f $(top_srcdir)/../texinfo/util/texi2dvi; then echo $(top_srcdir)/../texinfo/util/texi2dvi; else echo texi2dvi; fi`
+TEXINFO_TEX = $(top_srcdir)/../texinfo/texinfo.tex
+INFO_DEPS = binutils.info
+DVIS = binutils.dvi
+TEXINFOS = binutils.texi
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON =  README ./stamp-h.in ChangeLog Makefile.am Makefile.in \
+NEWS acinclude.m4 aclocal.m4 arlex.c arparse.c config.in configure \
+configure.in deflex.c defparse.c nlmheader.c rclex.c rcparse.c
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(nlmconv_SOURCES) $(srconv_SOURCES) $(sysdump_SOURCES) $(coffdump_SOURCES) $(dlltool_SOURCES) $(windres_SOURCES) $(dllwrap_SOURCES) $(size_SOURCES) $(objdump_SOURCES) $(ar_SOURCES) $(strings_SOURCES) $(ranlib_SOURCES) $(c__filt_SOURCES) $(objcopy_SOURCES) $(addr2line_SOURCES) $(readelf_SOURCES) $(nm_new_SOURCES) $(strip_new_SOURCES)
+OBJECTS = $(nlmconv_OBJECTS) $(srconv_OBJECTS) $(sysdump_OBJECTS) $(coffdump_OBJECTS) $(dlltool_OBJECTS) $(windres_OBJECTS) $(dllwrap_OBJECTS) $(size_OBJECTS) $(objdump_OBJECTS) $(ar_OBJECTS) $(strings_OBJECTS) $(ranlib_OBJECTS) $(c__filt_OBJECTS) $(objcopy_OBJECTS) $(addr2line_OBJECTS) $(readelf_OBJECTS) $(nm_new_OBJECTS) $(strip_new_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .dvi .info .l .lo .o .ps .s .texi .texinfo .txi .y
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in  acinclude.m4
+       cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+       cd $(srcdir) && $(AUTOCONF)
+
+config.h: stamp-h
+       @if test ! -f $@; then \
+               rm -f stamp-h; \
+               $(MAKE) stamp-h; \
+       else :; fi
+stamp-h: $(srcdir)/config.in $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES= CONFIG_HEADERS=config.h:config.in \
+            $(SHELL) ./config.status
+       @echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/config.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in
+       @if test ! -f $@; then \
+               rm -f $(srcdir)/stamp-h.in; \
+               $(MAKE) $(srcdir)/stamp-h.in; \
+       else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOHEADER)
+       @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+       -rm -f config.h
+
+maintainer-clean-hdr:
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+       -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(bindir)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+           $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       list='$(bin_PROGRAMS)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+       done
+
+mostlyclean-noinstPROGRAMS:
+
+clean-noinstPROGRAMS:
+       -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+
+distclean-noinstPROGRAMS:
+
+maintainer-clean-noinstPROGRAMS:
+
+.c.o:
+       $(COMPILE) -c $<
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+nlmconv$(EXEEXT): $(nlmconv_OBJECTS) $(nlmconv_DEPENDENCIES)
+       @rm -f nlmconv$(EXEEXT)
+       $(LINK) $(nlmconv_LDFLAGS) $(nlmconv_OBJECTS) $(nlmconv_LDADD) $(LIBS)
+
+srconv$(EXEEXT): $(srconv_OBJECTS) $(srconv_DEPENDENCIES)
+       @rm -f srconv$(EXEEXT)
+       $(LINK) $(srconv_LDFLAGS) $(srconv_OBJECTS) $(srconv_LDADD) $(LIBS)
+
+sysdump$(EXEEXT): $(sysdump_OBJECTS) $(sysdump_DEPENDENCIES)
+       @rm -f sysdump$(EXEEXT)
+       $(LINK) $(sysdump_LDFLAGS) $(sysdump_OBJECTS) $(sysdump_LDADD) $(LIBS)
+
+coffdump$(EXEEXT): $(coffdump_OBJECTS) $(coffdump_DEPENDENCIES)
+       @rm -f coffdump$(EXEEXT)
+       $(LINK) $(coffdump_LDFLAGS) $(coffdump_OBJECTS) $(coffdump_LDADD) $(LIBS)
+
+dlltool$(EXEEXT): $(dlltool_OBJECTS) $(dlltool_DEPENDENCIES)
+       @rm -f dlltool$(EXEEXT)
+       $(LINK) $(dlltool_LDFLAGS) $(dlltool_OBJECTS) $(dlltool_LDADD) $(LIBS)
+
+windres$(EXEEXT): $(windres_OBJECTS) $(windres_DEPENDENCIES)
+       @rm -f windres$(EXEEXT)
+       $(LINK) $(windres_LDFLAGS) $(windres_OBJECTS) $(windres_LDADD) $(LIBS)
+
+dllwrap$(EXEEXT): $(dllwrap_OBJECTS) $(dllwrap_DEPENDENCIES)
+       @rm -f dllwrap$(EXEEXT)
+       $(LINK) $(dllwrap_LDFLAGS) $(dllwrap_OBJECTS) $(dllwrap_LDADD) $(LIBS)
+
+size$(EXEEXT): $(size_OBJECTS) $(size_DEPENDENCIES)
+       @rm -f size$(EXEEXT)
+       $(LINK) $(size_LDFLAGS) $(size_OBJECTS) $(size_LDADD) $(LIBS)
+
+objdump$(EXEEXT): $(objdump_OBJECTS) $(objdump_DEPENDENCIES)
+       @rm -f objdump$(EXEEXT)
+       $(LINK) $(objdump_LDFLAGS) $(objdump_OBJECTS) $(objdump_LDADD) $(LIBS)
+
+ar$(EXEEXT): $(ar_OBJECTS) $(ar_DEPENDENCIES)
+       @rm -f ar$(EXEEXT)
+       $(LINK) $(ar_LDFLAGS) $(ar_OBJECTS) $(ar_LDADD) $(LIBS)
+
+strings$(EXEEXT): $(strings_OBJECTS) $(strings_DEPENDENCIES)
+       @rm -f strings$(EXEEXT)
+       $(LINK) $(strings_LDFLAGS) $(strings_OBJECTS) $(strings_LDADD) $(LIBS)
+
+ranlib$(EXEEXT): $(ranlib_OBJECTS) $(ranlib_DEPENDENCIES)
+       @rm -f ranlib$(EXEEXT)
+       $(LINK) $(ranlib_LDFLAGS) $(ranlib_OBJECTS) $(ranlib_LDADD) $(LIBS)
+
+c++filt$(EXEEXT): $(c__filt_OBJECTS) $(c__filt_DEPENDENCIES)
+       @rm -f c++filt$(EXEEXT)
+       $(LINK) $(c__filt_LDFLAGS) $(c__filt_OBJECTS) $(c__filt_LDADD) $(LIBS)
+
+objcopy$(EXEEXT): $(objcopy_OBJECTS) $(objcopy_DEPENDENCIES)
+       @rm -f objcopy$(EXEEXT)
+       $(LINK) $(objcopy_LDFLAGS) $(objcopy_OBJECTS) $(objcopy_LDADD) $(LIBS)
+
+addr2line$(EXEEXT): $(addr2line_OBJECTS) $(addr2line_DEPENDENCIES)
+       @rm -f addr2line$(EXEEXT)
+       $(LINK) $(addr2line_LDFLAGS) $(addr2line_OBJECTS) $(addr2line_LDADD) $(LIBS)
+
+readelf$(EXEEXT): $(readelf_OBJECTS) $(readelf_DEPENDENCIES)
+       @rm -f readelf$(EXEEXT)
+       $(LINK) $(readelf_LDFLAGS) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS)
+
+nm-new$(EXEEXT): $(nm_new_OBJECTS) $(nm_new_DEPENDENCIES)
+       @rm -f nm-new$(EXEEXT)
+       $(LINK) $(nm_new_LDFLAGS) $(nm_new_OBJECTS) $(nm_new_LDADD) $(LIBS)
+
+strip-new$(EXEEXT): $(strip_new_OBJECTS) $(strip_new_DEPENDENCIES)
+       @rm -f strip-new$(EXEEXT)
+       $(LINK) $(strip_new_LDFLAGS) $(strip_new_OBJECTS) $(strip_new_LDADD) $(LIBS)
+.l.c:
+       $(SHELL) $(YLWRAP) "$(LEX)" $< $(LEX_OUTPUT_ROOT).c $@ -- $(AM_LFLAGS) $(LFLAGS)
+.y.c:
+       $(SHELL) $(YLWRAP) "$(YACC)" $< y.tab.c $*.c y.tab.h $*.h -- $(AM_YFLAGS) $(YFLAGS)
+arparse.h: arparse.c
+defparse.h: defparse.c
+nlmheader.h: nlmheader.c
+rcparse.h: rcparse.c
+
+
+binutils.info: binutils.texi
+binutils.dvi: binutils.texi
+
+
+DVIPS = dvips
+
+.texi.info:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.texi.dvi:
+       TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.texi:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo.info:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo.dvi:
+       TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.txi.info:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.txi.dvi:
+       TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.txi:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+.dvi.ps:
+       $(DVIPS) $< -o $@
+
+install-info-am: $(INFO_DEPS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(infodir)
+       @list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \
+           if test -f $$d/$$ifile; then \
+             echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \
+             $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \
+           else : ; fi; \
+         done; \
+       done
+       @$(POST_INSTALL)
+       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+         list='$(INFO_DEPS)'; \
+         for file in $$list; do \
+           echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\
+           install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\
+         done; \
+       else : ; fi
+
+uninstall-info:
+       $(PRE_UNINSTALL)
+       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+         ii=yes; \
+       else ii=; fi; \
+       list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         test -z "$ii" \
+           || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file; \
+       done
+       @$(NORMAL_UNINSTALL)
+       list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \
+       done
+
+dist-info: $(INFO_DEPS)
+       list='$(INFO_DEPS)'; \
+       for base in $$list; do \
+         if test -f $$base; then d=.; else d=$(srcdir); fi; \
+         for file in `cd $$d && eval echo $$base*`; do \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file; \
+         done; \
+       done
+
+mostlyclean-aminfo:
+       -rm -f binutils.aux binutils.cp binutils.cps binutils.dvi binutils.fn \
+         binutils.fns binutils.ky binutils.kys binutils.ps \
+         binutils.log binutils.pg binutils.toc binutils.tp \
+         binutils.tps binutils.vr binutils.vrs binutils.op binutils.tr \
+         binutils.cv binutils.cn
+
+clean-aminfo:
+
+distclean-aminfo:
+
+maintainer-clean-aminfo:
+       for i in $(INFO_DEPS); do \
+         rm -f $$i; \
+         if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \
+           rm -f $$i-[0-9]*; \
+         fi; \
+       done
+clean-info: mostlyclean-aminfo
+
+install-man1:
+       $(mkinstalldirs) $(DESTDIR)$(man1dir)
+       @list='$(man1_MANS)'; \
+       l2='$(man_MANS)'; for i in $$l2; do \
+         case "$$i" in \
+           *.1*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+         else file=$$i; fi; \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+         $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+       done
+
+uninstall-man1:
+       @list='$(man1_MANS)'; \
+       l2='$(man_MANS)'; for i in $$l2; do \
+         case "$$i" in \
+           *.1*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+         rm -f $(DESTDIR)$(man1dir)/$$inst; \
+       done
+install-man: $(MANS)
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-man1
+uninstall-man:
+       @$(NORMAL_UNINSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive install-info-recursive \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+         rev="$$subdir $$rev"; \
+         test "$$subdir" = "." && dot_seen=yes; \
+       done; \
+       test "$$dot_seen" = "no" && rev=". $$rev"; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+   if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+   fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)config.in$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.in $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       -rm -rf $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+       mkdir $(distdir)/=build
+       mkdir $(distdir)/=inst
+       dc_install_base=`cd $(distdir)/=inst && pwd`; \
+       cd $(distdir)/=build \
+         && ../configure --srcdir=.. --prefix=$$dc_install_base \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) dist
+       -rm -rf $(distdir)
+       @banner="$(distdir).tar.gz is ready for distribution"; \
+       dashes=`echo "$$banner" | sed s/./=/g`; \
+       echo "$$dashes"; \
+       echo "$$banner"; \
+       echo "$$dashes"
+dist: distdir
+       -chmod -R a+r $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+       -rm -rf $(distdir)
+dist-all: distdir
+       -chmod -R a+r $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+       -rm -rf $(distdir)
+distdir: $(DISTFILES)
+       -rm -rf $(distdir)
+       mkdir $(distdir)
+       -chmod 777 $(distdir)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           cp -pr $$/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+       for subdir in $(SUBDIRS); do \
+         if test "$$subdir" = .; then :; else \
+           test -d $(distdir)/$$subdir \
+           || mkdir $(distdir)/$$subdir \
+           || exit 1; \
+           chmod 777 $(distdir)/$$subdir; \
+           (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+             || exit 1; \
+         fi; \
+       done
+       $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info
+
+RUNTESTFLAGS =
+
+DEJATOOL = $(PACKAGE)
+
+RUNTESTDEFAULTFLAGS = --tool $(DEJATOOL) --srcdir $$srcdir
+site.exp: Makefile
+       @echo 'Making a new site.exp file...'
+       @test ! -f site.bak || rm -f site.bak
+       @echo '## these variables are automatically generated by make ##' > $@-t
+       @echo '# Do not edit here.  If you wish to override these values' >> $@-t
+       @echo '# edit the last section' >> $@-t
+       @echo 'set tool $(DEJATOOL)' >> $@-t
+       @echo 'set srcdir $(srcdir)' >> $@-t
+       @echo 'set objdir' `pwd` >> $@-t
+       @echo 'set host_alias $(host_alias)' >> $@-t
+       @echo 'set host_triplet $(host_triplet)' >> $@-t
+       @echo 'set target_alias $(target_alias)' >> $@-t
+       @echo 'set target_triplet $(target_triplet)' >> $@-t
+       @echo 'set build_alias $(build_alias)' >> $@-t
+       @echo 'set build_triplet $(build_triplet)' >> $@-t
+       @echo '## All variables above are generated by configure. Do Not Edit ##' >> $@-t
+       @test ! -f site.exp || sed '1,/^## All variables above are.*##/ d' site.exp >> $@-t
+       @test ! -f site.exp || mv site.exp site.bak
+       @mv $@-t site.exp
+info-am: $(INFO_DEPS)
+info: info-recursive
+dvi-am: $(DVIS)
+dvi: dvi-recursive
+check-am:
+       $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+install-info-am: 
+install-info: install-info-recursive
+all-recursive-am: config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+install-exec-am: install-binPROGRAMS install-exec-local
+install-exec: install-exec-recursive
+
+install-data-am: install-man
+install-data: install-data-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+uninstall: uninstall-recursive
+all-am: Makefile $(PROGRAMS) $(MANS) config.h
+all-redirect: all-recursive-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+       $(mkinstalldirs)  $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
+
+
+mostlyclean-generic:
+       -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+       -test -z "arlexldeflexlrclexlarparseharparsecdefparsehdefparsecnlmheaderhnlmheadercrcparsehrcparsec$(MAINTAINERCLEANFILES)" || rm -f arlexl deflexl rclexl arparseh arparsec defparseh defparsec nlmheaderh nlmheaderc rcparseh rcparsec $(MAINTAINERCLEANFILES)
+mostlyclean-am:  mostlyclean-hdr mostlyclean-binPROGRAMS \
+               mostlyclean-noinstPROGRAMS mostlyclean-compile \
+               mostlyclean-libtool mostlyclean-aminfo mostlyclean-tags \
+               mostlyclean-generic mostlyclean-local
+
+mostlyclean: mostlyclean-recursive
+
+clean-am:  clean-hdr clean-binPROGRAMS clean-noinstPROGRAMS \
+               clean-compile clean-libtool clean-aminfo clean-tags \
+               clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am:  distclean-hdr distclean-binPROGRAMS \
+               distclean-noinstPROGRAMS distclean-compile \
+               distclean-libtool distclean-aminfo distclean-tags \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-recursive
+       -rm -f config.status
+
+maintainer-clean-am:  maintainer-clean-hdr maintainer-clean-binPROGRAMS \
+               maintainer-clean-noinstPROGRAMS \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-aminfo maintainer-clean-tags \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \
+clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool install-info-am uninstall-info \
+mostlyclean-aminfo distclean-aminfo clean-aminfo \
+maintainer-clean-aminfo install-man1 uninstall-man1 install-man \
+uninstall-man install-data-recursive uninstall-data-recursive \
+install-exec-recursive uninstall-exec-recursive installdirs-recursive \
+uninstalldirs-recursive all-recursive check-recursive \
+installcheck-recursive info-recursive dvi-recursive \
+mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir check-DEJAGNU \
+info-am info dvi-am dvi check check-am installcheck-am installcheck \
+install-info-am install-info all-recursive-am install-exec-local \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs-am \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+po/POTFILES.in: @MAINT@ Makefile
+       for file in $(POTFILES); do echo $$file; done | sort > tmp \
+         && mv tmp $(srcdir)/po/POTFILES.in
+
+check-DEJAGNU: site.exp
+       srcdir=`cd $(srcdir) && pwd`; export srcdir; \
+       r=`pwd`; export r; \
+       EXPECT=$(EXPECT); export EXPECT; \
+       if [ -f $(top_builddir)/../expect/expect ]; then \
+         TCL_LIBRARY=`cd $(top_srcdir)/../tcl/library && pwd`; \
+         export TCL_LIBRARY; \
+       fi; \
+       runtest=$(RUNTEST); \
+       if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+         $$runtest --tool $(DEJATOOL) --srcdir $${srcdir}/testsuite \
+               CC_FOR_TARGET="$(CC_FOR_TARGET)" \
+               CFLAGS_FOR_TARGET="$(CFLAGS)" $(RUNTESTFLAGS); \
+       else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+       fi
+
+installcheck:
+       /bin/sh $(srcdir)/sanity.sh $(bindir)
+
+underscore.c: stamp-under ; @true
+
+stamp-under: Makefile
+       echo '/*WARNING: This file is automatically generated!*/' >underscore.t
+       echo "int prepends_underscore = @UNDERSCORE@;" >>underscore.t
+       $(SHELL) $(srcdir)/../move-if-change underscore.t underscore.c
+       touch stamp-under
+
+cplus-dem.o: $(BASEDIR)/libiberty/cplus-dem.c $(INCDIR)/getopt.h
+       $(COMPILE) -c -DMAIN -DVERSION='"$(VERSION)"' $(BASEDIR)/libiberty/cplus-dem.c
+
+# The following is commented out for the convertion to automake.
+# This rule creates a single binary that switches between ar and ranlib
+# by looking at argv[0].  Use this kludge to save some disk space.
+# However, you have to install things by hand.
+# (That is after 'make install', replace the installed ranlib by a link to ar.)
+# Alternatively, you can install ranlib.sh as ranlib.
+# ar_with_ranlib: $(ADDL_DEPS) ar.o maybe-ranlib.o
+#      $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(AR_PROG) ar.o maybe-ranlib.o $(ADDL_LIBS) $(EXTRALIBS)
+#      -rm -f $(RANLIB_PROG)
+#      -ln $(AR_PROG) $(RANLIB_PROG)
+#
+# objcopy and strip in one binary that uses argv[0] to decide its action.
+#
+#objcopy_with_strip: $(ADDL_DEPS) objcopy.o maybe-strip.o
+#      $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o maybe-strip.o $(ADDL_LIBS) $(EXTRALIBS)
+#      -rm -f $(STRIP_PROG)
+#      -ln $(OBJCOPY_PROG) $(STRIP_PROG)
+
+sysroff.c: sysinfo$(EXEEXT_FOR_BUILD) sysroff.info 
+       ./sysinfo$(EXEEXT_FOR_BUILD) -c <$(srcdir)/sysroff.info >sysroff.c
+       ./sysinfo$(EXEEXT_FOR_BUILD) -i <$(srcdir)/sysroff.info >>sysroff.c
+       ./sysinfo$(EXEEXT_FOR_BUILD) -g <$(srcdir)/sysroff.info >>sysroff.c
+
+sysroff.h: sysinfo$(EXEEXT_FOR_BUILD) sysroff.info
+       ./sysinfo$(EXEEXT_FOR_BUILD) -d <$(srcdir)/sysroff.info >sysroff.h
+
+sysinfo$(EXEEXT_FOR_BUILD): sysinfo.o syslex.o
+       $(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o $@ sysinfo.o syslex.o 
+
+syslex.o: syslex.c sysinfo.h
+       if [ -r syslex.c ]; then \
+         $(CC_FOR_BUILD) -c -I. $(CFLAGS)  syslex.c  ; \
+       else \
+         $(CC_FOR_BUILD) -c -I. -I$(srcdir) $(CFLAGS) $(srcdir)/syslex.c ;\
+       fi
+
+sysinfo.o: sysinfo.c
+       if [ -r sysinfo.c ]; then \
+         $(CC_FOR_BUILD) -c -I. $(CFLAGS)  sysinfo.c  ; \
+       else \
+         $(CC_FOR_BUILD) -c -I. $(CFLAGS) $(srcdir)/sysinfo.c ; \
+       fi
+
+dlltool.o:dlltool.c
+       $(COMPILE) -c $(DLLTOOL_DEFS) $(srcdir)/dlltool.c
+
+# coff/sym.h and coff/ecoff.h won't be found by the automatic dependency
+# scripts, since they are only included conditionally.
+nlmconv.o: nlmconv.c $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h
+       ldname=`echo ld | sed '$(transform)'`; \
+       $(COMPILE) -c -DLD_NAME="\"$${ldname}\"" @NLMCONV_DEFS@ $(srcdir)/nlmconv.c
+
+
+diststuff: $(DISTSTUFF) info
+
+# Targets to rebuild dependencies in this Makefile.
+# Have to get rid of .dep1 here so that "$?" later includes all of $(CFILES).
+.dep: dep.sed $(CFILES) $(HFILES) $(GENERATED_CFILES) $(GENERATED_HFILES) config.h
+       rm -f .dep1
+       $(MAKE) DEP=$(DEP) .dep1
+       sed -f dep.sed <.dep1 >.dep
+
+# This rule really wants a mkdep that runs "gcc -MM".
+.dep1: $(CFILES) $(GENERATED_CFILES)
+       rm -f .dep2
+       echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep2
+       $(DEP) -f .dep2 $(INCLUDES) $?
+       $(SHELL) $(srcdir)/../move-if-change .dep2 .dep1
+
+dep.sed: dep-in.sed config.status
+       objdir=`pwd`; \
+       sed <$(srcdir)/dep-in.sed >dep.sed      \
+               -e 's!@INCDIR@!$(INCDIR)!'      \
+               -e 's!@BFDDIR@!$(BFDDIR)!'      \
+               -e 's!@SRCDIR@!$(srcdir)!'      \
+               -e "s!@OBJDIR@!$${objdir}!"
+
+dep: .dep
+       sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile
+       cat .dep >> tmp-Makefile
+       $(SHELL) $(srcdir)/../move-if-change tmp-Makefile Makefile
+
+dep-in: .dep
+       sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in
+       cat .dep >> tmp-Makefile.in
+       $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in
+
+dep-am: .dep
+       sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.am > tmp-Makefile.am
+       cat .dep >> tmp-Makefile.am
+       $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.am $(srcdir)/Makefile.am
+
+.PHONY: dep dep-in dep-am
+
+###
+# DOCUMENTATION TARGETS
+config.texi: Makefile
+       rm -f config.texi
+       echo '@set VERSION $(VERSION)' > config.texi
+
+binutils.dvi: $(srcdir)/binutils.texi config.texi
+
+binutils.info: $(srcdir)/binutils.texi config.texi
+
+$(DEMANGLER_PROG).1: cxxfilt.man Makefile
+       sed -e 's/@PROGRAM@/$(DEMANGLER_PROG)/' < $(srcdir)/cxxfilt.man \
+               > $(DEMANGLER_PROG).1
+mostlyclean-local:
+       -rm -rf tmpdir
+
+.PHONY: install-exec-local
+
+install-exec-local: $(bin_PROGRAMS) $(noinst_PROGRAMS)
+       @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+           $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+         else :; fi; \
+       done
+       $(mkinstalldirs) $(tooldir)/bin
+       for i in $(TOOL_PROGS); do \
+         if [ -f $$i$(EXEEXT) ]; then \
+           j=`echo $$i | sed -e 's/-new//'`; \
+           k=`echo $$j | sed '$(transform)'`; \
+           if [ "$(bindir)/$$k$(EXEEXT)" != "$(tooldir)/bin/$$j$(EXEEXT)" ]; then \
+             rm -f $(tooldir)/bin/$$j$(EXEEXT); \
+             ln $(bindir)/$$k$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT) >/dev/null 2>/dev/null \
+               || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$i$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT); \
+           fi; \
+         else true; \
+         fi; \
+       done
+
+# What appears below is generated by a hacked mkdep using gcc -MM.
+
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+addr2line.o: addr2line.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/getopt.h $(INCDIR)/libiberty.h $(INCDIR)/demangle.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h
+ar.o: ar.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
+  $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/aout/ar.h $(BFDDIR)/libbfd.h arsup.h
+arsup.o: arsup.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  arsup.h $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h
+bucomm.o: bucomm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h
+coffdump.o: coffdump.c coffgrok.h bucomm.h config.h \
+  $(INCDIR)/fopen-same.h
+coffgrok.o: coffgrok.c bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \
+  coffgrok.h
+debug.o: debug.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h
+dlltool.o: dlltool.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/getopt.h $(INCDIR)/demangle.h dlltool.h
+filemode.o: filemode.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h
+ieee.o: ieee.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/ieee.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h budbg.h
+is-ranlib.o: is-ranlib.c
+is-strip.o: is-strip.c
+maybe-ranlib.o: maybe-ranlib.c
+maybe-strip.o: maybe-strip.c
+nlmconv.o: nlmconv.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(BFDDIR)/libnlm.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \
+  $(INCDIR)/nlm/external.h nlmconv.h
+nm.o: nm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/progress.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h \
+  $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ranlib.h \
+  $(INCDIR)/demangle.h $(INCDIR)/libiberty.h
+not-ranlib.o: not-ranlib.c
+not-strip.o: not-strip.c
+objcopy.o: objcopy.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/getopt.h $(INCDIR)/libiberty.h budbg.h
+objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/getopt.h $(INCDIR)/progress.h bucomm.h config.h \
+  $(INCDIR)/fopen-same.h $(INCDIR)/dis-asm.h $(INCDIR)/libiberty.h \
+  $(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h
+prdbg.o: prdbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h budbg.h
+rdcoff.o: rdcoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/coff/internal.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/libiberty.h $(INCDIR)/demangle.h debug.h \
+  budbg.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h
+rddbg.o: rddbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h budbg.h
+size.o: size.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/getopt.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h
+srconv.o: srconv.c bucomm.h config.h $(INCDIR)/fopen-same.h \
+  sysroff.h coffgrok.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \
+  $(INCDIR)/bfdlink.h sysroff.c
+stabs.o: stabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  $(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h \
+  $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def
+strings.o: strings.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h
+sysdump.o: sysdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h sysroff.h \
+  sysroff.c
+version.o: version.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h
+wrstabs.o: wrstabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  debug.h budbg.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+  $(INCDIR)/aout/stab.def
+windres.o: windres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/getopt.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/libiberty.h $(INCDIR)/obstack.h windres.h \
+  winduni.h
+resrc.o: resrc.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h
+rescoff.o: rescoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \
+  $(INCDIR)/bfdlink.h
+resbin.o: resbin.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h
+winduni.o: winduni.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h winduni.h
+readelf.o: readelf.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \
+  $(INCDIR)/elf/dwarf2.h $(INCDIR)/elf/i386.h $(INCDIR)/elf/reloc-macros.h \
+  $(INCDIR)/elf/v850.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/mips.h \
+  $(INCDIR)/elf/alpha.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/m68k.h \
+  $(INCDIR)/elf/sparc.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/d10v.h \
+  $(INCDIR)/elf/d30v.h $(INCDIR)/elf/sh.h $(INCDIR)/elf/mn10200.h \
+  $(INCDIR)/elf/mn10300.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/arc.h \
+  $(INCDIR)/elf/fr30.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/getopt.h
+resres.o: resres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h
+dyn-string.o: dyn-string.c config.h $(INCDIR)/ansidecl.h \
+  dyn-string.h
+dllwrap.o: dllwrap.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/getopt.h dyn-string.h
+rename.o: rename.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h
+underscore.o: underscore.c
+arparse.o: arparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h arsup.h
+arlex.o: arlex.c $(INCDIR)/libiberty.h arparse.h
+sysroff.o: sysroff.c
+sysinfo.o: sysinfo.c
+syslex.o: syslex.c sysinfo.h
+defparse.o: defparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h dlltool.h
+deflex.o: deflex.c $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \
+  defparse.h dlltool.h
+nlmheader.o: nlmheader.c ../bfd/bfd.h bucomm.h config.h \
+  $(INCDIR)/fopen-same.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \
+  nlmconv.h
+rcparse.o: rcparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h
+rclex.o: rclex.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \
+  windres.h winduni.h rcparse.h
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/binutils/NEWS b/binutils/NEWS
new file mode 100644 (file)
index 0000000..76dcebd
--- /dev/null
@@ -0,0 +1,163 @@
+-*- text -*-
+
+Changes in binutils 2.10:
+
+* objdump support for -mi386:intel which causes disassembly to be displayed with
+  intel syntax.
+
+* New program: readelf.  This displays the contents of ELF format files,
+  regardless of target machine.
+
+* objcopy now takes --change-section-lma, --change-section-vma, and
+  --change-section-address options.  The old --adjust-section-vma option is
+  equivalent to --change-section-address.  The other --adjust-* options are now
+  renamed to --change-*, although --adjust-* continues to work.
+
+* dlltool now supports the IMPORTS command.
+
+* dlltool now takes --export-all-symbols, --no-export-all-symbols,
+  --exclude-symbols, and --no-default-excludes options.
+
+Changes in binutils 2.9:
+
+* Added windres program, which can be used to manipulate resources in WIN32
+  files as used on Windows 95 and Windows NT.
+
+* The objcopy --gap-fill and --pad-to options operate on the LMA rather than
+  the VMA of the sections.
+
+* Added S modifier to ar to not build a symbol table.
+
+Changes in binutils 2.8:
+
+* The objdump disassembly format has been changed, and hopefully improved.  Use
+  the new --prefix-addresses option to get the old format.  There are also new
+  --disassemble-zeroes and --no-show-raw-insn options which affect disassembler
+  output.
+
+* Formats may now be specified as configuration triplets.  For example,
+  objdump -b i386-pc-linux.  The triplets are not passed through config.sub,
+  so they must be in canonical form.
+
+* Added new addr2line program.  This uses the debugging information to convert
+  an address into a file name and line number within a program.
+
+* Added --change-leading-char argument to objcopy.
+
+* Added --weaken argument to objcopy.
+
+* objdump --dynamic-reloc now works on ELF executables and shared libraries.
+
+* Added --adjust-vma option to objdump.
+
+* Added -C/--demangle option to objdump.
+
+* Added -p/--preserve-dates option to strip and objcopy.
+
+Changes in binutils 2.7:
+
+* Added --enable-shared and --enable-commonbfdlib options to configure.
+
+* Added --debugging argument to objdump and objcopy.
+
+* Added --defined-only argument to nm.
+
+* Added --remove-leading-char argument to objcopy.
+
+* The objdump --line-numbers option is now meaningful with --reloc.
+
+* Added --line-numbers option to nm.
+
+* Added --endian/-EB/-EL option to objdump.
+
+* Added support for Alpha OpenVMS/AXP.
+
+Changes in binutils 2.6:
+
+* Added -N/--strip-symbol and -K/--keep-symbol arguments to strip and objcopy.
+
+* Added several arguments to objcopy to provide some control over how the new
+  file is laid out in memory.  Also added binary output format to BFD to permit
+  generating plain binary files.
+
+* Added --start-address and --stop-address options to objdump.
+
+* ar and ranlib now work on AIX.  The tools are now built by default on AIX.
+
+Changes in binutils 2.5:
+
+* Changed objdump -dr to dump the relocs interspersed with the assembly
+  listing, for a more useful listing of relocateable files.
+
+* Changed objdump -d/--disassemble to only disassemble SEC_CODE sections.
+  Added -D/--disassemble-all option to disassemble all sections.
+
+* Added --size-sort option to nm.
+
+* strip and objcopy should now be able to handle dynamically linked ELF
+  executables.
+
+Changes in binutils 2.4:
+
+* Support for HP-PA (by Jeff Law), i386 Mach (by David Mackenzie), RS/6000 and
+  PowerPC (except ar and ranlib; by Ian Taylor).
+
+* Support for Irix 5.
+
+* Programs `strip' and `objcopy' will not attempt to write dynamically linked
+  ELF output files, since BFD currently can't create them properly.
+
+Changes in binutils 2.3:
+
+* A new --stabs argument has been added to objdump to dump stabs sections in
+  ELF and COFF files.
+
+* A new program, nlmconv, has been added.  It can convert object files into
+  Novell NetWare Loadable Modules.
+
+* The strings program has been added.
+
+Changes in binutils 2.2:
+
+* The 'copy' program has been renamed to 'objcopy', for consistency with
+  'objdump', and because 'copy' might more plausibly be used as a synonym for
+  'cp'.
+
+* The new stand-alone program c++filt is a filter that converts encoded
+  (mangled) C++ assembly-level identifiers to user-level names.  (Note: This
+  may get moved to the gcc distribution.)
+
+* nm -o on an archive now prefixes each line with the archive name, matching
+  the output from BSD nm.
+
+* ar (and ld) can now read (but not write) BSD4.4-style archives.
+
+* New support for H8500, Z8000, and the Hitach SH.
+
+* Dis-assembler interface changed to allow sharing with gdb.
+
+* There is new Elf code, but it is not yet ready for general use.
+
+* There is the beginnings of a test suite.
+
+Changes in binutils 2.1:
+
+* There is now support for writing ECOFF files, so ld and the other utilities
+  should work on Risc/Ultrix and Irix.  Please let us know how well this works.
+
+* ar now automatically creates a symbol table (a __.SYMDEF member, in the BSD
+  version), if there are any object files in the archive.  So running ranlib is
+  now redundant (unless the non-standard q command is used).  This is required
+  for Posix.2 conformance.
+
+* The archive-reading code now reads both BSD-style and SYSV-style archives
+  independently of the selected target format.  This is to encourage people to
+  switch to SYSV-format, which has a number of advantages.
+
+* The strip and copy programs now have options to remove debug-symbols only
+  and/or local symbols only.  They now also support long options.
+
+\f
+Local variables:
+fill-column: 79
+End:
diff --git a/binutils/README b/binutils/README
new file mode 100644 (file)
index 0000000..4b2d277
--- /dev/null
@@ -0,0 +1,189 @@
+These are the GNU binutils.  These are utilities of use when dealing
+with object files.
+
+The linker (ld) is in a separate directory, which should be ../ld.
+Linker-specific notes are in ../ld/README.
+
+As of version 2.5, the assembler (as) is also included in this package, in
+../gas.  Assembler-specific notes can be found in ../gas/README.
+
+Recent changes are in ./NEWS, ../ld/NEWS, and ../gas/NEWS.
+
+Unpacking and Installation -- quick overview
+============================================
+
+When you unpack the binutils-2.9.tar.gz file, you'll get a directory
+called something like `binutils-2.9', which contains various files and
+directories.  Most of the files in the top directory are for
+information and for configuration.  The actual source code is in
+subdirectories.
+
+To build binutils, you can just do:
+
+       cd binutils-2.9
+       ./configure [options]
+       make
+       make install # copies the programs files into /usr/local/bin
+                    # by default.
+
+This will configure and build all the libraries as well as the
+assembler, the binutils, and the linker.
+
+If you have GNU make, we recommend building in a different directory:
+
+       mkdir objdir
+       cd objdir
+       ../binutils-2.9/configure [options]
+       make
+       make install
+
+This relies on the VPATH feature of GNU make.
+
+By default, the binutils will be configured to support the system on
+which they are built.  When doing cross development, use the --target
+configure option to specify a different target.
+
+The --enable-targets option adds support for more binary file formats
+besides the default.  List them as the argument to --enable-targets,
+separated by commas.  For example:
+
+       ./configure --enable-targets=sun3,rs6000-aix,decstation
+
+The name 'all' compiles in support for all valid BFD targets (this was
+the default in releases before 2.3):
+
+       ./configure --enable-targets=all
+
+You can also specify the --enable-shared option when you run
+configure.  This will build the BFD and opcodes libraries as shared
+libraries.  You can use arguments with the --enable-shared option to
+indicate that only certain libraries should be built shared; for
+example, --enable-shared=bfd.  The only potential shared libraries in
+a binutils release are bfd and opcodes.
+
+The binutils will be linked against the shared libraries.  The build
+step will attempt to place the correct library in the runtime search
+path for the binaries.  However, in some cases, after you install the
+binaries, you may have to set an environment variable, normally
+LD_LIBRARY_PATH, so that the system can find the installed libbfd
+shared library.
+
+To build under openVMS/AXP, see the file makefile.vms in the top level
+directory.
+
+If you don't have ar
+====================
+
+If your system does not already have an ar program, the normal
+binutils build process will not work.  In this case, run configure as
+usual.  Before running make, run this script:
+
+#!/bin/sh
+MAKE_PROG="${MAKE-make}"
+MAKE="${MAKE_PROG} AR=true LINK=true"
+export MAKE
+${MAKE} $* all-libiberty
+${MAKE} $* all-intl
+${MAKE} $* all-bfd
+cd binutils
+MAKE="${MAKE_PROG}"
+export MAKE
+${MAKE} $* ar_DEPENDENCIES= ar_LDADD='../bfd/*.o `cat ../libiberty/required-list ../libiberty/needed-list | sed -e "s,\([^ ][^ ]*\),../libiberty/\1,g"` `if test -f ../intl/gettext.o; then echo '../intl/*.o'; fi`' ar
+
+This script will build an ar program in binutils/ar.  Move binutils/ar
+into a directory on your PATH.  After doing this, you can run make as
+usual to build the complete binutils distribution.  You do not need
+the ranlib program in order to build the distribution.
+
+Porting
+=======
+
+Binutils-2.9 supports many different architectures, but there
+are many more not supported, including some that were supported
+by earlier versions.  We are hoping for volunteers to
+improve this situation.
+
+The major effort in porting binutils to a new host and/or target
+architecture involves the BFD library.  There is some documentation
+in ../bfd/doc.  The file ../gdb/doc/gdbint.texinfo (distributed
+with gdb-4.x) may also be of help.
+
+Reporting bugs
+==============
+
+Send bug reports and patches to bug-gnu-utils@gnu.org.  Always mention
+the version number you are running; this is printed by running any of
+the binutils with the --version option.  We appreciate reports about
+bugs, but we do not promise to fix them.
+
+VMS
+===
+
+This section was written by Klaus K"ampf <kkaempf@rmi.de>.  It
+describes how to build and install the binutils on openVMS (Alpha and
+Vax).  (The BFD library only supports reading Vax object files.)
+
+Compiling the release:
+
+To compile the gnu binary utilities and the gnu assembler, you'll
+need DEC C or GNU C for openVMS/Alpha. You'll need *both* compilers
+on openVMS/Vax.
+
+Compiling with either DEC C or GNU C works on openVMS/Alpha only. Some
+of the opcodes and binutils files trap a bug in the DEC C optimizer,
+so these files must be compiled with /noopt.
+
+Compiling on openVMS/Vax is a bit complicated, as the bfd library traps
+a bug in GNU C and the gnu assembler a bug in (my version of) DEC C.
+
+I never tried compiling with VAX C.
+
+
+You further need GNU Make Version 3.76 or later. This is available
+at ftp.progis.de or any GNU archive site. The makefiles assume that
+gmake starts gnu make as a foreign command.
+
+If you're compiling with DEC C or VAX C, you must run
+
+  $ @setup
+
+before starting gnu-make. This isn't needed with GNU C.
+
+On the Alpha you can choose the compiler by editing the toplevel
+makefile.vms. Either select CC=cc (for DEC C) or CC=gcc (for GNU C)
+
+
+Installing the release
+
+Provided that your directory setup conforms to the GNU on openVMS
+standard, you already have a concealed deviced named 'GNU_ROOT'.
+In this case, a simple
+
+ $ gmake install
+
+suffices to copy all programs and libraries to the proper directories.
+
+Define the programs as foreign commands by adding these lines to your
+login.com:
+
+  $ gas :== $GNU_ROOT:[bin]as.exe
+  $ size :== $GNU_ROOT:[bin]size.exe
+  $ nm :== $GNU_ROOT:[bin]nm.exe
+  $ objdump :== $GNU_ROOT:[bin]objdump.exe
+  $ strings :== $GNU_ROOT:[bin]strings.exe
+
+If you have a different directory setup, copy the binary utilities
+([.binutils]size.exe, [.binutils]nm.exe, [.binutils]objdump.exe,
+and [.binutils]strings.exe) and the gnu assembler and preprocessor
+([.gas]as.exe and [.gas]gasp.exe]) to a directory of your choice
+and define all programs as foreign commands.
+
+
+If you're satiesfied with the compilation, you may want to remove
+unneeded objects and libraries:
+
+  $ gmake clean
+
+
+If you have any problems or questions about the binutils on VMS, feel
+free to mail me at kkaempf@rmi.de.
diff --git a/binutils/acinclude.m4 b/binutils/acinclude.m4
new file mode 100644 (file)
index 0000000..71b09b9
--- /dev/null
@@ -0,0 +1 @@
+sinclude(../bfd/acinclude.m4)
diff --git a/binutils/aclocal.m4 b/binutils/aclocal.m4
new file mode 100644 (file)
index 0000000..88a1565
--- /dev/null
@@ -0,0 +1,1120 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+sinclude(../bfd/acinclude.m4)
+
+# Do all the work for Automake.  This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "[$]*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "[$]*" != "X $srcdir/configure conftestfile" \
+      && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "[$]2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+   $1=$2
+   AC_MSG_RESULT(found)
+else
+   $1="$3/missing $2"
+   AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+
+# serial 35 AC_PROG_LIBTOOL
+AC_DEFUN(AC_PROG_LIBTOOL,
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+# Save cache, so that ltconfig can load it
+AC_CACHE_SAVE
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+DLLTOOL="$DLLTOOL" AS="$AS" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| AC_MSG_ERROR([libtool configure failed])
+
+# Reload cache, that may have been modified by ltconfig
+AC_CACHE_LOAD
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+])
+
+AC_DEFUN(AC_LIBTOOL_SETUP,
+[AC_PREREQ(2.13)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_RANLIB])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_SYS_NM_PARSE])dnl
+AC_REQUIRE([AC_SYS_SYMBOL_UNDERSCORE])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+dnl
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags="--cache-file=$cache_file"
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$lt_dlopen" = yes && libtool_flags="$libtool_flags --enable-dlopen"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$host" in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+*-*-cygwin*)
+  AC_SYS_LIBTOOL_CYGWIN
+  ;;
+
+esac
+
+# enable the --disable-libtool-lock switch
+
+AC_ARG_ENABLE(libtool-lock,
+[  --disable-libtool-lock  force libtool not to do file locking],
+need_locks=$enableval,
+need_locks=yes)
+
+if test x"$need_locks" = xno; then
+  libtool_flags="$libtool_flags --disable-lock"
+fi
+])
+
+# AC_LIBTOOL_DLOPEN - check for dlopen support
+AC_DEFUN(AC_LIBTOOL_DLOPEN, [lt_dlopen=yes])
+
+# AC_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_SHARED,
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<<  --enable-shared[=PKGS]  build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN(AC_DISABLE_SHARED,
+[AC_ENABLE_SHARED(no)])
+
+# AC_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_STATIC,
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<<  --enable-static[=PKGS]  build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+])
+
+# AC_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN(AC_DISABLE_STATIC,
+[AC_ENABLE_STATIC(no)])
+
+
+# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_FAST_INSTALL,
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(fast-install,
+changequote(<<, >>)dnl
+<<  --enable-fast-install[=PKGS]  optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+])
+
+# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install
+AC_DEFUN(AC_DISABLE_FAST_INSTALL,
+[AC_ENABLE_FAST_INSTALL(no)])
+
+
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN(AC_PROG_LD,
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  ac_prog=`($CC -print-prog-name=ld) 2>&5`
+  case "$ac_prog" in
+    # Accept absolute paths.
+changequote(,)dnl
+    /* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+changequote([,])dnl
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog"; then
+      ac_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_SUBST(LD)
+AC_PROG_LD_GNU
+])
+
+AC_DEFUN(AC_PROG_LD_GNU,
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  ac_cv_prog_gnu_ld=yes
+else
+  ac_cv_prog_gnu_ld=no
+fi])
+])
+
+# AC_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN(AC_PROG_NM,
+[AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(ac_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  ac_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/nm; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -B"
+       break
+      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -p"
+       break
+      else
+       ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi])
+NM="$ac_cv_path_NM"
+AC_MSG_RESULT([$NM])
+AC_SUBST(NM)
+])
+
+# AC_SYS_NM_PARSE - Check for command to grab the raw symbol name followed
+# by C symbol name from nm.
+AC_DEFUN(AC_SYS_NM_PARSE,
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output])
+AC_CACHE_VAL(ac_cv_sys_global_symbol_pipe,
+[# These are sane defaults that work on at least a few old systems.
+# {They come from Ultrix.  What could be older than Ultrix?!! ;)}
+
+changequote(,)dnl
+# Character class describing NM global symbol codes.
+ac_symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+ac_symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+  ac_symcode='[BCDT]'
+  ;;
+cygwin* | mingw*)
+  ac_symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+  ;;
+irix*)
+  ac_symcode='[BCDEGRST]'
+  ;;
+solaris*)
+  ac_symcode='[BDT]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  ac_symcode='[ABCDGISTW]'
+fi
+changequote([,])dnl
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[      ]\($ac_symcode\)[       ][      ]*\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  ac_pipe_works=no
+  rm -f conftest.$ac_ext
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func;return 0;}
+EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+  
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
+
+      # Try sorting and uniquifying the output.
+      if sort "$ac_nlist" | uniq > "$ac_nlist"T; then
+       mv -f "$ac_nlist"T "$ac_nlist"
+      else
+       rm -f "$ac_nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then
+       if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then
+         cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c'
+
+         cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+changequote(,)dnl
+lt_preloaded_symbols[] =
+changequote([,])dnl
+{
+EOF
+       sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c
+       cat <<\EOF >> conftest.c
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftestm.$ac_objext
+         ac_save_LIBS="$LIBS"
+         ac_save_CFLAGS="$CFLAGS"
+         LIBS="conftestm.$ac_objext"
+         CFLAGS="$CFLAGS$no_builtin_flag"
+         if AC_TRY_EVAL(ac_link) && test -s conftest; then
+           ac_pipe_works=yes
+         else
+           echo "configure: failed program was:" >&AC_FD_CC
+           cat conftest.c >&AC_FD_CC
+         fi
+         LIBS="$ac_save_LIBS"
+         CFLAGS="$ac_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $ac_nlist" >&AC_FD_CC
+       fi
+      else
+       echo "cannot find nm_test_var in $ac_nlist" >&AC_FD_CC
+      fi
+    else
+      echo "cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC
+    fi
+  else
+    echo "$progname: failed program was:" >&AC_FD_CC
+    cat conftest.c >&AC_FD_CC
+  fi
+  rm -rf conftest*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$ac_pipe_works" = yes; then
+    if test x"$ac_symprfx" = x"_"; then
+      ac_cv_sys_symbol_underscore=yes
+    else
+      ac_cv_sys_symbol_underscore=no
+    fi
+    break
+  else
+    ac_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+
+ac_result=yes
+if test -z "$ac_cv_sys_global_symbol_pipe"; then
+   ac_result=no
+fi
+AC_MSG_RESULT($ac_result)
+])
+
+# AC_SYS_LIBTOOL_CYGWIN - find tools needed on cygwin
+AC_DEFUN(AC_SYS_LIBTOOL_CYGWIN,
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+AC_CHECK_TOOL(AS, as, false)
+])
+
+# AC_SYS_SYMBOL_UNDERSCORE - does the compiler prefix global symbols
+#                            with an underscore?
+AC_DEFUN(AC_SYS_SYMBOL_UNDERSCORE,
+[AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_SYS_NM_PARSE])dnl
+AC_MSG_CHECKING([for _ prefix in compiled symbols])
+AC_CACHE_VAL(ac_cv_sys_symbol_underscore,
+[ac_cv_sys_symbol_underscore=no
+cat > conftest.$ac_ext <<EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+EOF
+if AC_TRY_EVAL(ac_compile); then
+  # Now try to grab the symbols.
+  ac_nlist=conftest.nm
+  if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
+    # See whether the symbols have a leading underscore.
+    if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+      ac_cv_sys_symbol_underscore=yes
+    else
+      if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+       :
+      else
+       echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC
+      fi
+    fi
+  else
+    echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC
+  fi
+else
+  echo "configure: failed program was:" >&AC_FD_CC
+  cat conftest.c >&AC_FD_CC
+fi
+rm -rf conftest*
+])
+AC_MSG_RESULT($ac_cv_sys_symbol_underscore)
+USE_SYMBOL_UNDERSCORE=${ac_cv_sys_symbol_underscore=no}
+AC_SUBST(USE_SYMBOL_UNDERSCORE)dnl
+])
+
+# AC_CHECK_LIBM - check for math library
+AC_DEFUN(AC_CHECK_LIBM, [
+AC_CHECK_LIB(mw, _mwvalidcheckl)
+AC_CHECK_LIB(m, cos)
+])
+
+# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl convenience library, adds --enable-ltdl-convenience to
+# the configure arguments.  Note that LIBLTDL is not AC_SUBSTed, nor
+# is AC_CONFIG_SUBDIRS called.  If DIR is not provided, it is assumed
+# to be `${top_builddir}/libltdl'.  Make sure you start DIR with
+# '${top_builddir}/' (note the single quotes!) if your package is not
+# flat, and, if you're not using automake, define top_builddir as
+# appropriate in the Makefiles.
+AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [
+  case "$enable_ltdl_convenience" in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
+])
+
+# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl installable library, and adds --enable-ltdl-install to
+# the configure arguments.  Note that LIBLTDL is not AC_SUBSTed, nor
+# is AC_CONFIG_SUBDIRS called.  If DIR is not provided, it is assumed
+# to be `${top_builddir}/libltdl'.  Make sure you start DIR with
+# '${top_builddir}/' (note the single quotes!) if your package is not
+# flat, and, if you're not using automake, define top_builddir as
+# appropriate in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [
+  AC_CHECK_LIB(ltdl, main, LIBLTDL="-lltdl", [
+    case "$enable_ltdl_install" in
+    no) AC_MSG_WARN([libltdl not installed, but installation disabled]) ;;
+    "") enable_ltdl_install=yes
+        ac_configure_args="$ac_configure_args --enable-ltdl-install" ;;
+    esac
+  ])
+  if test x"$enable_ltdl_install" != x"no"; then
+    LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
+  fi
+])
+
+dnl old names
+AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl
+AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl
+AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl
+AC_DEFUN(AM_SYS_NM_PARSE, [indir([AC_SYS_NM_PARSE])])dnl
+AC_DEFUN(AM_SYS_SYMBOL_UNDERSCORE, [indir([AC_SYS_SYMBOL_UNDERSCORE])])dnl
+AC_DEFUN(AM_SYS_LIBTOOL_CYGWIN, [indir([AC_SYS_LIBTOOL_CYGWIN])])dnl
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated.  We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+  case " <<$>>CONFIG_HEADERS " in
+  *" <<$>>am_file "*<<)>>
+    echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+    ;;
+  esac
+  am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+
+dnl AM_PROG_LEX
+dnl Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT
+AC_DEFUN(AM_PROG_LEX,
+[missing_dir=ifelse([$1],,`cd $ac_aux_dir && pwd`,$1)
+AC_CHECK_PROGS(LEX, flex lex, "$missing_dir/missing flex")
+AC_PROG_LEX
+AC_DECL_YYTEXT])
+
+# This file is derived from `gettext.m4'.  The difference is that the
+# included macros assume Cygnus-style source and build trees.
+
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 3
+
+AC_DEFUN(CY_WITH_NLS,
+  [AC_MSG_CHECKING([whether NLS is requested])
+    dnl Default is enabled NLS
+    AC_ARG_ENABLE(nls,
+      [  --disable-nls           do not use Native Language Support],
+      USE_NLS=$enableval, USE_NLS=yes)
+    AC_MSG_RESULT($USE_NLS)
+    AC_SUBST(USE_NLS)
+
+    USE_INCLUDED_LIBINTL=no
+
+    dnl If we use NLS figure out what method
+    if test "$USE_NLS" = "yes"; then
+      AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if NLS is requested])
+      AC_MSG_CHECKING([whether included gettext is requested])
+      AC_ARG_WITH(included-gettext,
+        [  --with-included-gettext use the GNU gettext library included here],
+        nls_cv_force_use_gnu_gettext=$withval,
+        nls_cv_force_use_gnu_gettext=no)
+      AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+      nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+      if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+        dnl User does not insist on using GNU NLS library.  Figure out what
+        dnl to use.  If gettext or catgets are available (in this order) we
+        dnl use this.  Else we have to fall back to GNU NLS library.
+       dnl catgets is only used if permitted by option --with-catgets.
+       nls_cv_header_intl=
+       nls_cv_header_libgt=
+       CATOBJEXT=NONE
+
+       AC_CHECK_HEADER(libintl.h,
+         [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
+           [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
+              gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
+
+          if test "$gt_cv_func_gettext_libc" != "yes"; then
+            AC_CHECK_LIB(intl, bindtextdomain,
+              [AC_CACHE_CHECK([for gettext in libintl],
+                gt_cv_func_gettext_libintl,
+                [AC_TRY_LINK([], [return (int) gettext ("")],
+                gt_cv_func_gettext_libintl=yes,
+                gt_cv_func_gettext_libintl=no)])])
+          fi
+
+          if test "$gt_cv_func_gettext_libc" = "yes" \
+             || test "$gt_cv_func_gettext_libintl" = "yes"; then
+             AC_DEFINE(HAVE_GETTEXT, 1,
+                       [Define as 1 if you have gettext and don't want to use GNU gettext.])
+             AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+               [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+             if test "$MSGFMT" != "no"; then
+               AC_CHECK_FUNCS(dcgettext)
+               AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+               AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+                 [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+               AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+                              return _nl_msg_cat_cntr],
+                 [CATOBJEXT=.gmo
+                  DATADIRNAME=share],
+                 [CATOBJEXT=.mo
+                  DATADIRNAME=lib])
+               INSTOBJEXT=.mo
+             fi
+           fi
+       ])
+
+       dnl In the standard gettext, we would now check for catgets.
+        dnl However, we never want to use catgets for our releases.
+
+        if test "$CATOBJEXT" = "NONE"; then
+         dnl Neither gettext nor catgets in included in the C library.
+         dnl Fall back on GNU gettext library.
+         nls_cv_use_gnu_gettext=yes
+        fi
+      fi
+
+      if test "$nls_cv_use_gnu_gettext" = "yes"; then
+        dnl Mark actions used to generate GNU NLS library.
+        INTLOBJS="\$(GETTOBJS)"
+        AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+         [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
+        AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+        AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+         [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+        AC_SUBST(MSGFMT)
+       USE_INCLUDED_LIBINTL=yes
+        CATOBJEXT=.gmo
+        INSTOBJEXT=.mo
+        DATADIRNAME=share
+       INTLDEPS='$(top_builddir)/../intl/libintl.a'
+       INTLLIBS=$INTLDEPS
+       LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+        nls_cv_header_intl=libintl.h
+        nls_cv_header_libgt=libgettext.h
+      fi
+
+      dnl Test whether we really found GNU xgettext.
+      if test "$XGETTEXT" != ":"; then
+       dnl If it is no GNU xgettext we define it as : so that the
+       dnl Makefiles still can work.
+       if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+         : ;
+       else
+         AC_MSG_RESULT(
+           [found xgettext programs is not GNU xgettext; ignore it])
+         XGETTEXT=":"
+       fi
+      fi
+
+      # We need to process the po/ directory.
+      POSUB=po
+    else
+      DATADIRNAME=share
+      nls_cv_header_intl=libintl.h
+      nls_cv_header_libgt=libgettext.h
+    fi
+
+    # If this is used in GNU gettext we have to set USE_NLS to `yes'
+    # because some of the sources are only built for this goal.
+    if test "$PACKAGE" = gettext; then
+      USE_NLS=yes
+      USE_INCLUDED_LIBINTL=yes
+    fi
+
+    dnl These rules are solely for the distribution goal.  While doing this
+    dnl we only have to keep exactly one list of the available catalogs
+    dnl in configure.in.
+    for lang in $ALL_LINGUAS; do
+      GMOFILES="$GMOFILES $lang.gmo"
+      POFILES="$POFILES $lang.po"
+    done
+
+    dnl Make all variables we use known to autoconf.
+    AC_SUBST(USE_INCLUDED_LIBINTL)
+    AC_SUBST(CATALOGS)
+    AC_SUBST(CATOBJEXT)
+    AC_SUBST(DATADIRNAME)
+    AC_SUBST(GMOFILES)
+    AC_SUBST(INSTOBJEXT)
+    AC_SUBST(INTLDEPS)
+    AC_SUBST(INTLLIBS)
+    AC_SUBST(INTLOBJS)
+    AC_SUBST(POFILES)
+    AC_SUBST(POSUB)
+  ])
+
+AC_DEFUN(CY_GNU_GETTEXT,
+  [AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+   AC_REQUIRE([AC_PROG_CC])dnl
+   AC_REQUIRE([AC_PROG_RANLIB])dnl
+   AC_REQUIRE([AC_ISC_POSIX])dnl
+   AC_REQUIRE([AC_HEADER_STDC])dnl
+   AC_REQUIRE([AC_C_CONST])dnl
+   AC_REQUIRE([AC_C_INLINE])dnl
+   AC_REQUIRE([AC_TYPE_OFF_T])dnl
+   AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+   AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+   AC_REQUIRE([AC_FUNC_MMAP])dnl
+
+   AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h])
+   AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next])
+
+   if test "${ac_cv_func_stpcpy+set}" != "set"; then
+     AC_CHECK_FUNCS(stpcpy)
+   fi
+   if test "${ac_cv_func_stpcpy}" = "yes"; then
+     AC_DEFINE(HAVE_STPCPY, 1, [Define if you have the stpcpy function])
+   fi
+
+   AM_LC_MESSAGES
+   CY_WITH_NLS
+
+   if test "x$CATOBJEXT" != "x"; then
+     if test "x$ALL_LINGUAS" = "x"; then
+       LINGUAS=
+     else
+       AC_MSG_CHECKING(for catalogs to be installed)
+       NEW_LINGUAS=
+       for lang in ${LINGUAS=$ALL_LINGUAS}; do
+         case "$ALL_LINGUAS" in
+          *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+         esac
+       done
+       LINGUAS=$NEW_LINGUAS
+       AC_MSG_RESULT($LINGUAS)
+     fi
+
+     dnl Construct list of names of catalog files to be constructed.
+     if test -n "$LINGUAS"; then
+       for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+     fi
+   fi
+
+   dnl The reference to <locale.h> in the installed <libintl.h> file
+   dnl must be resolved because we cannot expect the users of this
+   dnl to define HAVE_LOCALE_H.
+   if test $ac_cv_header_locale_h = yes; then
+     INCLUDE_LOCALE_H="#include <locale.h>"
+   else
+     INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>.  Take care yourself.  */"
+   fi
+   AC_SUBST(INCLUDE_LOCALE_H)
+
+   dnl Determine which catalog format we have (if any is needed)
+   dnl For now we know about two different formats:
+   dnl   Linux libc-5 and the normal X/Open format
+   if test -f $srcdir/po2tbl.sed.in; then
+      if test "$CATOBJEXT" = ".cat"; then
+        AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
+
+        dnl Transform the SED scripts while copying because some dumb SEDs
+         dnl cannot handle comments.
+        sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed
+      fi
+      dnl po2tbl.sed is always needed.
+      sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+        $srcdir/po2tbl.sed.in > po2tbl.sed
+   fi
+
+   dnl In the intl/Makefile.in we have a special dependency which makes
+   dnl only sense for gettext.  We comment this out for non-gettext
+   dnl packages.
+   if test "$PACKAGE" = "gettext"; then
+     GT_NO="#NO#"
+     GT_YES=
+   else
+     GT_NO=
+     GT_YES="#YES#"
+   fi
+   AC_SUBST(GT_NO)
+   AC_SUBST(GT_YES)
+
+   MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs"
+   AC_SUBST(MKINSTALLDIRS)
+
+   dnl *** For now the libtool support in intl/Makefile is not for real.
+   l=
+   AC_SUBST(l)
+
+   dnl Generate list of files to be processed by xgettext which will
+   dnl be included in po/Makefile.  But only do this if the po directory
+   dnl exists in srcdir.
+   if test -d $srcdir/po; then
+      test -d po || mkdir po
+      if test "x$srcdir" != "x."; then
+        if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+           posrcprefix="$srcdir/"
+        else
+           posrcprefix="../$srcdir/"
+        fi
+      else
+        posrcprefix="../"
+      fi
+      rm -f po/POTFILES
+      sed -e "/^#/d" -e "/^\$/d" -e "s,.*,     $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+        < $srcdir/po/POTFILES.in > po/POTFILES
+   fi
+  ])
+
+# Search path for a program which passes the given test.
+# Ulrich Drepper <drepper@cygnus.com>, 1996.
+#
+# This file file be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl   TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN(AM_PATH_PROG_WITH_TEST,
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+  /*)
+  ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in ifelse([$5], , $PATH, [$5]); do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if [$3]; then
+       ac_cv_path_$1="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [  test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+  ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test -n "[$]$1"; then
+  AC_MSG_RESULT([$]$1)
+else
+  AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+AC_DEFUN(AM_LC_MESSAGES,
+  [if test $ac_cv_header_locale_h = yes; then
+    AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+      [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+       am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+    if test $am_cv_val_LC_MESSAGES = yes; then
+      AC_DEFINE(HAVE_LC_MESSAGES, 1,
+               [Define if your locale.h file contains LC_MESSAGES.])
+    fi
+  fi])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# serial 1
+
+AC_DEFUN(AM_MAINTAINER_MODE,
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode is disabled by default
+  AC_ARG_ENABLE(maintainer-mode,
+[  --enable-maintainer-mode enable make rules and dependencies not useful
+                          (and sometimes confusing) to the casual installer],
+      USE_MAINTAINER_MODE=$enableval,
+      USE_MAINTAINER_MODE=no)
+  AC_MSG_RESULT($USE_MAINTAINER_MODE)
+  AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes)
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST(MAINT)dnl
+]
+)
+
+# Define a conditional.
+
+AC_DEFUN(AM_CONDITIONAL,
+[AC_SUBST($1_TRUE)
+AC_SUBST($1_FALSE)
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi])
+
diff --git a/binutils/addr2line.1 b/binutils/addr2line.1
new file mode 100644 (file)
index 0000000..87ce103
--- /dev/null
@@ -0,0 +1,127 @@
+.\" Copyright (c) 1997 Free Software Foundation
+.\" See COPYING for conditions for redistribution
+.TH addr2line 1 "27 March 1997" "Cygnus Solutions" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+addr2line \- convert addresses into file names and line numbers
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B addr2line
+.RB "[\|" "\-b\ "\c
+.I bfdname\c
+.RB " | " "\-\-target="\c
+.I bfdname\c
+\&\|]
+.RB "[\|" \-C | \-\-demangle "\|]"
+.RB "[\|" "\-e\ "\c
+.I filename\c
+.RB " | " "\-\-exe="\c
+.I filename\c
+\&\|]
+.RB "[\|" \-f | \-\-functions "\|]"
+.RB "[\|" \-s | \-\-basenames "\|]"
+.RB "[\|" \-H | \-\-help "\|]"
+.RB "[\|" \-V | \-\-version "\|]"
+.RB "[\|" addr addr ...  "\|]"
+.ad b
+.hy 1
+.SH DESCRIPTION
+\c
+.B addr2line
+translates program addresses into file names and line numbers.  Given
+an address and an executable, it uses the debugging information in the
+executable to figure out which file name and line number are
+associated with a given address.
+
+The executable to use is specified with the
+.B \-e
+option.  The default is
+.B a.out\c
+\&.
+
+.B addr2line
+has two modes of operation.
+
+In the first, hexadecimal addresses are specified on the command line,
+and
+.B addr2line
+displays the file name and line number for each address.
+
+In the second,
+.B addr2line
+reads hexadecimal addresses from standard input, and prints the file
+name and line number for each address on standard output.  In this
+mode,
+.B addr2line
+may be used in a pipe to convert dynamically chosen addresses.
+
+The format of the output is FILENAME:LINENO.  The file name and line
+number for each address is printed on a separate line.  If the
+.B \-f
+option is used, then each FILENAME:LINENO line is preceded by a
+FUNCTIONNAME line which is the name of the function containing the
+address.
+
+If the file name or function name can not be determined,
+.B addr2line
+will print two question marks in their place.  If the line number can
+not be determined,
+.B addr2line
+will print 0.
+
+.SH OPTIONS
+.TP
+.BI "\-b " "bfdname"\c
+.TP
+.BI "\-\-target=" "bfdname"
+Specify the object-code format for the object files to be
+\c
+.I bfdname\c
+\&.
+
+.TP
+.B \-C
+.TP
+.B \-\-demangle
+Decode (\fIdemangle\fP) low-level symbol names into user-level names.
+Besides removing any initial underscore prepended by the system, this
+makes C++ function names readable.
+
+.TP
+.BI "\-e " "filename"\c
+.TP
+.BI "\-\-exe=" "filename"
+Specify the name of the executable for which addresses should be
+translated.  The default file is
+.B a.out\c
+\&.
+
+.TP
+.B \-f
+.TP
+.B \-\-functions
+Display function names as well as file and line number information.
+
+.TP
+.B \-s
+.TP
+.B \-\-basenames
+Display only the base of each file name.
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'"
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (October 1991).
diff --git a/binutils/addr2line.c b/binutils/addr2line.c
new file mode 100644 (file)
index 0000000..3cee867
--- /dev/null
@@ -0,0 +1,335 @@
+/* addr2line.c -- convert addresses to line number and function name
+   Copyright 1997, 1998, 1999 Free Software Foundation, Inc.
+   Contributed by Ulrich Lauther <Ulrich.Lauther@zfe.siemens.de>
+
+   This file is part of 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 2, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Derived from objdump.c and nm.c by Ulrich.Lauther@zfe.siemens.de
+
+   Usage: 
+   addr2line [options] addr addr ...
+   or
+   addr2line [options] 
+
+   both forms write results to stdout, the second form reads addresses
+   to be converted from stdin.  */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "bfd.h"
+#include "getopt.h"
+#include "libiberty.h"
+#include "demangle.h"
+#include "bucomm.h"
+
+extern char *program_version;
+
+static boolean with_functions; /* -f, show function names.  */
+static boolean do_demangle;    /* -C, demangle names.  */
+static boolean base_names;     /* -s, strip directory names.  */
+
+static int naddr;              /* Number of addresses to process.  */
+static char **addr;            /* Hex addresses to process.  */
+
+static asymbol **syms;         /* Symbol table.  */
+
+static struct option long_options[] =
+{
+  {"basenames", no_argument, NULL, 's'},
+  {"demangle", no_argument, NULL, 'C'},
+  {"exe", required_argument, NULL, 'e'},
+  {"functions", no_argument, NULL, 'f'},
+  {"target", required_argument, NULL, 'b'},
+  {"help", no_argument, NULL, 'H'},
+  {"version", no_argument, NULL, 'V'},
+  {0, no_argument, 0, 0}
+};
+
+static void usage PARAMS ((FILE *, int));
+static void slurp_symtab PARAMS ((bfd *));
+static void find_address_in_section PARAMS ((bfd *, asection *, PTR));
+static void translate_addresses PARAMS ((bfd *));
+static void process_file PARAMS ((const char *, const char *));
+\f
+/* Print a usage message to STREAM and exit with STATUS.  */
+
+static void
+usage (stream, status)
+     FILE *stream;
+     int status;
+{
+  fprintf (stream, _("\
+Usage: %s [-CfsHV] [-b bfdname] [--target=bfdname]\n\
+       [-e executable] [--exe=executable] [--demangle]\n\
+       [--basenames] [--functions] [addr addr ...]\n"),
+          program_name);
+  list_supported_targets (program_name, stream);
+  if (status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (status);
+}
+\f
+/* Read in the symbol table.  */
+
+static void
+slurp_symtab (abfd)
+     bfd *abfd;
+{
+  long storage;
+  long symcount;
+
+  if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0)
+    return;
+
+  storage = bfd_get_symtab_upper_bound (abfd);
+  if (storage < 0)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  syms = (asymbol **) xmalloc (storage);
+
+  symcount = bfd_canonicalize_symtab (abfd, syms);
+  if (symcount < 0)
+    bfd_fatal (bfd_get_filename (abfd));
+}
+\f
+/* These global variables are used to pass information between
+   translate_addresses and find_address_in_section.  */
+
+static bfd_vma pc;
+static const char *filename;
+static const char *functionname;
+static unsigned int line;
+static boolean found;
+
+/* Look for an address in a section.  This is called via
+   bfd_map_over_sections.  */
+
+static void
+find_address_in_section (abfd, section, data)
+     bfd *abfd;
+     asection *section;
+     PTR data;
+{
+  bfd_vma vma;
+  bfd_size_type size;
+
+  if (found)
+    return;
+
+  if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
+    return;
+
+  vma = bfd_get_section_vma (abfd, section);
+  if (pc < vma)
+    return;
+
+  size = bfd_get_section_size_before_reloc (section);
+  if (pc >= vma + size)
+    return;
+
+  found = bfd_find_nearest_line (abfd, section, syms, pc - vma,
+                                &filename, &functionname, &line);
+}
+
+/* Read hexadecimal addresses from stdin, translate into
+   file_name:line_number and optionally function name.  */
+
+static void
+translate_addresses (abfd)
+     bfd *abfd;
+{
+  int read_stdin = (naddr == 0);
+
+  for (;;)
+    {
+      if (read_stdin)
+       {
+         char addr_hex[100];
+
+         if (fgets (addr_hex, sizeof addr_hex, stdin) == NULL)
+           break;
+         pc = bfd_scan_vma (addr_hex, NULL, 16);
+       }
+      else
+       {
+         if (naddr <= 0)
+           break;
+         --naddr;
+         pc = bfd_scan_vma (*addr++, NULL, 16);
+       }
+
+      found = false;
+      bfd_map_over_sections (abfd, find_address_in_section, (PTR) NULL);
+
+      if (! found)
+       {
+         if (with_functions)
+           printf ("??\n");
+         printf ("??:0\n");
+       }
+      else
+       {
+         if (with_functions)
+           {
+             if (functionname == NULL || *functionname == '\0')
+               printf ("??\n");
+             else if (! do_demangle)
+               printf ("%s\n", functionname);
+             else
+               {
+                 char *res;
+
+                 res = cplus_demangle (functionname, DMGL_ANSI | DMGL_PARAMS);
+                 if (res == NULL)
+                   printf ("%s\n", functionname);
+                 else
+                   {
+                     printf ("%s\n", res);
+                     free (res);
+                   }
+               }
+           }
+
+         if (base_names && filename != NULL)
+           {
+             char *h;
+
+             h = strrchr (filename, '/');
+             if (h != NULL)
+               filename = h + 1;
+           }
+
+         printf ("%s:%u\n", filename ? filename : "??", line);
+       }
+
+      /* fflush() is essential for using this command as a server
+         child process that reads addresses from a pipe and responds
+         with line number information, processing one address at a
+         time.  */
+      fflush (stdout);
+    }
+}
+
+/* Process a file.  */
+
+static void
+process_file (filename, target)
+     const char *filename;
+     const char *target;
+{
+  bfd *abfd;
+  char **matching;
+
+  abfd = bfd_openr (filename, target);
+  if (abfd == NULL)
+    bfd_fatal (filename);
+
+  if (bfd_check_format (abfd, bfd_archive))
+    fatal (_("%s: can not get addresses from archive"), filename);
+
+  if (! bfd_check_format_matches (abfd, bfd_object, &matching))
+    {
+      bfd_nonfatal (bfd_get_filename (abfd));
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      xexit (1);
+    }
+
+  slurp_symtab (abfd);
+
+  translate_addresses (abfd);
+
+  if (syms != NULL)
+    {
+      free (syms);
+      syms = NULL;
+    }
+
+  bfd_close (abfd);
+}
+\f
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *filename;
+  char *target;
+  int c;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = *argv;
+  xmalloc_set_program_name (program_name);
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  filename = NULL;
+  target = NULL;
+  while ((c = getopt_long (argc, argv, "b:Ce:sfHV", long_options, (int *) 0))
+        != EOF)
+    {
+      switch (c)
+       {
+       case 0:
+         break;                /* we've been given a long option */
+       case 'b':
+         target = optarg;
+         break;
+       case 'C':
+         do_demangle = true;
+         break;
+       case 'e':
+         filename = optarg;
+         break;
+       case 's':
+         base_names = true;
+         break;
+       case 'f':
+         with_functions = true;
+         break;
+       case 'V':
+         print_version ("addr2line");
+         break;
+       case 'H':
+         usage (stdout, 0);
+         break;
+       default:
+         usage (stderr, 1);
+         break;
+       }
+    }
+
+  if (filename == NULL)
+    filename = "a.out";
+
+  addr = argv + optind;
+  naddr = argc - optind;
+
+  process_file (filename, target);
+
+  return 0;
+}
diff --git a/binutils/ar.1 b/binutils/ar.1
new file mode 100644 (file)
index 0000000..e4e8cff
--- /dev/null
@@ -0,0 +1,509 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH ar 1 "5 November 1991" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+ar \- create, modify, and extract from archives.
+
+.SH SYNOPSIS
+.hy 0
+.na
+.BR ar " [\|" "-" "\|]"\c
+.I {dmpqrtx}[abcilosSuvV] \c
+[\|\c
+.I membername\c
+\&\|] \c
+.I archive\c
+\& \c
+.I files\c
+\&.\|.\|.
+
+.ad b
+.hy 1
+.SH DESCRIPTION
+The GNU \c
+.B ar\c
+\& program creates, modifies, and extracts from
+archives.  An \c
+.I archive\c
+\& is a single file holding a collection of
+other files in a structure that makes it possible to retrieve
+the original individual files (called \c
+.I members\c
+\& of the archive).
+
+The original files' contents, mode (permissions), timestamp, owner, and
+group are preserved in the archive, and may be reconstituted on
+extraction.  
+
+GNU \c
+.B ar\c
+\& can maintain archives whose members have names of any
+length; however, depending on how \c
+.B ar\c
+\& is configured on your
+system, a limit on member-name length may be imposed (for compatibility
+with archive formats maintained with other tools).  If it exists, the
+limit is often 15 characters (typical of formats related to a.out) or 16
+characters (typical of formats related to coff).
+
+\c
+.B ar\c
+\& is considered a binary utility because archives of this sort
+are most often used as \c
+.I libraries\c
+\& holding commonly needed
+subroutines.
+
+\c
+.B ar\c
+\& will create an index to the symbols defined in relocatable
+object modules in the archive when you specify the modifier `\|\c
+.B s\c
+\|'.
+Once created, this index is updated in the archive whenever \c
+.B ar\c
+\&
+makes a change to its contents (save for the `\|\c
+.B q\c
+\|' update operation).
+An archive with such an index speeds up linking to the library, and
+allows routines in the library to call each other without regard to
+their placement in the archive.
+
+You may use `\|\c
+.B nm \-s\c
+\|' or `\|\c
+.B nm \-\-print\-armap\c
+\|' to list this index
+table.  If an archive lacks the table, another form of \c
+.B ar\c
+\& called
+\c
+.B ranlib\c
+\& can be used to add just the table.
+
+\c
+.B ar\c
+\& insists on at least two arguments to execute: one
+keyletter specifying the \c
+.I operation\c
+\& (optionally accompanied by other
+keyletters specifying \c
+.I modifiers\c
+\&), and the archive name to act on.
+
+Most operations can also accept further \c
+.I files\c
+\& arguments,
+specifying particular files to operate on.
+
+.SH OPTIONS
+GNU \c
+.B ar\c
+\& allows you to mix the operation code \c
+.I p\c
+\& and modifier
+flags \c
+.I mod\c
+\& in any order, within the first command-line argument.
+
+If you wish, you may begin the first command-line argument with a
+dash.
+
+The \c
+.I p\c
+\& keyletter specifies what operation to execute; it may be
+any of the following, but you must specify only one of them:
+
+.TP
+.B d
+\c
+.I Delete\c
+\& modules from the archive.  Specify the names of modules to
+be deleted as \c
+.I files\c
+\&; the archive is untouched if you
+specify no files to delete.
+
+If you specify the `\|\c
+.B v\c
+\|' modifier, \c
+.B ar\c
+\& will list each module
+as it is deleted.
+
+.TP
+.B m
+Use this operation to \c
+.I move\c
+\& members in an archive.
+
+The ordering of members in an archive can make a difference in how
+programs are linked using the library, if a symbol is defined in more
+than one member.  
+
+If no modifiers are used with \c
+.B m\c
+\&, any members you name in the
+\c
+.I files\c
+\& arguments are moved to the \c
+.I end\c
+\& of the archive;
+you can use the `\|\c
+.B a\c
+\|', `\|\c
+.B b\c
+\|', or `\|\c
+.B i\c
+\|' modifiers to move them to a
+specified place instead.
+
+.TP
+.B p
+\c
+.I Print\c
+\& the specified members of the archive, to the standard
+output file.  If the `\|\c
+.B v\c
+\|' modifier is specified, show the member
+name before copying its contents to standard output.
+
+If you specify no \c
+.I files\c
+\&, all the files in the archive are printed.
+
+.TP
+.B q
+\c
+.I Quick append\c
+\&; add \c
+.I files\c
+\& to the end of \c
+.I archive\c
+\&,
+without checking for replacement.  
+
+The modifiers `\|\c
+.B a\c
+\|', `\|\c
+.B b\c
+\|', and `\|\c
+.B i\c
+\|' do \c
+.I not\c
+\& affect this
+operation; new members are always placed at the end of the archive.
+
+The modifier `\|\c
+.B v\c
+\|' makes \c
+.B ar\c
+\& list each file as it is appended.
+
+Since the point of this operation is speed, the archive's symbol table
+index is not updated, even if it already existed; you can use `\|\c
+.B ar s\c
+\|' or
+\c
+.B ranlib\c
+\& explicitly to update the symbol table index.
+
+However, too many different systems assume quick append rebuilds the
+index, so GNU
+.B ar
+implements `\|\c
+.B q\c
+\|' as a synonym for `\|\c
+.B r\c
+\|'.
+
+.TP
+.B r
+Insert \c
+.I files\c
+\& into \c
+.I archive\c
+\& (with \c
+.I replacement\c
+\&). This
+operation differs from `\|\c
+.B q\c
+\|' in that any previously existing members
+are deleted if their names match those being added.
+
+If one of the files named in \c
+.I files\c
+\& doesn't exist, \c
+.B ar\c
+\&
+displays an error message, and leaves undisturbed any existing members
+of the archive matching that name.
+
+By default, new members are added at the end of the file; but you may
+use one of the modifiers `\|\c
+.B a\c
+\|', `\|\c
+.B b\c
+\|', or `\|\c
+.B i\c
+\|' to request
+placement relative to some existing member.
+
+The modifier `\|\c
+.B v\c
+\|' used with this operation elicits a line of
+output for each file inserted, along with one of the letters `\|\c
+.B a\c
+\|' or
+`\|\c
+.B r\c
+\|' to indicate whether the file was appended (no old member
+deleted) or replaced.
+
+.TP
+.B t
+Display a \c
+.I table\c
+\& listing the contents of \c
+.I archive\c
+\&, or those
+of the files listed in \c
+.I files\c
+\& that are present in the
+archive.  Normally only the member name is shown; if you also want to
+see the modes (permissions), timestamp, owner, group, and size, you can
+request that by also specifying the `\|\c
+.B v\c
+\|' modifier.
+
+If you do not specify any \c
+.I files\c
+\&, all files in the archive
+are listed.
+
+If there is more than one file with the same name (say, `\|\c
+.B fie\c
+\|') in
+an archive (say `\|\c
+.B b.a\c
+\|'), `\|\c
+.B ar t b.a fie\c
+\|' will list only the
+first instance; to see them all, you must ask for a complete
+listing\(em\&in our example, `\|\c
+.B ar t b.a\c
+\|'.
+
+.TP
+.B x
+\c
+.I Extract\c
+\& members (named \c
+.I files\c
+\&) from the archive.  You can
+use the `\|\c
+.B v\c
+\|' modifier with this operation, to request that
+\c
+.B ar\c
+\& list each name as it extracts it.
+
+If you do not specify any \c
+.I files\c
+\&, all files in the archive
+are extracted.
+
+.PP
+
+A number of modifiers (\c
+.I mod\c
+\&) may immediately follow the \c
+.I p\c
+\&
+keyletter, to specify variations on an operation's behavior:
+
+.TP
+.B a
+Add new files \c
+.I after\c
+\& an existing member of the
+archive.  If you use the modifier \c
+.B a\c
+\&, the name of an existing archive
+member must be present as the \c
+.I membername\c
+\& argument, before the
+\c
+.I archive\c
+\& specification.
+
+.TP
+.B b
+Add new files \c
+.I before\c
+\& an existing member of the
+archive.  If you use the modifier \c
+.B b\c
+\&, the name of an existing archive
+member must be present as the \c
+.I membername\c
+\& argument, before the
+\c
+.I archive\c
+\& specification.  (same as `\|\c
+.B i\c
+\|').
+
+.TP
+.B c
+\c
+.I Create\c
+\& the archive.  The specified \c
+.I archive\c
+\& is always
+created if it didn't exist, when you request an update.  But a warning is
+issued unless you specify in advance that you expect to create it, by
+using this modifier.
+
+.TP
+.B f
+Truncate names in the archive.  
+.B ar
+will normally permit file names of any length.  This will cause it to
+create archives which are not compatible with the native 
+.B ar
+program on some systems.  If this is a concern, the 
+.B f
+modifier may be used to truncate file names when putting them in the
+archive.
+
+.TP
+.B i
+Insert new files \c
+.I before\c
+\& an existing member of the
+archive.  If you use the modifier \c
+.B i\c
+\&, the name of an existing archive
+member must be present as the \c
+.I membername\c
+\& argument, before the
+\c
+.I archive\c
+\& specification.  (same as `\|\c
+.B b\c
+\|').
+
+.TP
+.B l
+This modifier is accepted but not used.
+
+.TP
+.B o
+Preserve the \c
+.I original\c
+\& dates of members when extracting them.  If
+you do not specify this modifier, files extracted from the archive
+will be stamped with the time of extraction.
+
+.TP
+.B s
+Write an object-file index into the archive, or update an existing one,
+even if no other change is made to the archive.  You may use this modifier
+flag either with any operation, or alone.  Running `\|\c
+.B ar s\c
+\|' on an
+archive is equivalent to running `\|\c
+.B ranlib\c
+\|' on it.
+
+.TP
+.B S
+Do not generate an archive symbol table.  This can speed up building a
+large library in several steps.  The resulting archive can not be used
+with the linker.  In order to build a symbol table, you must omit the
+`\|\c
+.B S\c
+\|' modifier on the last execution of `\|\c
+.B ar\c
+\|', or you must run `\|\c
+.B ranlib\c
+\|' on the archive.
+
+.TP
+.B u
+Normally, \c
+.B ar r\c
+\&.\|.\|. inserts all files
+listed into the archive.  If you would like to insert \c
+.I only\c
+\& those
+of the files you list that are newer than existing members of the same
+names, use this modifier.  The `\|\c
+.B u\c
+\|' modifier is allowed only for the
+operation `\|\c
+.B r\c
+\|' (replace).  In particular, the combination `\|\c
+.B qu\c
+\|' is
+not allowed, since checking the timestamps would lose any speed
+advantage from the operation `\|\c
+.B q\c
+\|'.
+
+.TP
+.B v
+This modifier requests the \c
+.I verbose\c
+\& version of an operation.  Many
+operations display additional information, such as filenames processed,
+when the modifier `\|\c
+.B v\c
+\|' is appended.
+
+.TP
+.B V
+This modifier shows the version number of
+.BR ar .
+
+.PP
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'"
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+, Roland H. Pesch (October 1991).
+.BR nm ( 1 )\c
+\&,
+.BR ranlib ( 1 )\c
+\&.
+
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/ar.c b/binutils/ar.c
new file mode 100644 (file)
index 0000000..c951ef7
--- /dev/null
@@ -0,0 +1,1338 @@
+/* ar.c - Archive modify and extract.
+   Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+\f
+/*
+   Bugs: should use getopt the way tar does (complete w/optional -) and
+   should have long options too. GNU ar used to check file against filesystem
+   in quick_update and replace operations (would check mtime). Doesn't warn
+   when name truncated. No way to specify pos_end. Error messages should be
+   more consistant.
+*/
+#include "bfd.h"
+#include "libiberty.h"
+#include "progress.h"
+#include "bucomm.h"
+#include "aout/ar.h"
+#include "libbfd.h"
+#include "arsup.h"
+#include <sys/stat.h>
+
+#ifdef __GO32___
+#define EXT_NAME_LEN 3         /* bufflen of addition to name if it's MS-DOS */
+#else
+#define EXT_NAME_LEN 6         /* ditto for *NIX */
+#endif
+
+#define BUFSIZE 8192
+
+/* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
+
+struct ar_hdr *
+  bfd_special_undocumented_glue PARAMS ((bfd * abfd, const char *filename));
+
+/* Static declarations */
+
+static void
+mri_emul PARAMS ((void));
+
+static const char *
+normalize PARAMS ((const char *, bfd *));
+
+static void
+remove_output PARAMS ((void));
+
+static void
+map_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int));
+
+static void
+print_contents PARAMS ((bfd * member));
+
+static void
+delete_members PARAMS ((bfd *, char **files_to_delete));
+
+#if 0
+static void
+do_quick_append PARAMS ((const char *archive_filename,
+                        char **files_to_append));
+#endif
+
+static void
+move_members PARAMS ((bfd *, char **files_to_move));
+
+static void
+replace_members PARAMS ((bfd *, char **files_to_replace, boolean quick));
+
+static void
+print_descr PARAMS ((bfd * abfd));
+
+static void
+write_archive PARAMS ((bfd *));
+
+static void
+ranlib_only PARAMS ((const char *archname));
+
+static void
+ranlib_touch PARAMS ((const char *archname));
+
+static void
+usage PARAMS ((int));
+\f
+/** Globals and flags */
+
+int mri_mode;
+
+/* This flag distinguishes between ar and ranlib:
+   1 means this is 'ranlib'; 0 means this is 'ar'.
+   -1 means if we should use argv[0] to decide.  */
+extern int is_ranlib;
+
+/* Nonzero means don't warn about creating the archive file if necessary.  */
+int silent_create = 0;
+
+/* Nonzero means describe each action performed.  */
+int verbose = 0;
+
+/* Nonzero means preserve dates of members when extracting them.  */
+int preserve_dates = 0;
+
+/* Nonzero means don't replace existing members whose dates are more recent
+   than the corresponding files.  */
+int newer_only = 0;
+
+/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
+   member).  -1 means we've been explicitly asked to not write a symbol table;
+   +1 means we've been explictly asked to write it;
+   0 is the default.
+   Traditionally, the default in BSD has been to not write the table.
+   However, for POSIX.2 compliance the default is now to write a symbol table
+   if any of the members are object files.  */
+int write_armap = 0;
+
+/* Nonzero means it's the name of an existing member; position new or moved
+   files with respect to this one.  */
+char *posname = NULL;
+
+/* Sez how to use `posname': pos_before means position before that member.
+   pos_after means position after that member. pos_end means always at end.
+   pos_default means default appropriately. For the latter two, `posname'
+   should also be zero.  */
+enum pos
+  {
+    pos_default, pos_before, pos_after, pos_end
+  } postype = pos_default;
+
+static bfd **
+get_pos_bfd PARAMS ((bfd **, enum pos, const char *));
+
+/* Whether to truncate names of files stored in the archive.  */
+static boolean ar_truncate = false;
+
+int interactive = 0;
+
+static void
+mri_emul ()
+{
+  interactive = isatty (fileno (stdin));
+  yyparse ();
+}
+
+/* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
+   COUNT is the length of the FILES chain; FUNCTION is called on each entry
+   whose name matches one in FILES.  */
+
+static void
+map_over_members (arch, function, files, count)
+     bfd *arch;
+     void (*function) PARAMS ((bfd *));
+     char **files;
+     int count;
+{
+  bfd *head;
+
+  if (count == 0)
+    {
+      for (head = arch->next; head; head = head->next)
+       {
+         PROGRESS (1);
+         function (head);
+       }
+      return;
+    }
+  /* This may appear to be a baroque way of accomplishing what we want.
+     However we have to iterate over the filenames in order to notice where
+     a filename is requested but does not exist in the archive.  Ditto
+     mapping over each file each time -- we want to hack multiple
+     references.  */
+
+  for (; count > 0; files++, count--)
+    {
+      boolean found = false;
+
+      for (head = arch->next; head; head = head->next)
+       {
+         PROGRESS (1);
+         if (head->filename == NULL)
+           {
+             /* Some archive formats don't get the filenames filled in
+                until the elements are opened.  */
+             struct stat buf;
+             bfd_stat_arch_elt (head, &buf);
+           }
+         if ((head->filename != NULL) &&
+             (!strcmp (*files, head->filename)))
+           {
+             found = true;
+             function (head);
+           }
+       }
+      if (!found)
+       /* xgettext:c-format */
+       fprintf (stderr, _("no entry %s in archive\n"), *files);
+    }
+}
+\f
+boolean operation_alters_arch = false;
+
+static void
+usage (help)
+     int help;
+{
+  FILE *s;
+
+  s = help ? stdout : stderr;
+  
+  if (! is_ranlib)
+    {
+      /* xgettext:c-format */
+      fprintf (s, _("Usage: %s [-]{dmpqrstx}[abcilosSuvV] [member-name] archive-file file...\n"), program_name);
+      /* xgettext:c-format */
+      fprintf (s, _("       %s -M [<mri-script]\n"), program_name);
+      fprintf (s, _(" commands:\n"));
+      fprintf (s, _("  d            - delete file(s) from the archive\n"));
+      fprintf (s, _("  m[ab]        - move file(s) in the archive\n"));
+      fprintf (s, _("  p            - print file(s) found in the archive\n"));
+      fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
+      fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
+      fprintf (s, _("  t            - display contents of archive\n"));
+      fprintf (s, _("  x[o]         - extract file(s) from the archive\n"));
+      fprintf (s, _(" command specific modifiers:\n"));
+      fprintf (s, _("  [a]          - put file(s) after [member-name]\n"));
+      fprintf (s, _("  [b]          - put file(s) before [member-name] (same as [i])\n"));
+      fprintf (s, _("  [f]          - truncate inserted file names\n"));
+      fprintf (s, _("  [o]          - preserve original dates\n"));
+      fprintf (s, _("  [u]          - only replace files that are newer than current archive contents\n"));
+      fprintf (s, _(" generic modifiers:\n"));
+      fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
+      fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
+      fprintf (s, _("  [S]          - do not build a symbol table\n"));
+      fprintf (s, _("  [v]          - be verbose\n"));
+      fprintf (s, _("  [V]          - display the version number\n"));
+    }
+  else
+    /* xgettext:c-format */
+    fprintf (s, _("Usage: %s [-vV] archive\n"), program_name);
+
+  list_supported_targets (program_name, stderr);
+
+  if (help)
+    fprintf (s, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+
+  xexit (help ? 0 : 1);
+}
+
+/* Normalize a file name specified on the command line into a file
+   name which we will use in an archive.  */
+
+static const char *
+normalize (file, abfd)
+     const char *file;
+     bfd *abfd;
+{
+  const char *filename;
+
+  filename = strrchr (file, '/');
+  if (filename != (char *) NULL)
+    filename++;
+  else
+    filename = file;
+
+  if (ar_truncate
+      && abfd != NULL
+      && strlen (filename) > abfd->xvec->ar_max_namelen)
+    {
+      char *s;
+
+      /* Space leak.  */
+      s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
+      memcpy (s, filename, abfd->xvec->ar_max_namelen);
+      s[abfd->xvec->ar_max_namelen] = '\0';
+      filename = s;
+    }
+
+  return filename;
+}
+
+/* Remove any output file.  This is only called via xatexit.  */
+
+static char *output_filename = NULL;
+static FILE *output_file = NULL;
+static bfd *output_bfd = NULL;
+
+static void
+remove_output ()
+{
+  if (output_filename != NULL)
+    {
+      if (output_bfd != NULL && output_bfd->iostream != NULL)
+       fclose ((FILE *) (output_bfd->iostream));
+      if (output_file != NULL)
+       fclose (output_file);
+      unlink (output_filename);
+    }
+}
+
+/* The option parsing should be in its own function.
+   It will be when I have getopt working.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  char *arg_ptr;
+  char c;
+  enum
+    {
+      none = 0, delete, replace, print_table,
+      print_files, extract, move, quick_append
+    } operation = none;
+  int arg_index;
+  char **files;
+  char *inarch_filename;
+  int show_version;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = argv[0];
+  xmalloc_set_program_name (program_name);
+
+  if (is_ranlib < 0)
+    {
+      char *temp;
+
+      temp = strrchr (program_name, '/');
+      if (temp == NULL)
+       temp = program_name;
+      else
+       ++temp;
+      if (strlen (temp) >= 6
+         && strcmp (temp + strlen (temp) - 6, "ranlib") == 0)
+       is_ranlib = 1;
+      else
+       is_ranlib = 0;
+    }
+
+  if (argc > 1 && argv[1][0] == '-')
+    {
+      if (strcmp (argv[1], "--help") == 0)
+       usage (1);
+      else if (strcmp (argv[1], "--version") == 0)
+       {
+         if (is_ranlib)
+           print_version ("ranlib");
+         else
+           print_version ("ar");
+       }
+    }
+
+  START_PROGRESS (program_name, 0);
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  show_version = 0;
+
+  xatexit (remove_output);
+
+  if (is_ranlib)
+    {
+      boolean touch = false;
+
+      if (argc < 2 || strcmp (argv[1], "--help") == 0)
+       usage (0);
+      if (strcmp (argv[1], "-V") == 0
+         || strcmp (argv[1], "-v") == 0
+         || strncmp (argv[1], "--v", 3) == 0)
+       print_version ("ranlib");
+      arg_index = 1;
+      if (strcmp (argv[1], "-t") == 0)
+       {
+         ++arg_index;
+         touch = true;
+       }
+      while (arg_index < argc)
+       {
+         if (! touch)
+           ranlib_only (argv[arg_index]);
+         else
+           ranlib_touch (argv[arg_index]);
+         ++arg_index;
+       }
+      xexit (0);
+    }
+
+  if (argc == 2 && strcmp (argv[1], "-M") == 0)
+    {
+      mri_emul ();
+      xexit (0);
+    }
+
+  if (argc < 2)
+    usage (0);
+
+  arg_ptr = argv[1];
+
+  if (*arg_ptr == '-')
+    ++arg_ptr;                 /* compatibility */
+
+  while ((c = *arg_ptr++) != '\0')
+    {
+      switch (c)
+       {
+       case 'd':
+       case 'm':
+       case 'p':
+       case 'q':
+       case 'r':
+       case 't':
+       case 'x':
+         if (operation != none)
+           fatal (_("two different operation options specified"));
+         switch (c)
+           {
+           case 'd':
+             operation = delete;
+             operation_alters_arch = true;
+             break;
+           case 'm':
+             operation = move;
+             operation_alters_arch = true;
+             break;
+           case 'p':
+             operation = print_files;
+             break;
+           case 'q':
+             operation = quick_append;
+             operation_alters_arch = true;
+             break;
+           case 'r':
+             operation = replace;
+             operation_alters_arch = true;
+             break;
+           case 't':
+             operation = print_table;
+             break;
+           case 'x':
+             operation = extract;
+             break;
+           }
+       case 'l':
+         break;
+       case 'c':
+         silent_create = 1;
+         break;
+       case 'o':
+         preserve_dates = 1;
+         break;
+       case 'V':
+         show_version = true;
+         break;
+       case 's':
+         write_armap = 1;
+         break;
+       case 'S':
+         write_armap = -1;
+         break;
+       case 'u':
+         newer_only = 1;
+         break;
+       case 'v':
+         verbose = 1;
+         break;
+       case 'a':
+         postype = pos_after;
+         break;
+       case 'b':
+         postype = pos_before;
+         break;
+       case 'i':
+         postype = pos_before;
+         break;
+       case 'M':
+         mri_mode = 1;
+         break;
+       case 'f':
+         ar_truncate = true;
+         break;
+       default:
+         /* xgettext:c-format */
+         fprintf (stderr, _("%s: illegal option -- %c\n"), program_name, c);
+         usage (0);
+       }
+    }
+
+  if (show_version)
+    print_version ("ar");
+
+  if (argc < 3)
+    usage (0);
+
+  if (mri_mode)
+    {
+      mri_emul ();
+    }
+  else
+    {
+      bfd *arch;
+
+      /* We can't write an armap when using ar q, so just do ar r
+         instead.  */
+      if (operation == quick_append && write_armap)
+       operation = replace;
+
+      if ((operation == none || operation == print_table)
+         && write_armap == 1)
+       {
+         ranlib_only (argv[2]);
+         xexit (0);
+       }
+
+      if (operation == none)
+       fatal (_("no operation specified"));
+
+      if (newer_only && operation != replace)
+       fatal (_("`u' is only meaningful with the `r' option."));
+
+      arg_index = 2;
+
+      if (postype != pos_default)
+       posname = argv[arg_index++];
+
+      inarch_filename = argv[arg_index++];
+
+      files = arg_index < argc ? argv + arg_index : NULL;
+
+#if 0
+      /* We don't use do_quick_append any more.  Too many systems
+         expect ar to always rebuild the symbol table even when q is
+         used.  */
+
+      /* We can't do a quick append if we need to construct an
+        extended name table, because do_quick_append won't be able to
+        rebuild the name table.  Unfortunately, at this point we
+        don't actually know the maximum name length permitted by this
+        object file format.  So, we guess.  FIXME.  */
+      if (operation == quick_append && ! ar_truncate)
+       {
+         char **chk;
+
+         for (chk = files; chk != NULL && *chk != '\0'; chk++)
+           {
+             if (strlen (normalize (*chk, (bfd *) NULL)) > 14)
+               {
+                 operation = replace;
+                 break;
+               }
+           }
+       }
+
+      if (operation == quick_append)
+       {
+         /* Note that quick appending to a non-existent archive creates it,
+            even if there are no files to append. */
+         do_quick_append (inarch_filename, files);
+         xexit (0);
+       }
+#endif
+
+      arch = open_inarch (inarch_filename,
+                         files == NULL ? (char *) NULL : files[0]);
+
+      switch (operation)
+       {
+       case print_table:
+         map_over_members (arch, print_descr, files, argc - 3);
+         break;
+
+       case print_files:
+         map_over_members (arch, print_contents, files, argc - 3);
+         break;
+
+       case extract:
+         map_over_members (arch, extract_file, files, argc - 3);
+         break;
+
+       case delete:
+         if (files != NULL)
+           delete_members (arch, files);
+         break;
+
+       case move:
+         if (files != NULL)
+           move_members (arch, files);
+         break;
+
+       case replace:
+       case quick_append:
+         if (files != NULL || write_armap > 0)
+           replace_members (arch, files, operation == quick_append);
+         break;
+
+         /* Shouldn't happen! */
+       default:
+         /* xgettext:c-format */
+         fprintf (stderr, _("%s: internal error -- this option not implemented\n"),
+                  program_name);
+         xexit (1);
+       }
+    }
+
+  END_PROGRESS (program_name);
+
+  xexit (0);
+  return 0;
+}
+
+bfd *
+open_inarch (archive_filename, file)
+     const char *archive_filename;
+     const char *file;
+{
+  const char *target;
+  bfd **last_one;
+  bfd *next_one;
+  struct stat sbuf;
+  bfd *arch;
+  char **matching;
+
+  bfd_set_error (bfd_error_no_error);
+
+  target = NULL;
+
+  if (stat (archive_filename, &sbuf) != 0)
+    {
+#ifndef __GO32__
+
+/* KLUDGE ALERT! Temporary fix until I figger why
+ * stat() is wrong ... think it's buried in GO32's IDT
+ * - Jax
+ */
+      if (errno != ENOENT)
+       bfd_fatal (archive_filename);
+#endif
+
+      if (!operation_alters_arch)
+       {
+         fprintf (stderr, "%s: ", program_name);
+         perror (archive_filename);
+         maybequit ();
+         return NULL;
+       }
+
+      /* Try to figure out the target to use for the archive from the
+         first object on the list.  */
+      if (file != NULL)
+       {
+         bfd *obj;
+
+         obj = bfd_openr (file, NULL);
+         if (obj != NULL)
+           {
+             if (bfd_check_format (obj, bfd_object))
+               target = bfd_get_target (obj);
+             (void) bfd_close (obj);
+           }
+       }
+
+      /* Create an empty archive.  */
+      arch = bfd_openw (archive_filename, target);
+      if (arch == NULL
+         || ! bfd_set_format (arch, bfd_archive)
+         || ! bfd_close (arch))
+       bfd_fatal (archive_filename);
+    }
+
+  arch = bfd_openr (archive_filename, target);
+  if (arch == NULL)
+    {
+    bloser:
+      bfd_fatal (archive_filename);
+    }
+
+  if (! bfd_check_format_matches (arch, bfd_archive, &matching))
+    {
+      bfd_nonfatal (archive_filename);
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      xexit (1);
+    }
+
+  last_one = &(arch->next);
+  /* Read all the contents right away, regardless.  */
+  for (next_one = bfd_openr_next_archived_file (arch, NULL);
+       next_one;
+       next_one = bfd_openr_next_archived_file (arch, next_one))
+    {
+      PROGRESS (1);
+      *last_one = next_one;
+      last_one = &next_one->next;
+    }
+  *last_one = (bfd *) NULL;
+  if (bfd_get_error () != bfd_error_no_more_archived_files)
+    goto bloser;
+  return arch;
+}
+
+static void
+print_contents (abfd)
+     bfd *abfd;
+{
+  int ncopied = 0;
+  char *cbuf = xmalloc (BUFSIZE);
+  struct stat buf;
+  long size;
+  if (bfd_stat_arch_elt (abfd, &buf) != 0)
+    /* xgettext:c-format */
+    fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
+
+  if (verbose)
+    /* xgettext:c-format */
+    printf (_("\n<member %s>\n\n"), bfd_get_filename (abfd));
+
+  bfd_seek (abfd, 0, SEEK_SET);
+
+  size = buf.st_size;
+  while (ncopied < size)
+    {
+
+      int nread;
+      int tocopy = size - ncopied;
+      if (tocopy > BUFSIZE)
+       tocopy = BUFSIZE;
+
+      nread = bfd_read (cbuf, 1, tocopy, abfd);        /* oops -- broke
+                                                          abstraction!  */
+      if (nread != tocopy)
+       /* xgettext:c-format */
+       fatal (_("%s is not a valid archive"),
+              bfd_get_filename (bfd_my_archive (abfd)));
+      fwrite (cbuf, 1, nread, stdout);
+      ncopied += tocopy;
+    }
+  free (cbuf);
+}
+
+/* Extract a member of the archive into its own file.
+
+   We defer opening the new file until after we have read a BUFSIZ chunk of the
+   old one, since we know we have just read the archive header for the old
+   one.  Since most members are shorter than BUFSIZ, this means we will read
+   the old header, read the old data, write a new inode for the new file, and
+   write the new data, and be done. This 'optimization' is what comes from
+   sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
+   Gilmore  */
+
+void
+extract_file (abfd)
+     bfd *abfd;
+{
+  FILE *ostream;
+  char *cbuf = xmalloc (BUFSIZE);
+  int nread, tocopy;
+  long ncopied = 0;
+  long size;
+  struct stat buf;
+  
+  if (bfd_stat_arch_elt (abfd, &buf) != 0)
+    /* xgettext:c-format */
+    fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
+  size = buf.st_size;
+
+  if (size < 0)
+    /* xgettext:c-format */
+    fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd));
+  
+  if (verbose)
+    printf ("x - %s\n", bfd_get_filename (abfd));
+
+  bfd_seek (abfd, 0, SEEK_SET);
+
+  ostream = NULL;
+  if (size == 0)
+    {
+      /* Seems like an abstraction violation, eh?  Well it's OK! */
+      output_filename = bfd_get_filename (abfd);
+
+      ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
+      if (ostream == NULL)
+       {
+         perror (bfd_get_filename (abfd));
+         xexit (1);
+       }
+
+      output_file = ostream;
+    }
+  else
+    while (ncopied < size)
+      {
+       tocopy = size - ncopied;
+       if (tocopy > BUFSIZE)
+         tocopy = BUFSIZE;
+
+       nread = bfd_read (cbuf, 1, tocopy, abfd);
+       if (nread != tocopy)
+         /* xgettext:c-format */
+         fatal (_("%s is not a valid archive"),
+                bfd_get_filename (bfd_my_archive (abfd)));
+
+       /* See comment above; this saves disk arm motion */
+       if (ostream == NULL)
+         {
+           /* Seems like an abstraction violation, eh?  Well it's OK! */
+           output_filename = bfd_get_filename (abfd);
+
+           ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
+           if (ostream == NULL)
+             {
+               perror (bfd_get_filename (abfd));
+               xexit (1);
+             }
+
+           output_file = ostream;
+         }
+       fwrite (cbuf, 1, nread, ostream);
+       ncopied += tocopy;
+      }
+
+  if (ostream != NULL)
+    fclose (ostream);
+
+  output_file = NULL;
+  output_filename = NULL;
+
+  chmod (bfd_get_filename (abfd), buf.st_mode);
+
+  if (preserve_dates)
+    set_times (bfd_get_filename (abfd), &buf);
+
+  free (cbuf);
+}
+
+#if 0
+
+/* We don't use this anymore.  Too many systems expect ar to rebuild
+   the symbol table even when q is used.  */
+
+/* Just do it quickly; don't worry about dups, armap, or anything like that */
+
+static void
+do_quick_append (archive_filename, files_to_append)
+     const char *archive_filename;
+     char **files_to_append;
+{
+  FILE *ofile, *ifile;
+  char *buf = xmalloc (BUFSIZE);
+  long tocopy, thistime;
+  bfd *temp;
+  struct stat sbuf;
+  boolean newfile = false;
+  bfd_set_error (bfd_error_no_error);
+
+  if (stat (archive_filename, &sbuf) != 0)
+    {
+
+#ifndef __GO32__
+
+/* KLUDGE ALERT! Temporary fix until I figger why
+ * stat() is wrong ... think it's buried in GO32's IDT
+ * - Jax
+ */
+
+      if (errno != ENOENT)
+       bfd_fatal (archive_filename);
+#endif
+
+      newfile = true;
+    }
+
+  ofile = fopen (archive_filename, FOPEN_AUB);
+  if (ofile == NULL)
+    {
+      perror (program_name);
+      xexit (1);
+    }
+
+  temp = bfd_openr (archive_filename, NULL);
+  if (temp == NULL)
+    {
+      bfd_fatal (archive_filename);
+    }
+  if (newfile == false)
+    {
+      if (bfd_check_format (temp, bfd_archive) != true)
+       /* xgettext:c-format */
+       fatal (_("%s is not an archive"), archive_filename);
+    }
+  else
+    {
+      fwrite (ARMAG, 1, SARMAG, ofile);
+      if (!silent_create)
+       /* xgettext:c-format */
+       fprintf (stderr, _("%s: creating %s\n"),
+                program_name, archive_filename);
+    }
+
+  if (ar_truncate)
+    temp->flags |= BFD_TRADITIONAL_FORMAT;
+
+  /* assume it's an achive, go straight to the end, sans $200 */
+  fseek (ofile, 0, 2);
+
+  for (; files_to_append && *files_to_append; ++files_to_append)
+    {
+      struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
+      if (hdr == NULL)
+       {
+         bfd_fatal (*files_to_append);
+       }
+
+      BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
+
+      ifile = fopen (*files_to_append, FOPEN_RB);
+      if (ifile == NULL)
+       {
+         bfd_nonfatal (*files_to_append);
+       }
+
+      if (stat (*files_to_append, &sbuf) != 0)
+       {
+         bfd_nonfatal (*files_to_append);
+       }
+
+      tocopy = sbuf.st_size;
+
+      /* XXX should do error-checking! */
+      fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
+
+      while (tocopy > 0)
+       {
+         thistime = tocopy;
+         if (thistime > BUFSIZE)
+           thistime = BUFSIZE;
+         fread (buf, 1, thistime, ifile);
+         fwrite (buf, 1, thistime, ofile);
+         tocopy -= thistime;
+       }
+      fclose (ifile);
+      if ((sbuf.st_size % 2) == 1)
+       putc ('\012', ofile);
+    }
+  fclose (ofile);
+  bfd_close (temp);
+  free (buf);
+}
+
+#endif /* 0 */
+
+static void
+write_archive (iarch)
+     bfd *iarch;
+{
+  bfd *obfd;
+  char *old_name, *new_name;
+  bfd *contents_head = iarch->next;
+
+  old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
+  strcpy (old_name, bfd_get_filename (iarch));
+  new_name = make_tempname (old_name);
+
+  output_filename = new_name;
+
+  obfd = bfd_openw (new_name, bfd_get_target (iarch));
+
+  if (obfd == NULL)
+    bfd_fatal (old_name);
+
+  output_bfd = obfd;
+
+  bfd_set_format (obfd, bfd_archive);
+
+  /* Request writing the archive symbol table unless we've
+     been explicitly requested not to.  */
+  obfd->has_armap = write_armap >= 0;
+
+  if (ar_truncate)
+    {
+      /* This should really use bfd_set_file_flags, but that rejects
+         archives.  */
+      obfd->flags |= BFD_TRADITIONAL_FORMAT;
+    }
+
+  if (bfd_set_archive_head (obfd, contents_head) != true)
+    bfd_fatal (old_name);
+
+  if (!bfd_close (obfd))
+    bfd_fatal (old_name);
+
+  output_bfd = NULL;
+  output_filename = NULL;
+
+  /* We don't care if this fails; we might be creating the archive.  */
+  bfd_close (iarch);
+
+  if (smart_rename (new_name, old_name, 0) != 0)
+    xexit (1);
+}
+
+/* Return a pointer to the pointer to the entry which should be rplacd'd
+   into when altering.  DEFAULT_POS should be how to interpret pos_default,
+   and should be a pos value.  */
+
+static bfd **
+get_pos_bfd (contents, default_pos, default_posname)
+     bfd **contents;
+     enum pos default_pos;
+     const char *default_posname;
+{
+  bfd **after_bfd = contents;
+  enum pos realpos;
+  const char *realposname;
+
+  if (postype == pos_default)
+    {
+      realpos = default_pos;
+      realposname = default_posname;
+    }
+  else
+    {
+      realpos = postype;
+      realposname = posname;
+    }
+
+  if (realpos == pos_end)
+    {
+      while (*after_bfd)
+       after_bfd = &((*after_bfd)->next);
+    }
+  else
+    {
+      for (; *after_bfd; after_bfd = &(*after_bfd)->next)
+       if (strcmp ((*after_bfd)->filename, realposname) == 0)
+         {
+           if (realpos == pos_after)
+             after_bfd = &(*after_bfd)->next;
+           break;
+         }
+    }
+  return after_bfd;
+}
+
+static void
+delete_members (arch, files_to_delete)
+     bfd *arch;
+     char **files_to_delete;
+{
+  bfd **current_ptr_ptr;
+  boolean found;
+  boolean something_changed = false;
+  for (; *files_to_delete != NULL; ++files_to_delete)
+    {
+      /* In a.out systems, the armap is optional.  It's also called
+        __.SYMDEF.  So if the user asked to delete it, we should remember
+        that fact. This isn't quite right for COFF systems (where
+        __.SYMDEF might be regular member), but it's very unlikely
+        to be a problem.  FIXME */
+
+      if (!strcmp (*files_to_delete, "__.SYMDEF"))
+       {
+         arch->has_armap = false;
+         write_armap = -1;
+         continue;
+       }
+
+      found = false;
+      current_ptr_ptr = &(arch->next);
+      while (*current_ptr_ptr)
+       {
+         if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0)
+           {
+             found = true;
+             something_changed = true;
+             if (verbose)
+               printf ("d - %s\n",
+                       *files_to_delete);
+             *current_ptr_ptr = ((*current_ptr_ptr)->next);
+             goto next_file;
+           }
+         else
+           {
+             current_ptr_ptr = &((*current_ptr_ptr)->next);
+           }
+       }
+
+      if (verbose && found == false)
+       {
+         /* xgettext:c-format */
+         printf (_("No member named `%s'\n"), *files_to_delete);
+       }
+    next_file:
+      ;
+    }
+
+  if (something_changed == true)
+    {
+      write_archive (arch);
+    }
+}
+
+
+/* Reposition existing members within an archive */
+
+static void
+move_members (arch, files_to_move)
+     bfd *arch;
+     char **files_to_move;
+{
+  bfd **after_bfd;             /* New entries go after this one */
+  bfd **current_ptr_ptr;       /* cdr pointer into contents */
+
+  for (; *files_to_move; ++files_to_move)
+    {
+      current_ptr_ptr = &(arch->next);
+      while (*current_ptr_ptr)
+       {
+         bfd *current_ptr = *current_ptr_ptr;
+         if (strcmp (normalize (*files_to_move, arch),
+                     current_ptr->filename) == 0)
+           {
+             /* Move this file to the end of the list - first cut from
+                where it is.  */
+             bfd *link;
+             *current_ptr_ptr = current_ptr->next;
+
+             /* Now glue to end */
+             after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
+             link = *after_bfd;
+             *after_bfd = current_ptr;
+             current_ptr->next = link;
+
+             if (verbose)
+               printf ("m - %s\n", *files_to_move);
+
+             goto next_file;
+           }
+
+         current_ptr_ptr = &((*current_ptr_ptr)->next);
+       }
+      /* xgettext:c-format */
+      fprintf (stderr, _("%s: no entry %s in archive %s!\n"),
+              program_name, *files_to_move, arch->filename);
+      xexit (1);
+    next_file:;
+    }
+
+  write_archive (arch);
+}
+
+/* Ought to default to replacing in place, but this is existing practice!  */
+
+static void
+replace_members (arch, files_to_move, quick)
+     bfd *arch;
+     char **files_to_move;
+     boolean quick;
+{
+  boolean changed = false;
+  bfd **after_bfd;             /* New entries go after this one */
+  bfd *current;
+  bfd **current_ptr;
+  bfd *temp;
+
+  while (files_to_move && *files_to_move)
+    {
+      if (! quick)
+       {
+         current_ptr = &arch->next;
+         while (*current_ptr)
+           {
+             current = *current_ptr;
+
+             /* For compatibility with existing ar programs, we
+                permit the same file to be added multiple times.  */
+             if (strcmp (normalize (*files_to_move, arch),
+                         normalize (current->filename, arch)) == 0
+                 && current->arelt_data != NULL)
+               {
+                 if (newer_only)
+                   {
+                     struct stat fsbuf, asbuf;
+
+                     if (stat (*files_to_move, &fsbuf) != 0)
+                       {
+                         if (errno != ENOENT)
+                           bfd_fatal (*files_to_move);
+                         goto next_file;
+                       }
+                     if (bfd_stat_arch_elt (current, &asbuf) != 0)
+                       /* xgettext:c-format */
+                       fatal (_("internal stat error on %s"), current->filename);
+
+                     if (fsbuf.st_mtime <= asbuf.st_mtime)
+                       goto next_file;
+                   }
+
+                 after_bfd = get_pos_bfd (&arch->next, pos_after,
+                                          current->filename);
+                 temp = *after_bfd;
+
+                 *after_bfd = bfd_openr (*files_to_move, NULL);
+                 if (*after_bfd == (bfd *) NULL)
+                   {
+                     bfd_fatal (*files_to_move);
+                   }
+                 (*after_bfd)->next = temp;
+
+                 /* snip out this entry from the chain */
+                 *current_ptr = (*current_ptr)->next;
+
+                 if (verbose)
+                   {
+                     printf ("r - %s\n", *files_to_move);
+                   }
+
+                 changed = true;
+
+                 goto next_file;
+               }
+             current_ptr = &(current->next);
+           }
+       }
+
+      /* Add to the end of the archive.  */
+
+      after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
+      temp = *after_bfd;
+      *after_bfd = bfd_openr (*files_to_move, NULL);
+      if (*after_bfd == (bfd *) NULL)
+       {
+         bfd_fatal (*files_to_move);
+       }
+      if (verbose)
+       {
+         printf ("a - %s\n", *files_to_move);
+       }
+
+      (*after_bfd)->next = temp;
+
+      changed = true;
+
+    next_file:;
+
+      files_to_move++;
+    }
+
+  if (changed)
+    write_archive (arch);
+}
+
+static void
+ranlib_only (archname)
+     const char *archname;
+{
+  bfd *arch;
+
+  write_armap = 1;
+  arch = open_inarch (archname, (char *) NULL);
+  if (arch == NULL)
+    xexit (1);
+  write_archive (arch);
+}
+
+/* Update the timestamp of the symbol map of an archive.  */
+
+static void
+ranlib_touch (archname)
+     const char *archname;
+{
+#ifdef __GO32__
+  /* I don't think updating works on go32.  */
+  ranlib_only (archname);
+#else
+  int f;
+  bfd *arch;
+  char **matching;
+
+  f = open (archname, O_RDWR, 0);
+  if (f < 0)
+    {
+      bfd_set_error (bfd_error_system_call);
+      bfd_fatal (archname);
+    }
+
+  arch = bfd_fdopenr (archname, (const char *) NULL, f);
+  if (arch == NULL)
+    bfd_fatal (archname);
+  if (! bfd_check_format_matches (arch, bfd_archive, &matching))
+    {
+      bfd_nonfatal (archname);
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      xexit (1);
+    }
+
+  if (! bfd_has_map (arch))
+    /* xgettext:c-format */
+    fatal (_("%s: no archive map to update"), archname);
+
+  bfd_update_armap_timestamp (arch);
+
+  if (! bfd_close (arch))
+    bfd_fatal (archname);
+#endif
+}
+
+/* Things which are interesting to map over all or some of the files: */
+
+static void
+print_descr (abfd)
+     bfd *abfd;
+{
+  print_arelt_descr (stdout, abfd, verbose);
+}
diff --git a/binutils/arlex.l b/binutils/arlex.l
new file mode 100644 (file)
index 0000000..74e13d1
--- /dev/null
@@ -0,0 +1,83 @@
+%{
+/* arlex.l - Strange script language lexer */
+
+/*   Copyright (C) 1992, 95, 1997 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+/* Contributed by Steve Chamberlain
+                 sac@cygnus.com
+
+*/
+#define DONTDECLARE_MALLOC
+#include <ansidecl.h>
+#include "libiberty.h"
+#include "arparse.h"
+
+int linenumber;
+%}
+%%
+
+"ADDLIB"       { return ADDLIB; }
+"ADDMOD"       { return ADDMOD; }
+"CLEAR"        { return CLEAR; }
+"CREATE"       { return CREATE; }
+"DELETE"       { return DELETE; }
+"DIRECTORY"    { return DIRECTORY; }
+"END"          { return END; }
+"EXTRACT"      { return EXTRACT; }
+"FULLDIR"      { return FULLDIR; }
+"HELP"         { return HELP; }
+"LIST"         { return LIST; }
+"OPEN"         { return OPEN; }
+"REPLACE"      { return REPLACE; }
+"VERBOSE"      { return VERBOSE; }
+"SAVE"         { return SAVE; }
+"addlib"       { return ADDLIB; }
+"addmod"       { return ADDMOD; }
+"clear"        { return CLEAR; }
+"create"       { return CREATE; }
+"delete"       { return DELETE; }
+"directory"    { return DIRECTORY; }
+"end"          { return END; }
+"extract"      { return EXTRACT; }
+"fulldir"      { return FULLDIR; }
+"help"         { return HELP; }
+"list"         { return LIST; }
+"open"         { return OPEN; }
+"replace"      { return REPLACE; }
+"verbose"      { return VERBOSE; }
+"save"         { return SAVE; }
+"+\n"           { linenumber ++; }
+"("             { return '('; }
+")"             { return ')'; }
+","             { return ','; }
+[A-Za-z0-9/$:.\-\_]+  {        
+               yylval.name =  xstrdup (yytext);
+               return FILENAME;
+               }
+"*".*          { }
+";".*          { }
+" "            { }
+"\n"            { linenumber ++; return NEWLINE; }     
+
+%%
+#ifndef yywrap
+/* Needed for lex, though not flex. */
+int yywrap() { return 1; }
+#endif
diff --git a/binutils/arparse.y b/binutils/arparse.y
new file mode 100644 (file)
index 0000000..d6c7600
--- /dev/null
@@ -0,0 +1,202 @@
+%{
+/* arparse.y - Stange script language parser */
+
+/*   Copyright (C) 1992, 93, 95, 97, 98, 1999 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+/* Contributed by Steve Chamberlain
+                 sac@cygnus.com
+
+*/
+#define DONTDECLARE_MALLOC
+#include "bfd.h"
+#include "bucomm.h"
+#include "arsup.h"
+extern int verbose;
+extern int yylex PARAMS ((void));
+static int yyerror PARAMS ((const char *));
+%}
+
+%union {
+  char *name;
+struct list *list ;
+
+};
+
+%token NEWLINE
+%token VERBOSE
+%token <name> FILENAME
+%token ADDLIB
+%token LIST
+%token ADDMOD
+%token CLEAR
+%token CREATE
+%token DELETE
+%token DIRECTORY
+%token END
+%token EXTRACT
+%token FULLDIR
+%token HELP
+%token QUIT
+%token REPLACE
+%token SAVE
+%token OPEN
+
+%type <list> modulelist 
+%type <list> modulename
+%type <name> optional_filename
+%%
+
+start:
+       { prompt(); } session
+       ;
+
+session:
+           session command_line
+       |
+       ;
+
+command_line:
+               command NEWLINE { prompt(); }
+
+command:
+               open_command    
+       |       create_command  
+       |       verbose_command
+       |       directory_command
+       |       addlib_command
+       |       clear_command
+       |       addmod_command
+       |       save_command
+        |       extract_command
+       |       replace_command
+       |       delete_command
+       |       list_command
+       |       END      { ar_end(); return 0; }
+       |       error
+       |       FILENAME { yyerror("foo"); }
+       |
+       ;
+
+
+extract_command:
+                EXTRACT modulename
+               { ar_extract($2); }
+       ;
+
+replace_command:       
+               REPLACE modulename
+               { ar_replace($2); }
+       ;
+       
+clear_command:
+               CLEAR
+               { ar_clear(); }
+       ;
+
+delete_command:
+               DELETE modulename
+               { ar_delete($2); }
+       ;
+addmod_command:
+       ADDMOD modulename
+               { ar_addmod($2); }
+       ;
+
+list_command:  
+               LIST
+               { ar_list(); }
+       ;
+
+save_command:  
+               SAVE
+               { ar_save(); }
+       ;
+
+
+
+open_command:
+               OPEN FILENAME 
+               { ar_open($2,0); }
+       ;
+
+create_command:
+               CREATE FILENAME 
+               { ar_open($2,1); }
+       ;
+
+
+addlib_command:
+               ADDLIB FILENAME modulelist
+               { ar_addlib($2,$3); }
+       ;
+directory_command:
+               DIRECTORY FILENAME modulelist optional_filename
+               { ar_directory($2, $3, $4); }
+       ;
+
+
+
+optional_filename:
+               FILENAME
+               { $$ = $1; }
+       |       { $$ = 0; }
+       ;
+
+modulelist:
+       '(' modulename ')' 
+               { $$ = $2; }
+       |
+               { $$ = 0; }
+       ;
+
+modulename:
+               modulename optcomma FILENAME
+               {       struct list *n  = (struct list *) malloc(sizeof(struct list));
+                       n->next = $1; 
+                       n->name = $3;
+                       $$ = n;
+                }
+       |       { $$ = 0; }
+       ;
+       
+
+optcomma:
+               ','
+       |
+       ;
+       
+               
+verbose_command:
+       VERBOSE 
+               { verbose = !verbose; }
+       ;
+
+
+%%
+
+static int
+yyerror (x)
+     const char *x;
+{
+  extern int linenumber;
+
+  printf (_("Syntax error in archive script, line %d\n"), linenumber + 1);
+  return 0;
+}
diff --git a/binutils/arsup.c b/binutils/arsup.c
new file mode 100644 (file)
index 0000000..38fd695
--- /dev/null
@@ -0,0 +1,456 @@
+/* arsup.c - Archive support for MRI compatibility
+   Copyright (C) 1992, 93, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+/* Contributed by Steve Chamberlain
+                 sac@cygnus.com
+
+This file looks after requests from arparse.y, to provide the MRI
+style librarian command syntax + 1 word LIST
+
+*/
+
+#include "bfd.h"
+#include "arsup.h"
+#include "libiberty.h"
+#include "bucomm.h"
+
+static void map_over_list
+  PARAMS ((bfd *, void (*function) (bfd *, bfd *), struct list *));
+static void ar_directory_doer PARAMS ((bfd *, bfd *));
+static void ar_addlib_doer PARAMS ((bfd *, bfd *));
+
+extern int verbose;
+
+static void
+map_over_list (arch, function, list)
+     bfd *arch;
+     void (*function) PARAMS ((bfd *, bfd *));
+     struct list *list;
+{
+  bfd *head;
+
+  if (list == NULL)
+    {
+      bfd *next;
+
+      head = arch->next;
+      while (head != NULL)
+       {
+         next = head->next;
+         function (head, (bfd *) NULL);
+         head = next;
+       }
+    }
+  else
+    {
+      struct list *ptr;
+
+      /* This may appear to be a baroque way of accomplishing what we
+        want.  however we have to iterate over the filenames in order
+        to notice where a filename is requested but does not exist in
+        the archive.  Ditto mapping over each file each time -- we
+        want to hack multiple references.  */
+      for (ptr = list; ptr; ptr = ptr->next)
+       {
+         boolean found = false;
+         bfd *prev = arch;
+
+         for (head = arch->next; head; head = head->next) 
+           {
+             if (head->filename != NULL
+                 && strcmp (ptr->name, head->filename) == 0)
+               {
+                 found = true;
+                 function (head, prev);
+               }
+             prev = head;
+           }
+         if (! found)
+           fprintf (stderr, _("No entry %s in archive.\n"), ptr->name);
+       }
+    }
+}
+
+
+FILE *outfile;
+
+/*ARGSUSED*/
+static void
+ar_directory_doer (abfd, ignore)
+     bfd *abfd;
+     bfd *ignore;
+{
+    print_arelt_descr(outfile, abfd, verbose);
+}
+
+void
+ar_directory (ar_name, list, output)
+     char *ar_name;
+     struct list *list;
+     char *output;
+{
+  bfd *arch;
+
+  arch = open_inarch (ar_name, (char *) NULL);
+  if (output)
+    {
+      outfile = fopen(output,"w");
+      if (outfile == 0)
+       {
+         outfile = stdout;
+         fprintf (stderr,_("Can't open file %s\n"), output);
+         output = 0;
+       }
+    }
+  else 
+    outfile = stdout;
+
+  map_over_list (arch, ar_directory_doer, list);
+
+  bfd_close (arch);
+
+  if (output)
+   fclose (outfile);
+}
+
+void
+DEFUN_VOID(prompt)
+{
+  extern int interactive;
+  if (interactive) 
+  {
+    printf("AR >");
+    fflush(stdout); 
+  }
+}
+
+void
+maybequit ()
+{
+  if (! interactive) 
+    xexit (9);
+}
+
+
+bfd *obfd;
+char *real_name ; 
+void
+DEFUN(ar_open,(name, t),
+      char *name AND
+      int t)
+
+{
+  char *tname = (char *) xmalloc (strlen (name) + 10);
+  real_name = name;
+  sprintf(tname, "%s-tmp", name);
+  obfd = bfd_openw(tname, NULL);
+
+  if (!obfd) {
+    fprintf(stderr,_("%s: Can't open output archive %s\n"), program_name,
+           tname);
+
+    maybequit();
+  }
+  else {
+    if (!t) {
+      bfd **ptr;
+      bfd *element;
+      bfd *ibfd;
+      ibfd = bfd_openr(name, NULL);
+      if (!ibfd) {
+       fprintf(stderr,_("%s: Can't open input archive %s\n"),
+               program_name, name);
+       maybequit();
+       return;
+      }
+      if (bfd_check_format(ibfd, bfd_archive) != true) {
+       fprintf(stderr,_("%s: file %s is not an archive\n"), program_name,
+               name);
+       maybequit();
+       return;
+      }
+      ptr = &(obfd->archive_head);
+      element = bfd_openr_next_archived_file(ibfd, NULL);
+
+      while (element) {
+       *ptr = element;
+       ptr = &element->next;
+       element = bfd_openr_next_archived_file(ibfd, element);
+      }
+    }
+
+    bfd_set_format(obfd, bfd_archive);
+
+    obfd->has_armap = 1;
+  }
+}
+
+
+static void
+ar_addlib_doer (abfd, prev)
+     bfd *abfd;
+     bfd *prev;
+{
+  /* Add this module to the output bfd */
+  if (prev != NULL)
+    prev->next = abfd->next;
+  abfd->next = obfd->archive_head;
+  obfd->archive_head = abfd;
+}
+
+void
+ar_addlib (name, list)
+     char *name;
+     struct list *list;
+{
+  if (obfd == NULL)
+    {
+      fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
+      maybequit ();
+    }
+  else
+    {
+      bfd *arch;
+
+      arch = open_inarch (name, (char *) NULL);
+      if (arch != NULL)
+       map_over_list (arch, ar_addlib_doer, list);
+
+      /* Don't close the bfd, since it will make the elements disasppear */
+    }
+}
+
+void
+DEFUN(ar_addmod, (list),
+      struct list *list)
+{
+  if (!obfd) {
+    fprintf(stderr, _("%s: no open output archive\n"), program_name);
+    maybequit();
+  }
+  else 
+  {
+    while (list) {
+      bfd *abfd = bfd_openr(list->name, NULL);
+      if (!abfd)  {
+       fprintf(stderr,_("%s: can't open file %s\n"), program_name,
+               list->name);
+       maybequit();
+      }
+      else {
+       abfd->next = obfd->archive_head;
+       obfd->archive_head = abfd;
+      }
+      list = list->next;
+    }
+  }
+}
+
+
+
+void
+DEFUN_VOID(ar_clear)
+{
+if (obfd) 
+ obfd->archive_head = 0;
+}
+
+void
+DEFUN(ar_delete, (list),
+      struct list *list)
+{
+  if (!obfd) {
+    fprintf(stderr, _("%s: no open output archive\n"), program_name);
+    maybequit();
+  }
+  else 
+  {
+    while (list) {
+      /* Find this name in the archive */
+      bfd *member = obfd->archive_head;
+      bfd **prev = &(obfd->archive_head);
+      int found = 0;
+      while (member) {
+       if (strcmp(member->filename, list->name) == 0) {
+         *prev = member->next;
+         found = 1;
+       }
+       else {
+         prev = &(member->next);
+       }
+         member = member->next;
+      }
+      if (!found)  {
+       fprintf(stderr,_("%s: can't find module file %s\n"), program_name,
+               list->name);
+       maybequit();
+      }
+      list = list->next;
+    }
+  }
+}
+
+
+void
+DEFUN_VOID(ar_save)
+{
+
+  if (!obfd) {
+    fprintf(stderr, _("%s: no open output archive\n"), program_name);
+    maybequit();
+  }
+  else {
+    char *ofilename = xstrdup (bfd_get_filename (obfd));
+    bfd_close(obfd);
+    
+    rename (ofilename, real_name);
+    obfd = 0;
+    free(ofilename);
+  }
+}
+
+
+
+void
+DEFUN(ar_replace, (list),
+      struct list *list)
+{
+  if (!obfd) {
+    fprintf(stderr, _("%s: no open output archive\n"), program_name);
+    maybequit();
+  }
+  else 
+  {
+    while (list) {
+      /* Find this name in the archive */
+      bfd *member = obfd->archive_head;
+      bfd **prev = &(obfd->archive_head);
+      int found = 0;
+      while (member) 
+      {
+       if (strcmp(member->filename, list->name) == 0) 
+       {
+         /* Found the one to replace */
+         bfd *abfd = bfd_openr(list->name, 0);
+         if (!abfd) 
+         {
+           fprintf(stderr, _("%s: can't open file %s\n"), program_name, list->name);
+           maybequit();
+         }
+         else {
+           *prev = abfd;
+           abfd->next = member->next;
+           found = 1;
+         }
+       }
+       else {
+         prev = &(member->next);
+       }
+       member = member->next;
+      }
+      if (!found)  {
+       bfd *abfd = bfd_openr(list->name, 0);
+       fprintf(stderr,_("%s: can't find module file %s\n"), program_name,
+               list->name);
+       if (!abfd) 
+       {
+         fprintf(stderr, _("%s: can't open file %s\n"), program_name, list->name);
+         maybequit();
+       }
+       else 
+       {
+         *prev = abfd;
+       }
+      }
+
+    list = list->next;
+    }
+  }
+}
+
+/* And I added this one */
+void
+DEFUN_VOID(ar_list)
+{
+  if (!obfd) 
+  {
+    fprintf(stderr, _("%s: no open output archive\n"), program_name);
+    maybequit();
+  }
+  else {
+    bfd *abfd;
+    outfile = stdout;
+    verbose =1 ;
+    printf(_("Current open archive is %s\n"), bfd_get_filename (obfd));
+    for (abfd = obfd->archive_head;
+        abfd != (bfd *)NULL;
+        abfd = abfd->next) 
+    {
+      ar_directory_doer (abfd, (bfd *) NULL);
+    }
+  }
+}
+
+
+void 
+DEFUN_VOID(ar_end)
+{
+  if (obfd)
+  {
+    fclose((FILE *)(obfd->iostream));
+    unlink(bfd_get_filename (obfd));
+  }
+}
+void
+DEFUN(ar_extract,(list),
+      struct list *list)
+{
+  if (!obfd) 
+  {
+
+    fprintf(stderr, _("%s: no open  archive\n"), program_name);
+    maybequit();
+  }
+  else 
+  {
+    while (list) {
+      /* Find this name in the archive */
+      bfd *member = obfd->archive_head;
+      int found = 0;
+      while (member && !found) 
+      {
+       if (strcmp(member->filename, list->name) == 0) 
+       {
+         extract_file(member);
+         found = 1;
+         }
+
+       member = member->next;
+      }
+      if (!found)  {
+       bfd_openr(list->name, 0);
+       fprintf(stderr,_("%s: can't find module file %s\n"), program_name,
+               list->name);
+
+      }
+      list = list->next;
+    }
+  }
+}
diff --git a/binutils/arsup.h b/binutils/arsup.h
new file mode 100644 (file)
index 0000000..f54a34b
--- /dev/null
@@ -0,0 +1,75 @@
+/* arsup.h - archive support header file
+   Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+struct list {
+       char *name;     
+       struct list *next;
+};
+
+void
+maybequit PARAMS ((void));
+
+void
+prompt PARAMS ((void));
+
+void
+ar_clear PARAMS ((void));
+
+void
+ar_replace PARAMS ((struct list *));
+
+void
+ar_delete PARAMS ((struct list *));
+
+void
+ar_save PARAMS ((void));
+
+void
+ar_list PARAMS ((void));
+
+void
+ar_open PARAMS ((char *, int));
+
+void
+ar_directory PARAMS ((char *, struct list *, char *));
+
+void
+ar_addmod PARAMS ((struct list *));
+
+void
+ar_addlib PARAMS ((char *, struct list *));
+
+void 
+ar_end PARAMS ((void));
+
+void
+ar_extract PARAMS ((struct list *));
+
+bfd *
+open_inarch PARAMS ((const char *archive_filename, const char *));
+
+int
+yyparse PARAMS ((void));
+
+/* Functions from ar.c */
+
+void
+extract_file PARAMS ((bfd * abfd));
+
+extern int interactive;
diff --git a/binutils/binutils.texi b/binutils/binutils.texi
new file mode 100644 (file)
index 0000000..5f7c646
--- /dev/null
@@ -0,0 +1,2904 @@
+\input texinfo       @c                    -*- Texinfo -*-
+@setfilename binutils.info
+@include config.texi
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Binutils: (binutils).         The GNU binary utilities "ar", "objcopy",
+                               "objdump", "nm", "nlmconv", "size", "readelf"
+                                "strings", "strip", "ranlib" and "dlltool".
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries a copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@synindex ky cp
+@c
+@c This file documents the GNU binary utilities "ar", "ld", "objcopy",
+@c  "objdump", "nm", "size", "strings", "strip", "readelf" and "ranlib".
+@c
+@c Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+@c 
+@c This text may be freely distributed under the terms of the GNU
+@c General Public License.
+@c
+
+@setchapternewpage odd
+@settitle @sc{gnu} Binary Utilities
+@titlepage
+@finalout
+@title The @sc{gnu} Binary Utilities
+@subtitle Version @value{VERSION}
+@sp 1
+@subtitle May 1993
+@author Roland H. Pesch
+@author Jeffrey M. Osier
+@author Cygnus Support
+@page
+
+@tex
+{\parskip=0pt \hfill Cygnus Support\par \hfill
+\TeX{}info \texinfoversion\par }
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+
+@node Top
+@top Introduction
+
+@cindex version
+This brief manual contains preliminary documentation for the @sc{gnu} binary
+utilities (collectively version @value{VERSION}): 
+
+@iftex
+@table @code
+@item ar
+Create, modify, and extract from archives
+
+@item nm
+List symbols from object files
+
+@item objcopy
+Copy and translate object files
+
+@item objdump
+Display information from object files
+
+@item ranlib
+Generate index to archive contents
+
+@item readelf
+Display the contents of ELF format files.
+
+@item size
+List file section sizes and total size
+
+@item strings
+List printable strings from files
+
+@item strip
+Discard symbols
+
+@item c++filt
+Demangle encoded C++ symbols
+
+@item addr2line
+Convert addresses into file names and line numbers
+
+@item nlmconv
+Convert object code into a Netware Loadable Module
+
+@item windres
+Manipulate Windows resources
+
+@item dlltool
+Create the files needed to build and use Dynamic Link Libraries
+@end table
+@end iftex
+
+@menu
+* ar::                          Create, modify, and extract from archives
+* nm::                          List symbols from object files
+* objcopy::                    Copy and translate object files
+* objdump::                     Display information from object files
+* ranlib::                      Generate index to archive contents
+* readelf::                    Display the contents of ELF format files.
+* size::                        List section sizes and total size
+* strings::                     List printable strings from files
+* strip::                       Discard symbols
+* c++filt::                    Filter to demangle encoded C++ symbols
+* addr2line::                  Convert addresses to file and line
+* nlmconv::                     Converts object code into an NLM
+* windres::                    Manipulate Windows resources
+* dlltool::                    Create files needed to build and use DLLs
+* Selecting The Target System:: How these utilities determine the target.
+* Reporting Bugs::              Reporting Bugs
+* Index::                       Index
+@end menu
+
+@node ar
+@chapter ar
+
+@kindex ar
+@cindex archives
+@cindex collections of files
+@smallexample
+ar [-]@var{p}[@var{mod} [@var{relpos}]] @var{archive} [@var{member}@dots{}]
+ar -M [ <mri-script ]
+@end smallexample
+
+The @sc{gnu} @code{ar} program creates, modifies, and extracts from
+archives.  An @dfn{archive} is a single file holding a collection of
+other files in a structure that makes it possible to retrieve
+the original individual files (called @dfn{members} of the archive).
+
+The original files' contents, mode (permissions), timestamp, owner, and
+group are preserved in the archive, and can be restored on
+extraction.  
+
+@cindex name length
+@sc{gnu} @code{ar} can maintain archives whose members have names of any
+length; however, depending on how @code{ar} is configured on your
+system, a limit on member-name length may be imposed for compatibility
+with archive formats maintained with other tools.  If it exists, the
+limit is often 15 characters (typical of formats related to a.out) or 16
+characters (typical of formats related to coff).
+
+@cindex libraries
+@code{ar} is considered a binary utility because archives of this sort
+are most often used as @dfn{libraries} holding commonly needed
+subroutines.
+
+@cindex symbol index
+@code{ar} creates an index to the symbols defined in relocatable
+object modules in the archive when you specify the modifier @samp{s}.
+Once created, this index is updated in the archive whenever @code{ar}
+makes a change to its contents (save for the @samp{q} update operation).
+An archive with such an index speeds up linking to the library, and
+allows routines in the library to call each other without regard to
+their placement in the archive.
+
+You may use @samp{nm -s} or @samp{nm --print-armap} to list this index
+table.  If an archive lacks the table, another form of @code{ar} called
+@code{ranlib} can be used to add just the table.
+
+@cindex compatibility, @code{ar}
+@cindex @code{ar} compatibility
+@sc{gnu} @code{ar} is designed to be compatible with two different
+facilities.  You can control its activity using command-line options,
+like the different varieties of @code{ar} on Unix systems; or, if you
+specify the single command-line option @samp{-M}, you can control it
+with a script supplied via standard input, like the MRI ``librarian''
+program.
+
+@menu
+* ar cmdline::                  Controlling @code{ar} on the command line
+* ar scripts::                  Controlling @code{ar} with a script
+@end menu
+
+@page
+@node ar cmdline
+@section Controlling @code{ar} on the command line
+
+@smallexample
+ar [-]@var{p}[@var{mod} [@var{relpos}]] @var{archive} [@var{member}@dots{}]
+@end smallexample
+
+@cindex Unix compatibility, @code{ar}
+When you use @code{ar} in the Unix style, @code{ar} insists on at least two
+arguments to execute: one keyletter specifying the @emph{operation}
+(optionally accompanied by other keyletters specifying
+@emph{modifiers}), and the archive name to act on.
+
+Most operations can also accept further @var{member} arguments,
+specifying particular files to operate on.
+
+@sc{gnu} @code{ar} allows you to mix the operation code @var{p} and modifier
+flags @var{mod} in any order, within the first command-line argument.
+
+If you wish, you may begin the first command-line argument with a
+dash.
+
+@cindex operations on archive
+The @var{p} keyletter specifies what operation to execute; it may be
+any of the following, but you must specify only one of them:
+
+@table @code
+@item d
+@cindex deleting from archive
+@emph{Delete} modules from the archive.  Specify the names of modules to
+be deleted as @var{member}@dots{}; the archive is untouched if you
+specify no files to delete.
+
+If you specify the @samp{v} modifier, @code{ar} lists each module
+as it is deleted.
+
+@item m
+@cindex moving in archive
+Use this operation to @emph{move} members in an archive.
+
+The ordering of members in an archive can make a difference in how
+programs are linked using the library, if a symbol is defined in more
+than one member.  
+
+If no modifiers are used with @code{m}, any members you name in the
+@var{member} arguments are moved to the @emph{end} of the archive;
+you can use the @samp{a}, @samp{b}, or @samp{i} modifiers to move them to a
+specified place instead.
+
+@item p
+@cindex printing from archive
+@emph{Print} the specified members of the archive, to the standard
+output file.  If the @samp{v} modifier is specified, show the member
+name before copying its contents to standard output.
+
+If you specify no @var{member} arguments, all the files in the archive are
+printed.
+
+@item q
+@cindex quick append to archive
+@emph{Quick append}; Historically, add the files @var{member}@dots{} to the end of
+@var{archive}, without checking for replacement.
+
+The modifiers @samp{a}, @samp{b}, and @samp{i} do @emph{not} affect this
+operation; new members are always placed at the end of the archive.
+
+The modifier @samp{v} makes @code{ar} list each file as it is appended.
+
+Since the point of this operation is speed, the archive's symbol table
+index is not updated, even if it already existed; you can use @samp{ar s} or
+@code{ranlib} explicitly to update the symbol table index.
+
+However, too many different systems assume quick append rebuilds the
+index, so GNU ar implements @code{q} as a synonym for @code{r}.
+
+@item r
+@cindex replacement in archive
+Insert the files @var{member}@dots{} into @var{archive} (with
+@emph{replacement}). This operation differs from @samp{q} in that any
+previously existing members are deleted if their names match those being
+added.
+
+If one of the files named in @var{member}@dots{} does not exist, @code{ar}
+displays an error message, and leaves undisturbed any existing members
+of the archive matching that name.
+
+By default, new members are added at the end of the file; but you may
+use one of the modifiers @samp{a}, @samp{b}, or @samp{i} to request
+placement relative to some existing member.
+
+The modifier @samp{v} used with this operation elicits a line of
+output for each file inserted, along with one of the letters @samp{a} or
+@samp{r} to indicate whether the file was appended (no old member
+deleted) or replaced.
+
+@item t
+@cindex contents of archive
+Display a @emph{table} listing the contents of @var{archive}, or those
+of the files listed in @var{member}@dots{} that are present in the
+archive.  Normally only the member name is shown; if you also want to
+see the modes (permissions), timestamp, owner, group, and size, you can
+request that by also specifying the @samp{v} modifier.
+
+If you do not specify a @var{member}, all files in the archive
+are listed.
+
+@cindex repeated names in archive
+@cindex name duplication in archive
+If there is more than one file with the same name (say, @samp{fie}) in
+an archive (say @samp{b.a}), @samp{ar t b.a fie} lists only the
+first instance; to see them all, you must ask for a complete
+listing---in our example, @samp{ar t b.a}.
+@c WRS only; per Gumby, this is implementation-dependent, and in a more
+@c recent case in fact works the other way.
+
+@item x
+@cindex extract from archive
+@emph{Extract} members (named @var{member}) from the archive.  You can
+use the @samp{v} modifier with this operation, to request that
+@code{ar} list each name as it extracts it.
+
+If you do not specify a @var{member}, all files in the archive
+are extracted.
+
+@end table
+
+A number of modifiers (@var{mod}) may immediately follow the @var{p}
+keyletter, to specify variations on an operation's behavior:
+
+@table @code
+@item a
+@cindex relative placement in archive
+Add new files @emph{after} an existing member of the
+archive.  If you use the modifier @samp{a}, the name of an existing archive
+member must be present as the @var{relpos} argument, before the
+@var{archive} specification.
+
+@item b
+Add new files @emph{before} an existing member of the
+archive.  If you use the modifier @samp{b}, the name of an existing archive
+member must be present as the @var{relpos} argument, before the
+@var{archive} specification.  (same as @samp{i}).
+
+@item c
+@cindex creating archives
+@emph{Create} the archive.  The specified @var{archive} is always
+created if it did not exist, when you request an update.  But a warning is
+issued unless you specify in advance that you expect to create it, by
+using this modifier.
+
+@item f
+Truncate names in the archive.  @sc{gnu} @code{ar} will normally permit file
+names of any length.  This will cause it to create archives which are
+not compatible with the native @code{ar} program on some systems.  If
+this is a concern, the @samp{f} modifier may be used to truncate file
+names when putting them in the archive.
+
+@item i
+Insert new files @emph{before} an existing member of the
+archive.  If you use the modifier @samp{i}, the name of an existing archive
+member must be present as the @var{relpos} argument, before the
+@var{archive} specification.  (same as @samp{b}).
+
+@item l
+This modifier is accepted but not used.
+@c whaffor ar l modifier??? presumably compat; with
+@c what???---doc@@cygnus.com, 25jan91 
+
+@item o
+@cindex dates in archive
+Preserve the @emph{original} dates of members when extracting them.  If
+you do not specify this modifier, files extracted from the archive
+are stamped with the time of extraction.
+
+@item s
+@cindex writing archive index
+Write an object-file index into the archive, or update an existing one,
+even if no other change is made to the archive.  You may use this modifier
+flag either with any operation, or alone.  Running @samp{ar s} on an
+archive is equivalent to running @samp{ranlib} on it.
+
+@item S
+@cindex not writing archive index
+Do not generate an archive symbol table.  This can speed up building a
+large library in several steps.  The resulting archive can not be used
+with the linker.  In order to build a symbol table, you must omit the
+@samp{S} modifier on the last execution of @samp{ar}, or you must run
+@samp{ranlib} on the archive.
+
+@item u
+@cindex updating an archive
+Normally, @samp{ar r}@dots{} inserts all files
+listed into the archive.  If you would like to insert @emph{only} those
+of the files you list that are newer than existing members of the same
+names, use this modifier.  The @samp{u} modifier is allowed only for the
+operation @samp{r} (replace).  In particular, the combination @samp{qu} is
+not allowed, since checking the timestamps would lose any speed
+advantage from the operation @samp{q}.
+
+@item v
+This modifier requests the @emph{verbose} version of an operation.  Many
+operations display additional information, such as filenames processed,
+when the modifier @samp{v} is appended.
+
+@item V
+This modifier shows the version number of @code{ar}.
+@end table
+
+@node ar scripts
+@section Controlling @code{ar} with a script
+
+@smallexample
+ar -M [ <@var{script} ]
+@end smallexample
+
+@cindex MRI compatibility, @code{ar}
+@cindex scripts, @code{ar}
+If you use the single command-line option @samp{-M} with @code{ar}, you
+can control its operation with a rudimentary command language.  This
+form of @code{ar} operates interactively if standard input is coming
+directly from a terminal.  During interactive use, @code{ar} prompts for
+input (the prompt is @samp{AR >}), and continues executing even after
+errors.  If you redirect standard input to a script file, no prompts are
+issued, and @code{ar} abandons execution (with a nonzero exit code)
+on any error.
+
+The @code{ar} command language is @emph{not} designed to be equivalent
+to the command-line options; in fact, it provides somewhat less control
+over archives.  The only purpose of the command language is to ease the
+transition to @sc{gnu} @code{ar} for developers who already have scripts
+written for the MRI ``librarian'' program.
+
+The syntax for the @code{ar} command language is straightforward:
+@itemize @bullet
+@item
+commands are recognized in upper or lower case; for example, @code{LIST}
+is the same as @code{list}.  In the following descriptions, commands are
+shown in upper case for clarity.
+
+@item
+a single command may appear on each line; it is the first word on the
+line.
+
+@item
+empty lines are allowed, and have no effect.
+
+@item
+comments are allowed; text after either of the characters @samp{*}
+or @samp{;} is ignored.
+
+@item
+Whenever you use a list of names as part of the argument to an @code{ar}
+command, you can separate the individual names with either commas or
+blanks.  Commas are shown in the explanations below, for clarity.
+
+@item
+@samp{+} is used as a line continuation character; if @samp{+} appears
+at the end of a line, the text on the following line is considered part
+of the current command.
+@end itemize
+
+Here are the commands you can use in @code{ar} scripts, or when using
+@code{ar} interactively.  Three of them have special significance:
+
+@code{OPEN} or @code{CREATE} specify a @dfn{current archive}, which is
+a temporary file required for most of the other commands.
+
+@code{SAVE} commits the changes so far specified by the script.  Prior
+to @code{SAVE}, commands affect only the temporary copy of the current
+archive.
+
+@table @code
+@item ADDLIB @var{archive} 
+@itemx ADDLIB @var{archive} (@var{module}, @var{module}, @dots{} @var{module})
+Add all the contents of @var{archive} (or, if specified, each named
+@var{module} from @var{archive}) to the current archive.
+
+Requires prior use of @code{OPEN} or @code{CREATE}.
+
+@item ADDMOD @var{member}, @var{member}, @dots{} @var{member}
+@c FIXME! w/Replacement??  If so, like "ar r @var{archive} @var{names}"
+@c        else like "ar q..."
+Add each named @var{member} as a module in the current archive.
+
+Requires prior use of @code{OPEN} or @code{CREATE}.
+
+@item CLEAR
+Discard the contents of the current archive, canceling the effect of
+any operations since the last @code{SAVE}.  May be executed (with no
+effect) even if  no current archive is specified.
+
+@item CREATE @var{archive}
+Creates an archive, and makes it the current archive (required for many
+other commands).  The new archive is created with a temporary name; it
+is not actually saved as @var{archive} until you use @code{SAVE}.
+You can overwrite existing archives; similarly, the contents of any
+existing file named @var{archive} will not be destroyed until @code{SAVE}.
+
+@item DELETE @var{module}, @var{module}, @dots{} @var{module}
+Delete each listed @var{module} from the current archive; equivalent to
+@samp{ar -d @var{archive} @var{module} @dots{} @var{module}}.
+
+Requires prior use of @code{OPEN} or @code{CREATE}.
+
+@item DIRECTORY @var{archive} (@var{module}, @dots{} @var{module})
+@itemx DIRECTORY @var{archive} (@var{module}, @dots{} @var{module}) @var{outputfile}
+List each named @var{module} present in @var{archive}.  The separate
+command @code{VERBOSE} specifies the form of the output: when verbose
+output is off, output is like that of @samp{ar -t @var{archive}
+@var{module}@dots{}}.  When verbose output is on, the listing is like
+@samp{ar -tv @var{archive} @var{module}@dots{}}.
+
+Output normally goes to the standard output stream; however, if you
+specify @var{outputfile} as a final argument, @code{ar} directs the
+output to that file.
+
+@item END
+Exit from @code{ar}, with a @code{0} exit code to indicate successful
+completion.  This command does not save the output file; if you have
+changed the current archive since the last @code{SAVE} command, those
+changes are lost.
+
+@item EXTRACT @var{module}, @var{module}, @dots{} @var{module}
+Extract each named @var{module} from the current archive, writing them
+into the current directory as separate files.  Equivalent to @samp{ar -x
+@var{archive} @var{module}@dots{}}.
+
+Requires prior use of @code{OPEN} or @code{CREATE}.
+
+@ignore
+@c FIXME Tokens but no commands???
+@item FULLDIR
+
+@item HELP
+@end ignore
+
+@item LIST
+Display full contents of the current archive, in ``verbose'' style
+regardless of the state of @code{VERBOSE}.  The effect is like @samp{ar
+tv @var{archive}}).  (This single command is a @sc{gnu} @code{ld}
+enhancement, rather than present for MRI compatibility.)
+
+Requires prior use of @code{OPEN} or @code{CREATE}.
+
+@item OPEN @var{archive}
+Opens an existing archive for use as the current archive (required for
+many other commands).  Any changes as the result of subsequent commands
+will not actually affect @var{archive} until you next use @code{SAVE}.
+
+@item REPLACE @var{module}, @var{module}, @dots{} @var{module}
+In the current archive, replace each existing @var{module} (named in
+the @code{REPLACE} arguments) from files in the current working directory.
+To execute this command without errors, both the file, and the module in
+the current archive, must exist. 
+
+Requires prior use of @code{OPEN} or @code{CREATE}.
+
+@item VERBOSE
+Toggle an internal flag governing the output from @code{DIRECTORY}.
+When the flag is on, @code{DIRECTORY} output matches output from
+@samp{ar -tv }@dots{}.
+
+@item SAVE
+Commit your changes to the current archive, and actually save it as a
+file with the name specified in the last @code{CREATE} or @code{OPEN}
+command. 
+
+Requires prior use of @code{OPEN} or @code{CREATE}.
+
+@end table
+
+@iftex
+@node ld
+@chapter ld
+@cindex linker
+@kindex ld
+The @sc{gnu} linker @code{ld} is now described in a separate manual.
+@xref{Top,, Overview,, Using LD: the @sc{gnu} linker}.
+@end iftex
+
+@node nm
+@chapter nm
+@cindex symbols
+@kindex nm
+
+@smallexample
+nm [ -a | --debug-syms ]  [ -g | --extern-only ]
+   [ -B ]  [ -C | --demangle ] [ -D | --dynamic ]
+   [ -s | --print-armap ]  [ -A | -o | --print-file-name ]
+   [ -n | -v | --numeric-sort ]  [ -p | --no-sort ]
+   [ -r | --reverse-sort ]  [ --size-sort ] [ -u | --undefined-only ]
+   [ -t @var{radix} | --radix=@var{radix} ] [ -P | --portability ]
+   [ --target=@var{bfdname} ] [ -f @var{format} | --format=@var{format} ]
+   [ --defined-only ] [-l | --line-numbers ]
+   [ --no-demangle ] [ -V | --version ]  [ --help ]  [ @var{objfile}@dots{} ]
+@end smallexample
+
+@sc{gnu} @code{nm} lists the symbols from object files @var{objfile}@dots{}.
+If no object files are listed as arguments, @code{nm} assumes
+@file{a.out}.
+
+For each symbol, @code{nm} shows:
+
+@itemize @bullet
+@item
+The symbol value, in the radix selected by options (see below), or
+hexadecimal by default.
+
+@item
+The symbol type.  At least the following types are used; others are, as
+well, depending on the object file format.  If lowercase, the symbol is
+local; if uppercase, the symbol is global (external).
+
+@c Some more detail on exactly what these symbol types are used for
+@c would be nice.
+@table @code
+@item A
+The symbol's value is absolute, and will not be changed by further
+linking.
+
+@item B
+The symbol is in the uninitialized data section (known as BSS).
+
+@item C
+The symbol is common.  Common symbols are uninitialized data.  When
+linking, multiple common symbols may appear with the same name.  If the
+symbol is defined anywhere, the common symbols are treated as undefined
+references.  For more details on common symbols, see the discussion of
+--warn-common in @ref{Options,,Linker options,ld.info,The GNU linker}.
+
+@item D
+The symbol is in the initialized data section.
+
+@item G
+The symbol is in an initialized data section for small objects.  Some
+object file formats permit more efficient access to small data objects,
+such as a global int variable as opposed to a large global array.
+
+@item I
+The symbol is an indirect reference to another symbol.  This is a GNU
+extension to the a.out object file format which is rarely used.
+
+@item N
+The symbol is a debugging symbol.
+
+@item R
+The symbol is in a read only data section.
+
+@item S
+The symbol is in an uninitialized data section for small objects.
+
+@item T
+The symbol is in the text (code) section.
+
+@item U
+The symbol is undefined.
+
+@item W
+The symbol is weak.  When a weak defined symbol is linked with a normal
+defined symbol, the normal defined symbol is used with no error.  When a
+weak undefined symbol is linked and the symbol is not defined, the value
+of the weak symbol becomes zero with no error.
+
+@item -
+The symbol is a stabs symbol in an a.out object file.  In this case, the
+next values printed are the stabs other field, the stabs desc field, and
+the stab type.  Stabs symbols are used to hold debugging information;
+for more information, see @ref{Top,Stabs,Stabs Overview,stabs.info, The
+``stabs'' debug format}.
+
+@item ?
+The symbol type is unknown, or object file format specific.
+@end table
+
+@item
+The symbol name.
+@end itemize
+
+The long and short forms of options, shown here as alternatives, are
+equivalent.
+
+@table @code
+@item -A
+@itemx -o
+@itemx --print-file-name 
+@cindex input file name
+@cindex file name
+@cindex source file name
+Precede each symbol by the name of the input file (or archive element)
+in which it was found, rather than identifying the input file once only,
+before all of its symbols.
+
+@item -a
+@itemx --debug-syms 
+@cindex debugging symbols
+Display all symbols, even debugger-only symbols; normally these are not
+listed.
+
+@item -B
+@cindex @code{nm} format
+@cindex @code{nm} compatibility
+The same as @samp{--format=bsd} (for compatibility with the MIPS @code{nm}).
+
+@item -C
+@itemx --demangle
+@cindex demangling in nm
+Decode (@dfn{demangle}) low-level symbol names into user-level names.
+Besides removing any initial underscore prepended by the system, this
+makes C++ function names readable.  @xref{c++filt}, for more information
+on demangling.
+
+@item --no-demangle
+Do not demangle low-level symbol names.  This is the default.
+
+@item -D
+@itemx --dynamic
+@cindex dynamic symbols
+Display the dynamic symbols rather than the normal symbols.  This is
+only meaningful for dynamic objects, such as certain types of shared
+libraries.
+
+@item -f @var{format}
+@itemx --format=@var{format}
+@cindex @code{nm} format
+@cindex @code{nm} compatibility
+Use the output format @var{format}, which can be @code{bsd},
+@code{sysv}, or @code{posix}.  The default is @code{bsd}.
+Only the first character of @var{format} is significant; it can be
+either upper or lower case.
+
+@item -g
+@itemx --extern-only 
+@cindex external symbols
+Display only external symbols.
+
+@item -l
+@itemx --line-numbers
+@cindex symbol line numbers
+For each symbol, use debugging information to try to find a filename and
+line number.  For a defined symbol, look for the line number of the
+address of the symbol.  For an undefined symbol, look for the line
+number of a relocation entry which refers to the symbol.  If line number
+information can be found, print it after the other symbol information.
+
+@item -n
+@itemx -v
+@itemx --numeric-sort 
+Sort symbols numerically by their addresses, rather than alphabetically
+by their names. 
+
+@item -p
+@itemx --no-sort 
+@cindex sorting symbols
+Do not bother to sort the symbols in any order; print them in the order
+encountered.
+
+@item -P
+@itemx --portability
+Use the POSIX.2 standard output format instead of the default format.
+Equivalent to @samp{-f posix}.
+
+@item -s
+@itemx --print-armap
+@cindex symbol index, listing
+When listing symbols from archive members, include the index: a mapping
+(stored in the archive by @code{ar} or @code{ranlib}) of which modules
+contain definitions for which names.
+
+@item -r
+@itemx --reverse-sort 
+Reverse the order of the sort (whether numeric or alphabetic); let the
+last come first.
+
+@item --size-sort
+Sort symbols by size.  The size is computed as the difference between
+the value of the symbol and the value of the symbol with the next higher
+value.  The size of the symbol is printed, rather than the value.
+
+@item -t @var{radix}
+@itemx --radix=@var{radix}
+Use @var{radix} as the radix for printing the symbol values.  It must be
+@samp{d} for decimal, @samp{o} for octal, or @samp{x} for hexadecimal.
+
+@item --target=@var{bfdname}
+@cindex object code format
+Specify an object code format other than your system's default format.
+@xref{Target Selection}, for more information.
+
+@item -u
+@itemx --undefined-only 
+@cindex external symbols
+@cindex undefined symbols
+Display only undefined symbols (those external to each object file).
+
+@item --defined-only
+@cindex external symbols
+@cindex undefined symbols
+Display only defined symbols for each object file.
+
+@item -V
+@itemx --version
+Show the version number of @code{nm} and exit.
+
+@item --help
+Show a summary of the options to @code{nm} and exit.
+@end table
+
+@node objcopy
+@chapter objcopy
+
+@smallexample
+objcopy [ -F @var{bfdname} | --target=@var{bfdname} ]
+        [ -I @var{bfdname} | --input-target=@var{bfdname} ]
+        [ -O @var{bfdname} | --output-target=@var{bfdname} ]
+        [ -S | --strip-all ]  [ -g | --strip-debug ]
+        [ -K @var{symbolname} | --keep-symbol=@var{symbolname} ]
+        [ -N @var{symbolname} | --strip-symbol=@var{symbolname} ]
+        [ -L @var{symbolname} | --localize-symbol=@var{symbolname} ]
+        [ -W @var{symbolname} | --weaken-symbol=@var{symbolname} ]
+        [ -x | --discard-all ]  [ -X | --discard-locals ]
+        [ -b @var{byte} | --byte=@var{byte} ]
+        [ -i @var{interleave} | --interleave=@var{interleave} ]
+        [ -R @var{sectionname} | --remove-section=@var{sectionname} ]
+        [ -p | --preserve-dates ] [ --debugging ]
+        [ --gap-fill=@var{val} ] [ --pad-to=@var{address} ]
+        [ --set-start=@var{val} ] [ --adjust-start=@var{incr} ]
+        [ --change-addresses=@var{incr} ]
+        [ --change-section-address=@var{section}@{=,+,-@}@var{val} ]
+        [ --change-section-lma=@var{section}@{=,+,-@}@var{val} ]
+        [ --change-section-vma=@var{section}@{=,+,-@}@var{val} ]
+        [ --change-warnings ] [ --no-change-warnings ]
+        [ --set-section-flags=@var{section}=@var{flags} ]
+        [ --add-section=@var{sectionname}=@var{filename} ]
+        [ --change-leading-char ] [ --remove-leading-char ]
+        [ --weaken ]
+        [ -v | --verbose ] [ -V | --version ]  [ --help ]
+        @var{infile} [@var{outfile}]
+@end smallexample
+
+The @sc{gnu} @code{objcopy} utility copies the contents of an object
+file to another.  @code{objcopy} uses the @sc{gnu} @sc{bfd} Library to
+read and write the object files.  It can write the destination object
+file in a format different from that of the source object file.  The
+exact behavior of @code{objcopy} is controlled by command-line options.
+
+@code{objcopy} creates temporary files to do its translations and
+deletes them afterward.  @code{objcopy} uses @sc{bfd} to do all its
+translation work; it has access to all the formats described in @sc{bfd}
+and thus is able to recognize most formats without being told
+explicitly.  @xref{BFD,,BFD,ld.info,Using LD}.
+
+@code{objcopy} can be used to generate S-records by using an output
+target of @samp{srec} (e.g., use @samp{-O srec}).
+
+@code{objcopy} can be used to generate a raw binary file by using an
+output target of @samp{binary} (e.g., use @samp{-O binary}).  When
+@code{objcopy} generates a raw binary file, it will essentially produce
+a memory dump of the contents of the input object file.  All symbols and
+relocation information will be discarded.  The memory dump will start at
+the load address of the lowest section copied into the output file.
+
+When generating an S-record or a raw binary file, it may be helpful to
+use @samp{-S} to remove sections containing debugging information.  In
+some cases @samp{-R} will be useful to remove sections which contain
+information which is not needed by the binary file.
+
+@table @code
+@item @var{infile}
+@itemx @var{outfile}
+The source and output files, respectively.
+If you do not specify @var{outfile}, @code{objcopy} creates a
+temporary file and destructively renames the result with
+the name of @var{infile}.
+
+@item -I @var{bfdname} 
+@itemx --input-target=@var{bfdname}
+Consider the source file's object format to be @var{bfdname}, rather than
+attempting to deduce it.  @xref{Target Selection}, for more information.
+
+@item -O @var{bfdname}
+@itemx --output-target=@var{bfdname}
+Write the output file using the object format @var{bfdname}.
+@xref{Target Selection}, for more information.
+
+@item -F @var{bfdname}
+@itemx --target=@var{bfdname}
+Use @var{bfdname} as the object format for both the input and the output
+file; i.e., simply transfer data from source to destination with no
+translation.  @xref{Target Selection}, for more information.
+
+@item -R @var{sectionname}
+@itemx --remove-section=@var{sectionname}
+Remove any section named @var{sectionname} from the output file.  This
+option may be given more than once.  Note that using this option
+inappropriately may make the output file unusable.
+
+@item -S
+@itemx --strip-all
+Do not copy relocation and symbol information from the source file.
+
+@item -g
+@itemx --strip-debug
+Do not copy debugging symbols from the source file.
+
+@item --strip-unneeded
+Strip all symbols that are not needed for relocation processing.
+
+@item -K @var{symbolname}
+@itemx --keep-symbol=@var{symbolname}
+Copy only symbol @var{symbolname} from the source file.  This option may
+be given more than once.
+
+@item -N @var{symbolname}
+@itemx --strip-symbol=@var{symbolname}
+Do not copy symbol @var{symbolname} from the source file.  This option
+may be given more than once.
+
+@item -L @var{symbolname}
+@itemx --localize-symbol=@var{symbolname}
+Make symbol @var{symbolname} local to the file, so that it is not
+visible externally.  This option may be given more than once.
+
+@item -W @var{symbolname}
+@itemx --weaken-symbol=@var{symbolname}
+Make symbol @var{symbolname} weak. This option may be given more than once.
+
+@item -x
+@itemx --discard-all
+Do not copy non-global symbols from the source file.
+@c FIXME any reason to prefer "non-global" to "local" here?
+
+@item -X
+@itemx --discard-locals
+Do not copy compiler-generated local symbols.
+(These usually start with @samp{L} or @samp{.}.)
+
+@item -b @var{byte}
+@itemx --byte=@var{byte}
+Keep only every @var{byte}th byte of the input file (header data is not
+affected).  @var{byte} can be in the range from 0 to @var{interleave}-1,
+where @var{interleave} is given by the @samp{-i} or @samp{--interleave}
+option, or the default of 4.  This option is useful for creating files
+to program @sc{rom}.  It is typically used with an @code{srec} output
+target.
+
+@item -i @var{interleave}
+@itemx --interleave=@var{interleave}
+Only copy one out of every @var{interleave} bytes.  Select which byte to
+copy with the @var{-b} or @samp{--byte} option.  The default is 4.
+@code{objcopy} ignores this option if you do not specify either @samp{-b} or
+@samp{--byte}.
+
+@item -p
+@itemx --preserve-dates
+Set the access and modification dates of the output file to be the same
+as those of the input file.
+
+@item --debugging
+Convert debugging information, if possible.  This is not the default
+because only certain debugging formats are supported, and the
+conversion process can be time consuming.
+
+@item --gap-fill @var{val}
+Fill gaps between sections with @var{val}.  This operation applies to
+the @emph{load address} (LMA) of the sections.  It is done by increasing
+the size of the section with the lower address, and filling in the extra
+space created with @var{val}.
+
+@item --pad-to @var{address}
+Pad the output file up to the load address @var{address}.  This is
+done by increasing the size of the last section.  The extra space is
+filled in with the value specified by @samp{--gap-fill} (default zero).
+
+@item --set-start @var{val}
+Set the address of the new file to @var{val}.  Not all object file
+formats support setting the start address.
+
+@item --change-start @var{incr}
+@itemx --adjust-start @var{incr}
+@cindex changing start address
+Change the start address by adding @var{incr}.  Not all object file
+formats support setting the start address.
+
+@item --change-addresses @var{incr}
+@itemx --adjust-vma @var{incr}
+@cindex changing object addresses
+Change the VMA and LMA addresses of all sections, as well as the start
+address, by adding @var{incr}.  Some object file formats do not permit
+section addresses to be changed arbitrarily.  Note that this does not
+relocate the sections; if the program expects sections to be loaded at a
+certain address, and this option is used to change the sections such
+that they are loaded at a different address, the program may fail. 
+
+@item --change-section-address @var{section}@{=,+,-@}@var{val}
+@itemx --adjust-section-vma @var{section}@{=,+,-@}@var{val}
+@cindex changing section address
+Set or change both the VMA address and the LMA address of the named
+@var{section}.  If @samp{=} is used, the section address is set to
+@var{val}.  Otherwise, @var{val} is added to or subtracted from the
+section address.  See the comments under @samp{--change-addresses},
+above. If @var{section} does not exist in the input file, a warning will
+be issued, unless @samp{--no-change-warnings} is used.
+
+@item --change-section-lma @var{section}@{=,+,-@}@var{val}
+@cindex changing section LMA
+Set or change the LMA address of the named @var{section}.  The LMA
+address is the address where the section will be loaded into memory at
+program load time.  Normally this is the same as the VMA address, which
+is the address of the section at program run time, but on some systems,
+especially those where a program is held in ROM, the two can be
+different.  If @samp{=} is used, the section address is set to
+@var{val}.  Otherwise, @var{val} is added to or subtracted from the
+section address.  See the comments under @samp{--change-addresses},
+above.  If @var{section} does not exist in the input file, a warning
+will be issued, unless @samp{--no-change-warnings} is used.  
+
+@item --change-section-vma @var{section}@{=,+,-@}@var{val}
+@cindex changing section VMA
+Set or change the VMA address of the named @var{section}.  The VMA
+address is the address where the section will be located once the
+program has started executing.  Normally this is the same as the LMA
+address, which is the address where the section will be loaded into
+memory, but on some systems, especially those where a program is held in
+ROM, the two can be different.  If @samp{=} is used, the section address
+is set to @var{val}.  Otherwise, @var{val} is added to or subtracted
+from the section address.  See the comments under
+@samp{--change-addresses}, above.  If @var{section} does not exist in
+the input file, a warning will be issued, unless
+@samp{--no-change-warnings} is used.   
+
+@item --change-warnings
+@itemx --adjust-warnings
+If @samp{--change-section-address} or @samp{--change-section-lma} or
+@samp{--change-section-vma} is used, and the named section does not
+exist, issue a warning.  This is the default. 
+
+@item --no-change-warnings
+@itemx --no-adjust-warnings
+Do not issue a warning if @samp{--change-section-address} or
+@samp{--adjust-section-lma} or @samp{--adjust-section-vma} is used, even
+if the named section does not exist. 
+
+@item --set-section-flags @var{section}=@var{flags}
+Set the flags for the named section.  The @var{flags} argument is a
+comma separated string of flag names.  The recognized names are
+@samp{alloc}, @samp{contents}, @samp{load}, @samp{readonly},
+@samp{code}, @samp{data}, and @samp{rom}.  You can set the
+@samp{contents} flag for a section which does not have contents, but it
+is not meaningful to clear the @samp{contents} flag of a section which
+does have contents--just remove the section instead.  Not all flags are
+meaningful for all object file formats.
+
+@item --add-section @var{sectionname}=@var{filename}
+Add a new section named @var{sectionname} while copying the file.  The
+contents of the new section are taken from the file @var{filename}.  The
+size of the section will be the size of the file.  This option only
+works on file formats which can support sections with arbitrary names.
+
+@item --change-leading-char
+Some object file formats use special characters at the start of
+symbols.  The most common such character is underscore, which compilers
+often add before every symbol.  This option tells @code{objcopy} to
+change the leading character of every symbol when it converts between
+object file formats.  If the object file formats use the same leading
+character, this option has no effect.  Otherwise, it will add a
+character, or remove a character, or change a character, as
+appropriate.
+
+@item --remove-leading-char
+If the first character of a global symbol is a special symbol leading
+character used by the object file format, remove the character.  The
+most common symbol leading character is underscore.  This option will
+remove a leading underscore from all global symbols.  This can be useful
+if you want to link together objects of different file formats with
+different conventions for symbol names.  This is different from
+@code{--change-leading-char} because it always changes the symbol name
+when appropriate, regardless of the object file format of the output
+file.
+
+@item --weaken
+Change all global symbols in the file to be weak.  This can be useful
+when building an object which will be linked against other objects using
+the @code{-R} option to the linker.  This option is only effective when
+using an object file format which supports weak symbols.
+
+@item -V
+@itemx --version
+Show the version number of @code{objcopy}.
+
+@item -v
+@itemx --verbose
+Verbose output: list all object files modified.  In the case of
+archives, @samp{objcopy -V} lists all members of the archive.
+
+@item --help
+Show a summary of the options to @code{objcopy}.
+@end table
+
+@node objdump
+@chapter objdump
+
+@cindex object file information
+@kindex objdump
+
+@smallexample
+objdump [ -a | --archive-headers ] 
+        [ -b @var{bfdname} | --target=@var{bfdname} ] [ --debugging ]
+        [ -C | --demangle ] [ -d | --disassemble ]
+        [ -D | --disassemble-all ] [ --disassemble-zeroes ]
+        [ -EB | -EL | --endian=@{big | little @} ]
+        [ -f | --file-headers ]
+        [ -h | --section-headers | --headers ]  [ -i | --info ]
+        [ -j @var{section} | --section=@var{section} ]
+        [ -l | --line-numbers ] [ -S | --source ]
+        [ -m @var{machine} | --architecture=@var{machine} ]
+        [ -p | --private-headers ]
+        [ -r | --reloc ] [ -R | --dynamic-reloc ]
+        [ -s | --full-contents ]  [ --stabs ]
+        [ -t | --syms ] [ -T | --dynamic-syms ] [ -x | --all-headers ]
+        [ -w | --wide ] [ --start-address=@var{address} ]
+        [ --stop-address=@var{address} ]
+        [ --prefix-addresses] [ --[no-]show-raw-insn ]
+        [ --adjust-vma=@var{offset} ]
+        [ --version ]  [ --help ]
+        @var{objfile}@dots{}
+@end smallexample
+
+@code{objdump} displays information about one or more object files.
+The options control what particular information to display.  This
+information is mostly useful to programmers who are working on the
+compilation tools, as opposed to programmers who just want their
+program to compile and work.
+
+@var{objfile}@dots{} are the object files to be examined.  When you
+specify archives, @code{objdump} shows information on each of the member
+object files.
+
+The long and short forms of options, shown here as alternatives, are
+equivalent.  At least one option besides @samp{-l} must be given.
+
+@table @code
+@item -a
+@itemx --archive-header
+@cindex archive headers
+If any of the @var{objfile} files are archives, display the archive
+header information (in a format similar to @samp{ls -l}).  Besides the
+information you could list with @samp{ar tv}, @samp{objdump -a} shows
+the object file format of each archive member.
+
+@item --adjust-vma=@var{offset}
+@cindex section addresses in objdump
+@cindex VMA in objdump
+When dumping information, first add @var{offset} to all the section
+addresses.  This is useful if the section addresses do not correspond to
+the symbol table, which can happen when putting sections at particular
+addresses when using a format which can not represent section addresses,
+such as a.out.
+
+@item -b @var{bfdname}
+@itemx --target=@var{bfdname}
+@cindex object code format
+Specify that the object-code format for the object files is
+@var{bfdname}.  This option may not be necessary; @var{objdump} can
+automatically recognize many formats.
+
+For example,
+@example
+objdump -b oasys -m vax -h fu.o
+@end example
+@noindent
+displays summary information from the section headers (@samp{-h}) of
+@file{fu.o}, which is explicitly identified (@samp{-m}) as a VAX object
+file in the format produced by Oasys compilers.  You can list the
+formats available with the @samp{-i} option.
+@xref{Target Selection}, for more information.
+
+@item -C
+@itemx --demangle
+@cindex demangling in objdump
+Decode (@dfn{demangle}) low-level symbol names into user-level names.
+Besides removing any initial underscore prepended by the system, this
+makes C++ function names readable.  @xref{c++filt}, for more information
+on demangling.
+
+@item --debugging
+Display debugging information.  This attempts to parse debugging
+information stored in the file and print it out using a C like syntax.
+Only certain types of debugging information have been implemented.
+
+@item -d
+@itemx --disassemble
+@cindex disassembling object code
+@cindex machine instructions
+Display the assembler mnemonics for the machine instructions from
+@var{objfile}.  This option only disassembles those sections which are
+expected to contain instructions.
+
+@item -D
+@itemx --disassemble-all
+Like @samp{-d}, but disassemble the contents of all sections, not just
+those expected to contain instructions.
+
+@item --prefix-addresses
+When disassembling, print the complete address on each line.  This is
+the older disassembly format.
+
+@item --disassemble-zeroes
+Normally the disassembly output will skip blocks of zeroes.  This
+option directs the disassembler to disassemble those blocks, just like
+any other data.
+
+@item -EB
+@itemx -EL
+@itemx --endian=@{big|little@}
+@cindex endianness
+@cindex disassembly endianness
+Specify the endianness of the object files.  This only affects
+disassembly.  This can be useful when disassembling a file format which
+does not describe endianness information, such as S-records.
+
+@item -f
+@itemx --file-header
+@cindex object file header
+Display summary information from the overall header of
+each of the @var{objfile} files.
+
+@item -h
+@itemx --section-header
+@itemx --header
+@cindex section headers
+Display summary information from the section headers of the
+object file.
+
+File segments may be relocated to nonstandard addresses, for example by
+using the @samp{-Ttext}, @samp{-Tdata}, or @samp{-Tbss} options to
+@code{ld}.  However, some object file formats, such as a.out, do not
+store the starting address of the file segments.  In those situations,
+although @code{ld} relocates the sections correctly, using @samp{objdump
+-h} to list the file section headers cannot show the correct addresses.
+Instead, it shows the usual addresses, which are implicit for the
+target.
+
+@item --help
+Print a summary of the options to @code{objdump} and exit.
+
+@item -i
+@itemx --info
+@cindex architectures available
+@cindex object formats available
+Display a list showing all architectures and object formats available
+for specification with @samp{-b} or @samp{-m}.
+
+@item -j @var{name}
+@itemx --section=@var{name}
+@cindex section information
+Display information only for section @var{name}.
+
+@item -l
+@itemx --line-numbers
+@cindex source filenames for object files
+Label the display (using debugging information) with the filename and
+source line numbers corresponding to the object code or relocs shown.
+Only useful with @samp{-d}, @samp{-D}, or @samp{-r}.
+
+@item -m @var{machine}
+@itemx --architecture=@var{machine}
+@cindex architecture
+@cindex disassembly architecture
+Specify the architecture to use when disassembling object files.  This
+can be useful when disassembling object files which do not describe
+architecture information, such as S-records.  You can list the available
+architectures with the @samp{-i} option.
+
+@item -p
+@itemx --private-headers
+Print information that is specific to the object file format.  The exact
+information printed depends upon the object file format.  For some
+object file formats, no additional information is printed.
+
+@item -r
+@itemx --reloc
+@cindex relocation entries, in object file
+Print the relocation entries of the file.  If used with @samp{-d} or
+@samp{-D}, the relocations are printed interspersed with the
+disassembly.
+
+@item -R
+@itemx --dynamic-reloc
+@cindex dynamic relocation entries, in object file
+Print the dynamic relocation entries of the file.  This is only
+meaningful for dynamic objects, such as certain types of shared
+libraries.
+
+@item -s
+@itemx --full-contents
+@cindex sections, full contents
+@cindex object file sections
+Display the full contents of any sections requested.
+
+@item -S
+@itemx --source
+@cindex source disassembly
+@cindex disassembly, with source
+Display source code intermixed with disassembly, if possible.  Implies
+@samp{-d}.
+
+@item --show-raw-insn
+When disassembling instructions, print the instruction in hex as well as
+in symbolic form.  This is the default except when
+@code{--prefix-addresses} is used.
+
+@item --no-show-raw-insn
+When disassembling instructions, do not print the instruction bytes.
+This is the default when @code{--prefix-addresses} is used.
+
+@item --stabs
+@cindex stab
+@cindex .stab
+@cindex debug symbols
+@cindex ELF object file format
+Display the full contents of any sections requested.  Display the
+contents of the .stab and .stab.index and .stab.excl sections from an
+ELF file.  This is only useful on systems (such as Solaris 2.0) in which
+@code{.stab} debugging symbol-table entries are carried in an ELF
+section.  In most other file formats, debugging symbol-table entries are
+interleaved with linkage symbols, and are visible in the @samp{--syms}
+output.  For more information on stabs symbols, see @ref{Top,Stabs,Stabs
+Overview,stabs.info, The ``stabs'' debug format}.
+
+@item --start-address=@var{address}
+@cindex start-address
+Start displaying data at the specified address.  This affects the output
+of the @code{-d}, @code{-r} and @code{-s} options.
+
+@item --stop-address=@var{address}
+@cindex stop-address
+Stop displaying data at the specified address.  This affects the output
+of the @code{-d}, @code{-r} and @code{-s} options.
+
+@item -t
+@itemx --syms
+@cindex symbol table entries, printing
+Print the symbol table entries of the file.
+This is similar to the information provided by the @samp{nm} program.
+
+@item -T
+@itemx --dynamic-syms
+@cindex dynamic symbol table entries, printing
+Print the dynamic symbol table entries of the file.  This is only
+meaningful for dynamic objects, such as certain types of shared
+libraries.  This is similar to the information provided by the @samp{nm}
+program when given the @samp{-D} (@samp{--dynamic}) option.
+
+@item --version
+Print the version number of @code{objdump} and exit.
+
+@item -x
+@itemx --all-header
+@cindex all header information, object file
+@cindex header information, all
+Display all available header information, including the symbol table and
+relocation entries.  Using @samp{-x} is equivalent to specifying all of
+@samp{-a -f -h -r -t}.
+
+@item -w
+@itemx --wide
+@cindex wide output, printing
+Format some lines for output devices that have more than 80 columns.
+@end table
+
+@node ranlib
+@chapter ranlib
+
+@kindex ranlib
+@cindex archive contents
+@cindex symbol index
+
+@smallexample
+ranlib [-vV] @var{archive}
+@end smallexample
+
+@code{ranlib} generates an index to the contents of an archive and
+stores it in the archive.  The index lists each symbol defined by a
+member of an archive that is a relocatable object file.  
+
+You may use @samp{nm -s} or @samp{nm --print-armap} to list this index.
+
+An archive with such an index speeds up linking to the library and
+allows routines in the library to call each other without regard to
+their placement in the archive.
+
+The @sc{gnu} @code{ranlib} program is another form of @sc{gnu} @code{ar}; running
+@code{ranlib} is completely equivalent to executing @samp{ar -s}.
+@xref{ar}.
+
+@table @code
+@item -v
+@itemx -V
+Show the version number of @code{ranlib}.
+@end table
+
+@node size
+@chapter size
+
+@kindex size
+@cindex section sizes
+
+@smallexample
+size [ -A | -B | --format=@var{compatibility} ]
+     [ --help ]  [ -d | -o | -x | --radix=@var{number} ]
+     [ --target=@var{bfdname} ]  [ -V | --version ]  
+     [ @var{objfile}@dots{} ]
+@end smallexample
+
+The @sc{gnu} @code{size} utility lists the section sizes---and the total
+size---for each of the object or archive files @var{objfile} in its
+argument list.  By default, one line of output is generated for each
+object file or each module in an archive.
+
+@var{objfile}@dots{} are the object files to be examined.
+If none are specified, the file @code{a.out} will be used.
+
+The command line options have the following meanings:
+
+@table @code
+@item -A
+@itemx -B
+@itemx --format=@var{compatibility}
+@cindex @code{size} display format
+Using one of these options, you can choose whether the output from @sc{gnu}
+@code{size} resembles output from System V @code{size} (using @samp{-A},
+or @samp{--format=sysv}), or Berkeley @code{size} (using @samp{-B}, or
+@samp{--format=berkeley}).  The default is the one-line format similar to
+Berkeley's.  
+@c Bonus for doc-source readers: you can also say --format=strange (or
+@c anything else that starts with 's') for sysv, and --format=boring (or
+@c anything else that starts with 'b') for Berkeley.
+
+Here is an example of the Berkeley (default) format of output from
+@code{size}: 
+@smallexample
+size --format=Berkeley ranlib size
+text    data    bss     dec     hex     filename
+294880  81920   11592   388392  5ed28   ranlib
+294880  81920   11888   388688  5ee50   size
+@end smallexample
+
+@noindent
+This is the same data, but displayed closer to System V conventions:
+
+@smallexample
+size --format=SysV ranlib size
+ranlib  :
+section         size         addr
+.text         294880         8192       
+.data          81920       303104       
+.bss           11592       385024       
+Total         388392    
+
+
+size  :
+section         size         addr
+.text         294880         8192       
+.data          81920       303104       
+.bss           11888       385024       
+Total         388688    
+@end smallexample
+
+@item --help
+Show a summary of acceptable arguments and options.
+
+@item -d
+@itemx -o
+@itemx -x
+@itemx --radix=@var{number}
+@cindex @code{size} number format
+@cindex radix for section sizes
+Using one of these options, you can control whether the size of each
+section is given in decimal (@samp{-d}, or @samp{--radix=10}); octal
+(@samp{-o}, or @samp{--radix=8}); or hexadecimal (@samp{-x}, or
+@samp{--radix=16}).  In @samp{--radix=@var{number}}, only the three
+values (8, 10, 16) are supported.  The total size is always given in two
+radices; decimal and hexadecimal for @samp{-d} or @samp{-x} output, or
+octal and hexadecimal if you're using @samp{-o}.
+
+@item --target=@var{bfdname}
+@cindex object code format
+Specify that the object-code format for @var{objfile} is
+@var{bfdname}.  This option may not be necessary; @code{size} can
+automatically recognize many formats.
+@xref{Target Selection}, for more information.
+
+@item -V
+@itemx --version
+Display the version number of @code{size}.
+@end table
+
+@node strings
+@chapter strings
+@kindex strings
+@cindex listings strings
+@cindex printing strings
+@cindex strings, printing
+
+@smallexample
+strings [-afov] [-@var{min-len}] [-n @var{min-len}] [-t @var{radix}] [-]
+        [--all] [--print-file-name] [--bytes=@var{min-len}]
+        [--radix=@var{radix}] [--target=@var{bfdname}]
+        [--help] [--version] @var{file}@dots{}
+@end smallexample
+
+For each @var{file} given, @sc{gnu} @code{strings} prints the printable
+character sequences that are at least 4 characters long (or the number
+given with the options below) and are followed by an unprintable
+character.  By default, it only prints the strings from the initialized
+and loaded sections of object files; for other types of files, it prints
+the strings from the whole file.
+
+@code{strings} is mainly useful for determining the contents of non-text
+files.
+
+@table @code
+@item -a
+@itemx --all
+@itemx -
+Do not scan only the initialized and loaded sections of object files;
+scan the whole files.
+
+@item -f
+@itemx --print-file-name
+Print the name of the file before each string.
+
+@item --help
+Print a summary of the program usage on the standard output and exit.
+
+@item -@var{min-len}
+@itemx -n @var{min-len}
+@itemx --bytes=@var{min-len}
+Print sequences of characters that are at least @var{min-len} characters
+long, instead of the default 4.
+
+@item -o
+Like @samp{-t o}.  Some other versions of @code{strings} have @samp{-o}
+act like @samp{-t d} instead.  Since we can not be compatible with both
+ways, we simply chose one.
+
+@item -t @var{radix}
+@itemx --radix=@var{radix}
+Print the offset within the file before each string.  The single
+character argument specifies the radix of the offset---@samp{o} for
+octal, @samp{x} for hexadecimal, or @samp{d} for decimal.
+
+@item --target=@var{bfdname}
+@cindex object code format
+Specify an object code format other than your system's default format.
+@xref{Target Selection}, for more information.
+
+@item -v
+@itemx --version
+Print the program version number on the standard output and exit.
+@end table
+
+@node strip
+@chapter strip
+
+@kindex strip
+@cindex removing symbols
+@cindex discarding symbols
+@cindex symbols, discarding
+
+@smallexample
+strip [ -F @var{bfdname} | --target=@var{bfdname} ]
+      [ -I @var{bfdname} | --input-target=@var{bfdname} ]
+      [ -O @var{bfdname} | --output-target=@var{bfdname} ]
+      [ -s | --strip-all ] [ -S | -g | --strip-debug ]
+      [ -K @var{symbolname} | --keep-symbol=@var{symbolname} ]
+      [ -N @var{symbolname} | --strip-symbol=@var{symbolname} ]
+      [ -x | --discard-all ] [ -X | --discard-locals ]
+      [ -R @var{sectionname} | --remove-section=@var{sectionname} ]
+      [ -o @var{file} ] [ -p | --preserve-dates ]
+      [ -v | --verbose ]  [ -V | --version ]  [ --help ]
+      @var{objfile}@dots{}
+@end smallexample
+
+@sc{gnu} @code{strip} discards all symbols from object files
+@var{objfile}.  The list of object files may include archives.
+At least one object file must be given.
+
+@code{strip} modifies the files named in its argument,
+rather than writing modified copies under different names.
+
+@table @code
+@item -F @var{bfdname}
+@itemx --target=@var{bfdname}
+Treat the original @var{objfile} as a file with the object
+code format @var{bfdname}, and rewrite it in the same format.
+@xref{Target Selection}, for more information.
+
+@item --help
+Show a summary of the options to @code{strip} and exit.
+
+@item -I @var{bfdname} 
+@itemx --input-target=@var{bfdname}
+Treat the original @var{objfile} as a file with the object
+code format @var{bfdname}.
+@xref{Target Selection}, for more information.
+
+@item -O @var{bfdname}
+@itemx --output-target=@var{bfdname}
+Replace @var{objfile} with a file in the output format @var{bfdname}.
+@xref{Target Selection}, for more information.
+
+@item -R @var{sectionname}
+@itemx --remove-section=@var{sectionname}
+Remove any section named @var{sectionname} from the output file.  This
+option may be given more than once.  Note that using this option
+inappropriately may make the output file unusable.
+
+@item -s
+@itemx --strip-all
+Remove all symbols.
+
+@item -g
+@itemx -S
+@itemx --strip-debug
+Remove debugging symbols only.
+
+@item --strip-unneeded
+Remove all symbols that are not needed for relocation processing.
+
+@item -K @var{symbolname}
+@itemx --keep-symbol=@var{symbolname}
+Keep only symbol @var{symbolname} from the source file.  This option may
+be given more than once.
+
+@item -N @var{symbolname}
+@itemx --strip-symbol=@var{symbolname}
+Remove symbol @var{symbolname} from the source file. This option may be
+given more than once, and may be combined with strip options other than
+@code{-K}.
+
+@item -o @var{file}
+Put the stripped output in @var{file}, rather than replacing the
+existing file.  When this argument is used, only one @var{objfile}
+argument may be specified.
+
+@item -p
+@itemx --preserve-dates
+Preserve the access and modification dates of the file.
+
+@item -x
+@itemx --discard-all
+Remove non-global symbols.
+
+@item -X
+@itemx --discard-locals
+Remove compiler-generated local symbols.
+(These usually start with @samp{L} or @samp{.}.)
+
+@item -V
+@itemx --version
+Show the version number for @code{strip}.
+
+@item -v
+@itemx --verbose
+Verbose output: list all object files modified.  In the case of
+archives, @samp{strip -v} lists all members of the archive.
+@end table
+
+@node c++filt
+@chapter c++filt
+
+@kindex c++filt
+@cindex demangling C++ symbols
+
+@smallexample
+c++filt [ -_ | --strip-underscores ]
+        [ -j | --java ]
+       [ -n | --no-strip-underscores ]
+        [ -s @var{format} | --format=@var{format} ]
+        [ --help ]  [ --version ]  [ @var{symbol}@dots{} ]
+@end smallexample
+
+The C++ and Java languages provides function overloading, which means
+that you can write many functions with the same name (providing each
+takes parameters of different types).  All C++ and Java function names
+are encoded into a low-level assembly label (this process is known as
+@dfn{mangling}). The @code{c++filt} program does the inverse mapping: it
+decodes (@dfn{demangles}) low-level names into user-level names so that
+the linker can keep these overloaded functions from clashing.
+
+Every alphanumeric word (consisting of letters, digits, underscores,
+dollars, or periods) seen in the input is a potential label.  If the
+label decodes into a C++ name, the C++ name replaces the low-level
+name in the output.
+
+You can use @code{c++filt} to decipher individual symbols:
+
+@example
+c++filt @var{symbol}
+@end example
+
+If no @var{symbol} arguments are given, @code{c++filt} reads symbol
+names from the standard input and writes the demangled names to the
+standard output.  All results are printed on the standard output.
+
+@table @code
+@item -_
+@itemx --strip-underscores
+On some systems, both the C and C++ compilers put an underscore in front
+of every name.  For example, the C name @code{foo} gets the low-level
+name @code{_foo}.  This option removes the initial underscore.  Whether
+@code{c++filt} removes the underscore by default is target dependent.
+
+@item -j
+@itemx --java
+Prints demangled names using Java syntax.  The default is to use C++
+syntax.
+
+@item -n
+@itemx --no-strip-underscores
+Do not remove the initial underscore.
+
+@item -s @var{format}
+@itemx --format=@var{format}
+@sc{gnu} @code{nm} can decode three different methods of mangling, used by
+different C++ compilers.  The argument to this option selects which
+method it uses:
+
+@table @code
+@item gnu
+the one used by the @sc{gnu} compiler (the default method)
+@item lucid
+the one used by the Lucid compiler
+@item arm
+the one specified by the C++ Annotated Reference Manual
+@item hp
+the one used by the HP compiler
+@item edg
+the one used by the EDG compiler
+@end table
+
+@item --help
+Print a summary of the options to @code{c++filt} and exit.
+
+@item --version
+Print the version number of @code{c++filt} and exit.
+@end table
+
+@quotation
+@emph{Warning:} @code{c++filt} is a new utility, and the details of its
+user interface are subject to change in future releases.  In particular,
+a command-line option may be required in the the future to decode a name
+passed as an argument on the command line; in other words, 
+
+@example
+c++filt @var{symbol}
+@end example
+
+@noindent
+may in a future release become
+
+@example
+c++filt @var{option} @var{symbol}
+@end example
+@end quotation
+
+@node addr2line
+@chapter addr2line
+
+@kindex addr2line
+@cindex address to file name and line number
+
+@smallexample
+addr2line [ -b @var{bfdname} | --target=@var{bfdname} ]
+          [ -C | --demangle ]
+          [ -e @var{filename} | --exe=@var{filename} ]
+          [ -f | --functions ] [ -s | --basename ]
+          [ -H | --help ] [ -V | --version ]
+          [ addr addr ... ]
+@end smallexample
+
+@code{addr2line} translates program addresses into file names and line
+numbers.  Given an address and an executable, it uses the debugging
+information in the executable to figure out which file name and line
+number are associated with a given address.
+
+The executable to use is specified with the @code{-e} option.  The
+default is @file{a.out}.
+
+@code{addr2line} has two modes of operation.
+
+In the first, hexadecimal addresses are specified on the command line,
+and @code{addr2line} displays the file name and line number for each
+address.
+
+In the second, @code{addr2line} reads hexadecimal addresses from
+standard input, and prints the file name and line number for each
+address on standard output.  In this mode, @code{addr2line} may be used
+in a pipe to convert dynamically chosen addresses.
+
+The format of the output is @samp{FILENAME:LINENO}.  The file name and
+line number for each address is printed on a separate line.  If the
+@code{-f} option is used, then each @samp{FILENAME:LINENO} line is
+preceded by a @samp{FUNCTIONNAME} line which is the name of the function
+containing the address.
+
+If the file name or function name can not be determined,
+@code{addr2line} will print two question marks in their place.  If the
+line number can not be determined, @code{addr2line} will print 0.
+
+The long and short forms of options, shown here as alternatives, are
+equivalent.
+
+@table @code
+@item -b @var{bfdname}
+@itemx --target=@var{bfdname}
+@cindex object code format
+Specify that the object-code format for the object files is
+@var{bfdname}.
+
+@item -C
+@itemx --demangle
+@cindex demangling in objdump
+Decode (@dfn{demangle}) low-level symbol names into user-level names.
+Besides removing any initial underscore prepended by the system, this
+makes C++ function names readable.  @xref{c++filt}, for more information
+on demangling.
+
+@item -e @var{filename}
+@itemx --exe=@var{filename}
+Specify the name of the executable for which addresses should be
+translated.  The default file is @file{a.out}.
+
+@item -f
+@itemx --functions
+Display function names as well as file and line number information.
+
+@item -s
+@itemx --basenames
+Display only the base of each file name.
+@end table
+
+@node nlmconv
+@chapter nlmconv
+
+@code{nlmconv} converts a relocatable object file into a NetWare
+Loadable Module.
+
+@ignore
+@code{nlmconv} currently works with @samp{i386} object
+files in @code{coff}, @sc{elf}, or @code{a.out} format, and @sc{SPARC}
+object files in @sc{elf}, or @code{a.out} format@footnote{
+@code{nlmconv} should work with any @samp{i386} or @sc{sparc} object
+format in the Binary File Descriptor library.  It has only been tested
+with the above formats.}.
+@end ignore
+
+@quotation
+@emph{Warning:} @code{nlmconv} is not always built as part of the binary
+utilities, since it is only useful for NLM targets.
+@end quotation
+
+@smallexample
+nlmconv [ -I @var{bfdname} | --input-target=@var{bfdname} ]
+        [ -O @var{bfdname} | --output-target=@var{bfdname} ]
+        [ -T @var{headerfile} | --header-file=@var{headerfile} ]
+        [ -d | --debug]  [ -l @var{linker} | --linker=@var{linker} ]
+        [ -h | --help ]  [ -V | --version ]
+        @var{infile} @var{outfile}
+@end smallexample
+
+@code{nlmconv} converts the relocatable @samp{i386} object file
+@var{infile} into the NetWare Loadable Module @var{outfile}, optionally
+reading @var{headerfile} for NLM header information.  For instructions
+on writing the NLM command file language used in header files, see the
+@samp{linkers} section, @samp{NLMLINK} in particular, of the @cite{NLM
+Development and Tools Overview}, which is part of the NLM Software
+Developer's Kit (``NLM SDK''), available from Novell, Inc.
+@code{nlmconv} uses the @sc{gnu} Binary File Descriptor library to read
+@var{infile}; see @ref{BFD,,BFD,ld.info,Using LD}, for
+more information.
+
+@code{nlmconv} can perform a link step.  In other words, you can list
+more than one object file for input if you list them in the definitions
+file (rather than simply specifying one input file on the command line).
+In this case, @code{nlmconv} calls the linker for you.
+
+@table @code
+@item -I @var{bfdname}
+@itemx --input-target=@var{bfdname}
+Object format of the input file.  @code{nlmconv} can usually determine
+the format of a given file (so no default is necessary).
+@xref{Target Selection}, for more information.
+
+@item -O @var{bfdname}
+@itemx --output-target=@var{bfdname}
+Object format of the output file.  @code{nlmconv} infers the output
+format based on the input format, e.g. for a @samp{i386} input file the
+output format is @samp{nlm32-i386}.
+@xref{Target Selection}, for more information.
+
+@item -T @var{headerfile}
+@itemx --header-file=@var{headerfile}
+Reads @var{headerfile} for NLM header information.  For instructions on
+writing the NLM command file language used in header files, see@ see the
+@samp{linkers} section, of the @cite{NLM Development and Tools
+Overview}, which is part of the NLM Software Developer's Kit, available
+from Novell, Inc.
+
+@item -d
+@itemx --debug
+Displays (on standard error) the linker command line used by @code{nlmconv}.
+
+@item -l @var{linker}
+@itemx --linker=@var{linker}
+Use @var{linker} for any linking.  @var{linker} can be an absolute or a
+relative pathname.
+
+@item -h
+@itemx --help
+Prints a usage summary.
+
+@item -V
+@itemx --version
+Prints the version number for @code{nlmconv}.
+@end table
+
+@node windres
+@chapter windres
+
+@code{windres} may be used to manipulate Windows resources.
+
+@quotation
+@emph{Warning:} @code{windres} is not always built as part of the binary
+utilities, since it is only useful for Windows targets.
+@end quotation
+
+@smallexample
+windres [options] [input-file] [output-file]
+@end smallexample
+
+@code{windres} reads resources from an input file and copies them into
+an output file.  Either file may be in one of three formats:
+
+@table @code
+@item rc
+A text format read by the Resource Compiler.
+
+@item res
+A binary format generated by the Resource Compiler.
+
+@item coff
+A COFF object or executable.
+@end table
+
+The exact description of these different formats is available in
+documentation from Microsoft.
+
+When @code{windres} converts from the @code{rc} format to the @code{res}
+format, it is acting like the Windows Resource Compiler.  When
+@code{windres} converts from the @code{res} format to the @code{coff}
+format, it is acting like the Windows @code{CVTRES} program.
+
+When @code{windres} generates an @code{rc} file, the output is similar
+but not identical to the format expected for the input.  When an input
+@code{rc} file refers to an external filename, an output @code{rc} file
+will instead include the file contents.
+
+If the input or output format is not specified, @code{windres} will
+guess based on the file name, or, for the input file, the file contents.
+A file with an extension of @file{.rc} will be treated as an @code{rc}
+file, a file with an extension of @file{.res} will be treated as a
+@code{res} file, and a file with an extension of @file{.o} or
+@file{.exe} will be treated as a @code{coff} file.
+
+If no output file is specified, @code{windres} will print the resources
+in @code{rc} format to standard output.
+
+The normal use is for you to write an @code{rc} file, use @code{windres}
+to convert it to a COFF object file, and then link the COFF file into
+your application.  This will make the resources described in the
+@code{rc} file available to Windows.
+
+@table @code
+@item -i @var{filename}
+@itemx --input @var{filename}
+The name of the input file.  If this option is not used, then
+@code{windres} will use the first non-option argument as the input file
+name.  If there are no non-option arguments, then @code{windres} will
+read from standard input.  @code{windres} can not read a COFF file from
+standard input.
+
+@item -o @var{filename}
+@itemx --output @var{filename}
+The name of the output file.  If this option is not used, then
+@code{windres} will use the first non-option argument, after any used
+for the input file name, as the output file name.  If there is no
+non-option argument, then @code{windres} will write to standard output.
+@code{windres} can not write a COFF file to standard output.
+
+@item -I @var{format}
+@itemx --input-format @var{format}
+The input format to read.  @var{format} may be @samp{res}, @samp{rc}, or
+@samp{coff}.  If no input format is specified, @code{windres} will
+guess, as described above.
+
+@item -O @var{format}
+@itemx --output-format @var{format}
+The output format to generate.  @var{format} may be @samp{res},
+@samp{rc}, or @samp{coff}.  If no output format is specified,
+@code{windres} will guess, as described above.
+
+@item -F @var{target}
+@itemx --target @var{target}
+Specify the BFD format to use for a COFF file as input or output.  This
+is a BFD target name; you can use the @code{--help} option to see a list
+of supported targets.  Normally @code{windres} will use the default
+format, which is the first one listed by the @code{--help} option.
+@ref{Target Selection}.
+
+@item --preprocessor @var{program}
+When @code{windres} reads an @code{rc} file, it runs it through the C
+preprocessor first.  This option may be used to specify the preprocessor
+to use, including any leading arguments.  The default preprocessor
+argument is @code{gcc -E -xc-header -DRC_INVOKED}.
+
+@item --include-dir @var{directory}
+Specify an include directory to use when reading an @code{rc} file.
+@code{windres} will pass this to the preprocessor as an @code{-I}
+option.  @code{windres} will also search this directory when looking for
+files named in the @code{rc} file.
+
+@item --define @var{sym[=val]}
+Specify a @code{-D} option to pass to the preprocessor when reading an
+@code{rc} file.
+
+@item --language @var{val}
+Specify the default language to use when reading an @code{rc} file.
+@var{val} should be a hexadecimal language code.  The low eight bits are
+the language, and the high eight bits are the sublanguage.
+
+@item --help
+Prints a usage summary.
+
+@item --version
+Prints the version number for @code{windres}.
+
+@item --yydebug
+If @code{windres} is compiled with @code{YYDEBUG} defined as @code{1},
+this will turn on parser debugging.
+@end table
+
+
+@node dlltool
+@chapter Create files needed to build and use DLLs
+@cindex DLL
+@kindex dlltool
+
+@code{dlltool} may be used to create the files needed to build and use
+dynamic link libraries (DLLs).
+
+@quotation
+@emph{Warning:} @code{dlltool} is not always built as part of the binary
+utilities, since it is only useful for those targets which support DLLs.
+@end quotation
+
+@smallexample
+dlltool [-d|--input-def @var{def-file-name}]
+        [-b|--base-file @var{base-file-name}]
+        [-e|--output-exp @var{exports-file-name}]
+        [-z|--output-def @var{def-file-name}]
+        [-l|--output-lib @var{library-file-name}]        
+        [--export-all-symbols] [--no-export-all-symbols]
+        [--exclude-symbols @var{list}]
+        [--no-default-excludes]
+        [-S|--as @var{path-to-assembler}] [-f|--as-flags @var{options}]
+        [-D|--dllname @var{name}] [-m|--machine @var{machine}]
+        [-a|--add-indirect] [-U|--add-underscore] [-k|--kill-at]
+        [-A|--add-stdcall-alias]
+        [-x|--no-idata4] [-c|--no-idata5] [-i|--interwork]
+        [-n|--nodelete] [-v|--verbose] [-h|--help] [-V|--version]
+        [object-file @dots{}]
+@end smallexample
+
+@code{dlltool} reads its inputs, which can come from the @samp{-d} and
+@samp{-b} options as well as object files specified on the command
+line.  It then processes these inputs and if the @samp{-e} option has
+been specified it creates a exports file.  If the @samp{-l} option
+has been specified it creates a library file and if the @samp{-z} option
+has been specified it creates a def file.  Any or all of the -e, -l
+and -z options can be present in one invocation of dlltool.
+
+When creating a DLL, along with the source for the DLL, it is necessary
+to have three other files.  @code{dlltool} can help with the creation of
+these files.
+
+The first file is a @samp{.def} file which specifies which functions are
+exported from the DLL, which functions the DLL imports, and so on.  This
+is a text file and can be created by hand, or @code{dlltool} can be used
+to create it using the @samp{-z} option.  In this case @code{dlltool}
+will scan the object files specified on its command line looking for
+those functions which have been specially marked as being exported and
+put entries for them in the .def file it creates.
+
+In order to mark a function as being exported from a DLL, it needs to
+have an @samp{-export:<name_of_function>} entry in the @samp{.drectve}
+section of the object file.  This can be done in C by using the
+asm() operator:
+
+@smallexample
+  asm (".section .drectve");  
+  asm (".ascii \"-export:my_func\"");
+
+  int my_func (void) @{ @dots{} @}
+@end smallexample
+
+The second file needed for DLL creation is an exports file.  This file
+is linked with the object files that make up the body of the DLL and it
+handles the interface between the DLL and the outside world.  This is a
+binary file and it can be created by giving the @samp{-e} option to
+@code{dlltool} when it is creating or reading in a .def file. 
+
+The third file needed for DLL creation is the library file that programs
+will link with in order to access the functions in the DLL.  This file
+can be created by giving the @samp{-l} option to dlltool when it
+is creating or reading in a .def file.
+
+@code{dlltool} builds the library file by hand, but it builds the
+exports file by creating temporary files containing assembler statements
+and then assembling these.  The @samp{-S} command line option can be
+used to specify the path to the assembler that dlltool will use,
+and the @samp{-f} option can be used to pass specific flags to that
+assembler.  The @samp{-n} can be used to prevent dlltool from deleting
+these temporary assembler files when it is done, and if @samp{-n} is
+specified twice then this will prevent dlltool from deleting the
+temporary object files it used to build the library.
+
+Here is an example of creating a DLL from a source file @samp{dll.c} and
+also creating a program (from an object file called @samp{program.o})
+that uses that DLL:
+
+@smallexample
+  gcc -c dll.c
+  dlltool -e exports.o -l dll.lib dll.o
+  gcc dll.o exports.o -o dll.dll
+  gcc program.o dll.lib -o program
+@end smallexample
+
+The command line options have the following meanings:
+
+@table @code
+
+@item -d @var{filename}
+@itemx --input-def @var{filename}
+@cindex input .def file
+Specifies the name of a .def file to be read in and processed.
+
+@item -b @var{filename}
+@itemx --base-file @var{filename}
+@cindex base files
+Specifies the name of a base file to be read in and processed.  The
+contents of this file will be added to the relocation section in the
+exports file generated by dlltool.
+
+@item -e @var{filename}
+@itemx --output-exp @var{filename}
+Specifies the name of the export file to be created by dlltool.
+
+@item -z @var{filename}
+@itemx --output-def @var{filename}
+Specifies the name of the .def file to be created by dlltool.
+
+@item -l @var{filename}
+@itemx --output-lib @var{filename}
+Specifies the name of the library file to be created by dlltool.
+
+@item --export-all-symbols
+Treat all global and weak defined symbols found in the input object
+files as symbols to be exported.  There is a small list of symbols which
+are not exported by default; see the @code{--no-default-excludes}
+option.  You may add to the list of symbols to not export by using the
+@code{--exclude-symbols} option.
+
+@item --no-export-all-symbols
+Only export symbols explicitly listed in an input .def file or in
+@samp{.drectve} sections in the input object files.  This is the default
+behaviour.  The @samp{.drectve} sections are created by @samp{dllexport}
+attributes in the source code.
+
+@item --exclude-symbols @var{list}
+Do not export the symbols in @var{list}.  This is a list of symbol names
+separated by comma or colon characters.  The symbol names should not
+contain a leading underscore.  This is only meaningful when
+@code{--export-all-symbols} is used.
+
+@item --no-default-excludes
+When @code{--export-all-symbols} is used, it will by default avoid
+exporting certain special symbols.  The current list of symbols to avoid
+exporting is @samp{DllMain@@12}, @samp{DllEntryPoint@@0},
+@samp{impure_ptr}.  You may use the @code{--no-default-excludes} option
+to go ahead and export these special symbols.  This is only meaningful
+when @code{--export-all-symbols} is used.
+
+@item -S @var{path}
+@itemx --as @var{path}
+Specifies the path, including the filename, of the assembler to be used
+to create the exports file.
+
+@item -f @var{switches}
+@itemx --as-flags @var{switches}
+Specifies any specific command line switches to be passed to the
+assembler when building the exports file.  This option will work even if
+the @samp{-S} option is not used.  This option only takes one argument,
+and if it occurs more than once on the command line, then later
+occurrences will override earlier occurrences.  So if it is necessary to
+pass multiple switches to the assembler they should be enclosed in
+double quotes.
+
+@item -D @var{name}
+@itemx --dll-name @var{name}
+Specifies the name to be stored in the .def file as the name of the DLL
+when the @samp{-e} option is used.  If this option is not present, then
+the filename given to the @samp{-e} option will be used as the name of
+the DLL.
+
+@item -m @var{machine}
+@itemx -machine @var{machine}
+Specifies the type of machine for which the library file should be
+built.  @code{dlltool} has a built in default type, depending upon how
+it was created, but this option can be used to override that.  This is
+normally only useful when creating DLLs for an ARM processor, when the
+contents of the DLL are actually encode using THUMB instructions.
+
+@item -a
+@itemx --add-indirect
+Specifies that when @code{dlltool} is creating the exports file it
+should add a section which allows the exported functions to be
+referenced without using the import library.  Whatever the hell that
+means! 
+
+@item -U
+@itemx --add-underscore
+Specifies that when @code{dlltool} is creating the exports file it
+should prepend an underscore to the names of the exported functions. 
+
+@item -k
+@itemx --kill-at
+Specifies that when @code{dlltool} is creating the exports file it
+should not append the string @samp{@@ <number>}.  These numbers are
+called ordinal numbers and they represent another way of accessing the
+function in a DLL, other than by name.
+
+@item -A
+@itemx --add-stdcall-alias
+Specifies that when @code{dlltool} is creating the exports file it
+should add aliases for stdcall symbols without @samp{@@ <number>}
+in addition to the symbols with @samp{@@ <number>}.
+
+@item -x
+@itemx --no-idata4
+Specifies that when @code{dlltool} is creating the exports and library
+files it should omit the .idata4 section.  This is for compatibility
+with certain operating systems.
+
+@item -c
+@itemx --no-idata5
+Specifies that when @code{dlltool} is creating the exports and library
+files it should omit the .idata5 section.  This is for compatibility
+with certain operating systems.
+
+@item -i
+@itemx --interwork
+Specifies that @code{dlltool} should mark the objects in the library
+file and exports file that it produces as supporting interworking
+between ARM and THUMB code.
+
+@item -n
+@itemx --nodelete
+Makes @code{dlltool} preserve the temporary assembler files it used to
+create the exports file.  If this option is repeated then dlltool will
+also preserve the temporary object files it uses to create the library
+file. 
+
+@item -v
+@itemx --verbose
+Make dlltool describe what it is doing.
+
+@item -h
+@itemx --help
+Displays a list of command line options and then exits.
+
+@item -V
+@itemx --version
+Displays dlltool's version number and then exits.
+
+@end table
+
+@node readelf
+@chapter readelf
+
+@cindex ELF file information
+@kindex readelf
+
+@smallexample
+readelf [ -a | --all ] 
+        [ -h | --file-header]
+        [ -l | --program-headers | --segments]
+        [ -S | --section-headers | --sections]
+        [ -e | --headers]
+        [ -s | --syms | --symbols]
+        [ -r | --relocs]
+        [ -d | --dynamic]
+        [ -V | --version-info]
+        [ -D | --use-dynamic]
+        [ -x <number> | --hex-dump=<number>]
+        [ -w[liapr] | --debug-dump[=info,=line,=abbrev,=pubnames,=ranges]]
+        [      --histogram]
+        [ -v | --version]
+        [ -H | --help]
+        @var{elffile}@dots{}
+@end smallexample
+
+@code{readelf} displays information about one or more ELF format object
+files.  The options control what particular information to display.
+
+@var{elffile}@dots{} are the object files to be examined.  At the
+moment, @code{readelf} does not support examining archives, nor does it
+support examing 64 bit ELF files.
+
+The long and short forms of options, shown here as alternatives, are
+equivalent.  At least one option besides @samp{-v} or @samp{-H} must be
+given. 
+
+@table @code
+@item -a
+@itemx --all
+Equivalent to specifiying @samp{--file-header},
+@samp{--program-headers}, @samp{--sections}, @samp{--symbols},
+@samp{--relocs}, @samp{--dynamic} and @samp{--version-info}.
+
+@item -h
+@itemx --file-header
+@cindex ELF file header information
+Displays the information contained in the ELF header at the start of the
+file.
+
+@item -l
+@itemx --program-headers
+@itemx --segments
+@cindex ELF program header information
+@cindex ELF segment information
+Displays the information contained in the file's segment headers, if it
+has any.
+
+@item -S
+@itemx --sections
+@itemx --section-headers
+@cindex ELF section information
+Displays the information contained in the file's section headers, if it
+has any.
+
+@item -s
+@itemx --symbols
+@itemx --syms
+@cindex ELF symbol table information
+Displays the entries in symbol table section of the file, if it has one.
+
+@item -e
+@itemx --headers
+Display all the headers in the file.  Equivalent to @samp{-h -l -S}.
+
+@item -r
+@itemx --relocs
+@cindex ELF reloc information
+Displays the contents of the file's relocation section, if it ha one.
+
+@item -d
+@itemx --dynamic
+@cindex ELF dynamic section information
+Displays the contents of the file's dynamic section, if it has one.
+
+@item -V
+@itemx --version-info
+@cindex ELF version sections informations
+Displays the contents of the version sections in the file, it they
+exist.
+
+@item -D
+@itemx --use-dynamic
+When displaying symbols, this option makes @code{readelf} use the
+symblol table in the file's dynamic section, rather than the one in the
+symbols section.
+
+@item -x <number>
+@itemx --hex-dump=<number>
+Displays the contents of the indicated section as a hexadecimal dump.
+
+@item -w[liapr]
+@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=ranges]
+Displays the contents of the debug sections in the file, if any are
+present.  If one of the optional letters or words follows the switch
+then only data found in those specific sections will be dumped.
+
+@item --histogram
+Display a histogram of bucket list lengths when displaying the contents
+of the symbol tables.
+
+@item -v
+@itemx --version
+Display the version number of readelf.
+
+@item -H
+@itemx --help
+Display the command line options understood by @code{readelf}.
+
+@end table
+
+
+@node Selecting The Target System
+@chapter Selecting the target system
+
+You can specify three aspects of the target system to the @sc{gnu}
+binary file utilities, each in several ways:
+
+@itemize @bullet
+@item
+the target
+
+@item
+the architecture
+
+@item
+the linker emulation (which applies to the linker only)
+@end itemize
+
+In the following summaries, the lists of ways to specify values are in
+order of decreasing precedence.  The ways listed first override those
+listed later.
+
+The commands to list valid values only list the values for which the
+programs you are running were configured.  If they were configured with
+@samp{--enable-targets=all}, the commands list most of the available
+values, but a few are left out; not all targets can be configured in at
+once because some of them can only be configured @dfn{native} (on hosts
+with the same type as the target system).
+
+@menu
+* Target Selection::            
+* Architecture Selection::      
+* Linker Emulation Selection::  
+@end menu
+
+@node Target Selection
+@section Target Selection
+
+A @dfn{target} is an object file format.  A given target may be
+supported for multiple architectures (@pxref{Architecture Selection}).
+A target selection may also have variations for different operating
+systems or architectures.
+
+The command to list valid target values is @samp{objdump -i}
+(the first column of output contains the relevant information).
+
+Some sample values are: @samp{a.out-hp300bsd}, @samp{ecoff-littlemips},
+@samp{a.out-sunos-big}.
+
+You can also specify a target using a configuration triplet.  This is
+the same sort of name that is passed to configure to specify a target.
+When you use a configuration triplet as an argument, it must be fully
+canonicalized.  You can see the canonical version of a triplet by
+running the shell script @file{config.sub} which is included with the
+sources.
+
+Some sample configuration triplets are: @samp{m68k-hp-bsd},
+@samp{mips-dec-ultrix}, @samp{sparc-sun-sunos}.
+
+@subheading @code{objdump} Target
+
+Ways to specify:
+
+@enumerate
+@item
+command line option: @samp{-b} or @samp{--target}
+
+@item
+environment variable @code{GNUTARGET}
+
+@item
+deduced from the input file
+@end enumerate
+
+@subheading @code{objcopy} and @code{strip} Input Target
+
+Ways to specify:
+
+@enumerate
+@item
+command line options: @samp{-I} or @samp{--input-target}, or @samp{-F} or @samp{--target}
+
+@item
+environment variable @code{GNUTARGET}
+
+@item
+deduced from the input file
+@end enumerate
+
+@subheading @code{objcopy} and @code{strip} Output Target
+
+Ways to specify:
+
+@enumerate
+@item
+command line options: @samp{-O} or @samp{--output-target}, or @samp{-F} or @samp{--target}
+
+@item
+the input target (see ``@code{objcopy} and @code{strip} Input Target'' above)
+
+@item
+environment variable @code{GNUTARGET}
+
+@item
+deduced from the input file
+@end enumerate
+
+@subheading @code{nm}, @code{size}, and @code{strings} Target
+
+Ways to specify:
+
+@enumerate
+@item
+command line option: @samp{--target}
+
+@item
+environment variable @code{GNUTARGET}
+
+@item
+deduced from the input file
+@end enumerate
+
+@subheading Linker Input Target
+
+Ways to specify:
+
+@enumerate
+@item
+command line option: @samp{-b} or @samp{--format}
+(@pxref{Options,,Options,ld.info,Using LD})
+
+@item
+script command @code{TARGET}
+(@pxref{Option Commands,,Option Commands,ld.info,Using LD})
+
+@item
+environment variable @code{GNUTARGET}
+(@pxref{Environment,,Environment,ld.info,Using LD})
+
+@item
+the default target of the selected linker emulation
+(@pxref{Linker Emulation Selection})
+@end enumerate
+
+@subheading Linker Output Target
+
+Ways to specify:
+
+@enumerate
+@item
+command line option: @samp{-oformat}
+(@pxref{Options,,Options,ld.info,Using LD})
+
+@item
+script command @code{OUTPUT_FORMAT}
+(@pxref{Option Commands,,Option Commands,ld.info,Using LD})
+
+@item
+the linker input target (see ``Linker Input Target'' above)
+@end enumerate
+
+@node Architecture Selection
+@section Architecture selection
+
+An @dfn{architecture} is a type of @sc{cpu} on which an object file is
+to run.  Its name may contain a colon, separating the name of the
+processor family from the name of the particular @sc{cpu}.
+
+The command to list valid architecture values is @samp{objdump -i} (the
+second column contains the relevant information).
+
+Sample values: @samp{m68k:68020}, @samp{mips:3000}, @samp{sparc}.
+
+@subheading @code{objdump} Architecture
+
+Ways to specify:
+
+@enumerate
+@item
+command line option: @samp{-m} or @samp{--architecture}
+
+@item
+deduced from the input file
+@end enumerate
+
+@subheading @code{objcopy}, @code{nm}, @code{size}, @code{strings} Architecture
+
+Ways to specify:
+
+@enumerate
+@item
+deduced from the input file
+@end enumerate
+
+@subheading Linker Input Architecture
+
+Ways to specify:
+
+@enumerate
+@item
+deduced from the input file
+@end enumerate
+
+@subheading Linker Output Architecture
+
+Ways to specify:
+
+@enumerate
+@item
+script command @code{OUTPUT_ARCH}
+(@pxref{Option Commands,,Option Commands,ld.info,Using LD})
+
+@item
+the default architecture from the linker output target
+(@pxref{Target Selection})
+@end enumerate
+
+@node Linker Emulation Selection
+@section Linker emulation selection
+
+A linker @dfn{emulation} is a ``personality'' of the linker, which gives
+the linker default values for the other aspects of the target system.
+In particular, it consists of
+
+@itemize @bullet
+@item
+the linker script
+
+@item
+the target
+
+@item
+several ``hook'' functions that are run at certain stages of the linking
+process to do special things that some targets require
+@end itemize
+
+The command to list valid linker emulation values is @samp{ld -V}.
+
+Sample values: @samp{hp300bsd}, @samp{mipslit}, @samp{sun4}.
+
+Ways to specify:
+
+@enumerate
+@item
+command line option: @samp{-m}
+(@pxref{Options,,Options,ld.info,Using LD})
+
+@item
+environment variable @code{LDEMULATION}
+
+@item
+compiled-in @code{DEFAULT_EMULATION} from @file{Makefile},
+which comes from @code{EMUL} in @file{config/@var{target}.mt}
+@end enumerate
+
+@node Reporting Bugs
+@chapter Reporting Bugs
+@cindex bugs
+@cindex reporting bugs
+
+Your bug reports play an essential role in making the binary utilities
+reliable.
+
+Reporting a bug may help you by bringing a solution to your problem, or
+it may not.  But in any case the principal function of a bug report is
+to help the entire community by making the next version of the binary
+utilities work better.  Bug reports are your contribution to their
+maintenance.
+
+In order for a bug report to serve its purpose, you must include the
+information that enables us to fix the bug.
+
+@menu
+* Bug Criteria::                Have you found a bug?
+* Bug Reporting::               How to report bugs
+@end menu
+
+@node Bug Criteria
+@section Have you found a bug?
+@cindex bug criteria
+
+If you are not sure whether you have found a bug, here are some guidelines:
+
+@itemize @bullet
+@cindex fatal signal
+@cindex crash
+@item
+If a binary utility gets a fatal signal, for any input whatever, that is
+a bug.  Reliable utilities never crash.
+
+@cindex error on valid input
+@item
+If a binary utility produces an error message for valid input, that is a
+bug.
+
+@item
+If you are an experienced user of binary utilities, your suggestions for
+improvement are welcome in any case.
+@end itemize
+
+@node Bug Reporting
+@section How to report bugs
+@cindex bug reports
+@cindex bugs, reporting
+
+A number of companies and individuals offer support for @sc{gnu}
+products.  If you obtained the binary utilities from a support
+organization, we recommend you contact that organization first.
+
+You can find contact information for many support companies and
+individuals in the file @file{etc/SERVICE} in the @sc{gnu} Emacs
+distribution.
+
+In any event, we also recommend that you send bug reports for the binary
+utilities to @samp{bug-gnu-utils@@gnu.org}.
+
+The fundamental principle of reporting bugs usefully is this:
+@strong{report all the facts}.  If you are not sure whether to state a
+fact or leave it out, state it!
+
+Often people omit facts because they think they know what causes the
+problem and assume that some details do not matter.  Thus, you might
+assume that the name of a file you use in an example does not matter.
+Well, probably it does not, but one cannot be sure.  Perhaps the bug is
+a stray memory reference which happens to fetch from the location where
+that pathname is stored in memory; perhaps, if the pathname were
+different, the contents of that location would fool the utility into
+doing the right thing despite the bug.  Play it safe and give a
+specific, complete example.  That is the easiest thing for you to do,
+and the most helpful.
+
+Keep in mind that the purpose of a bug report is to enable us to fix the bug if
+it is new to us.  Therefore, always write your bug reports on the assumption
+that the bug has not been reported previously.
+
+Sometimes people give a few sketchy facts and ask, ``Does this ring a
+bell?''  Those bug reports are useless, and we urge everyone to
+@emph{refuse to respond to them} except to chide the sender to report
+bugs properly.
+
+To enable us to fix the bug, you should include all these things:
+
+@itemize @bullet
+@item
+The version of the utility.  Each utility announces it if you start it
+with the @samp{--version} argument.
+
+Without this, we will not know whether there is any point in looking for
+the bug in the current version of the binary utilities.
+
+@item
+Any patches you may have applied to the source, including any patches
+made to the @code{BFD} library.
+
+@item
+The type of machine you are using, and the operating system name and
+version number.
+
+@item
+What compiler (and its version) was used to compile the utilities---e.g.
+``@code{gcc-2.7}''.
+
+@item
+The command arguments you gave the utility to observe the bug.  To
+guarantee you will not omit something important, list them all.  A copy
+of the Makefile (or the output from make) is sufficient.
+
+If we were to try to guess the arguments, we would probably guess wrong
+and then we might not encounter the bug.
+
+@item
+A complete input file, or set of input files, that will reproduce the
+bug.  If the utility is reading an object file or files, then it is
+generally most helpful to send the actual object files, uuencoded if
+necessary to get them through the mail system.  Making them available
+for anonymous FTP is not as good, but may be the only reasonable choice
+for large object files.
+
+If the source files were produced exclusively using @sc{gnu} programs
+(e.g., @code{gcc}, @code{gas}, and/or the @sc{gnu} @code{ld}), then it
+may be OK to send the source files rather than the object files.  In
+this case, be sure to say exactly what version of @code{gcc}, or
+whatever, was used to produce the object files.  Also say how
+@code{gcc}, or whatever, was configured.
+
+@item
+A description of what behavior you observe that you believe is
+incorrect.  For example, ``It gets a fatal signal.''
+
+Of course, if the bug is that the utility gets a fatal signal, then we
+will certainly notice it.  But if the bug is incorrect output, we might
+not notice unless it is glaringly wrong.  You might as well not give us
+a chance to make a mistake.
+
+Even if the problem you experience is a fatal signal, you should still
+say so explicitly.  Suppose something strange is going on, such as, your
+copy of the utility is out of synch, or you have encountered a bug in
+the C library on your system.  (This has happened!)  Your copy might
+crash and ours would not.  If you told us to expect a crash, then when
+ours fails to crash, we would know that the bug was not happening for
+us.  If you had not told us to expect a crash, then we would not be able
+to draw any conclusion from our observations.
+
+@item
+If you wish to suggest changes to the source, send us context diffs, as
+generated by @code{diff} with the @samp{-u}, @samp{-c}, or @samp{-p}
+option.  Always send diffs from the old file to the new file.  If you
+even discuss something in the @code{ld} source, refer to it by context,
+not by line number.
+
+The line numbers in our development sources will not match those in your
+sources.  Your line numbers would convey no useful information to us.
+@end itemize
+
+Here are some things that are not necessary:
+
+@itemize @bullet
+@item
+A description of the envelope of the bug.
+
+Often people who encounter a bug spend a lot of time investigating
+which changes to the input file will make the bug go away and which
+changes will not affect it.
+
+This is often time consuming and not very useful, because the way we
+will find the bug is by running a single example under the debugger
+with breakpoints, not by pure deduction from a series of examples.
+We recommend that you save your time for something else.
+
+Of course, if you can find a simpler example to report @emph{instead}
+of the original one, that is a convenience for us.  Errors in the
+output will be easier to spot, running under the debugger will take
+less time, and so on.
+
+However, simplification is not vital; if you do not want to do this,
+report the bug anyway and send us the entire test case you used.
+
+@item
+A patch for the bug.
+
+A patch for the bug does help us if it is a good one.  But do not omit
+the necessary information, such as the test case, on the assumption that
+a patch is all we need.  We might see problems with your patch and decide
+to fix the problem another way, or we might not understand it at all.
+
+Sometimes with programs as complicated as the binary utilities it is
+very hard to construct an example that will make the program follow a
+certain path through the code.  If you do not send us the example, we
+will not be able to construct one, so we will not be able to verify that
+the bug is fixed.
+
+And if we cannot understand what bug you are trying to fix, or why your
+patch should be an improvement, we will not install it.  A test case will
+help us to understand.
+
+@item
+A guess about what the bug is or what it depends on.
+
+Such guesses are usually wrong.  Even we cannot guess right about such
+things without first using the debugger to find the facts.
+@end itemize
+
+@node Index
+@unnumbered Index
+
+@printindex cp
+
+@contents
+@bye
diff --git a/binutils/bucomm.c b/binutils/bucomm.c
new file mode 100644 (file)
index 0000000..a5b0054
--- /dev/null
@@ -0,0 +1,266 @@
+/* bucomm.c -- Bin Utils COMmon code.
+   Copyright (C) 1991, 92, 93, 94, 95, 1997, 1998 Free Software Foundation, Inc.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+\f
+/* We might put this in a library someday so it could be dynamically
+   loaded, but for now it's not necessary.  */
+
+#include "bfd.h"
+#include "libiberty.h"
+#include "bucomm.h"
+
+#include <sys/stat.h>
+#include <time.h>              /* ctime, maybe time_t */
+
+#ifndef HAVE_TIME_T_IN_TIME_H
+#ifndef HAVE_TIME_T_IN_TYPES_H
+typedef long time_t;
+#endif
+#endif
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+\f
+/* Error reporting */
+
+char *program_name;
+
+void
+bfd_nonfatal (string)
+     CONST char *string;
+{
+  CONST char *errmsg = bfd_errmsg (bfd_get_error ());
+
+  if (string)
+    fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
+  else
+    fprintf (stderr, "%s: %s\n", program_name, errmsg);
+}
+
+void
+bfd_fatal (string)
+     CONST char *string;
+{
+  bfd_nonfatal (string);
+  xexit (1);
+}
+
+static void
+report (format, args)
+     const char * format;
+     va_list args;
+{
+  fprintf (stderr, "%s: ", program_name);
+  vfprintf (stderr, format, args);
+  putc ('\n', stderr);
+}
+
+#ifdef ANSI_PROTOTYPES
+void
+fatal (const char *format, ...)
+{
+  va_list args;
+
+  va_start (args, format);
+  report (format, args);
+  va_end (args);
+  xexit (1);
+}
+
+void
+non_fatal (const char *format, ...)
+{
+  va_list args;
+
+  va_start (args, format);
+  report (format, args);
+  va_end (args);
+}
+#else
+void 
+fatal (va_alist)
+     va_dcl
+{
+  char *Format;
+  va_list args;
+
+  va_start (args);
+  Format = va_arg (args, char *);
+  report (Format, args);
+  va_end (args);
+  xexit (1);
+}
+
+void 
+non_fatal (va_alist)
+     va_dcl
+{
+  char *Format;
+  va_list args;
+
+  va_start (args);
+  Format = va_arg (args, char *);
+  report (Format, args);
+  va_end (args);
+}
+#endif
+
+/* Set the default BFD target based on the configured target.  Doing
+   this permits the binutils to be configured for a particular target,
+   and linked against a shared BFD library which was configured for a
+   different target.  */
+
+void
+set_default_bfd_target ()
+{
+  /* The macro TARGET is defined by Makefile.  */
+  const char *target = TARGET;
+
+  if (! bfd_set_default_target (target))
+    fatal (_("can't set BFD default target to `%s': %s"),
+          target, bfd_errmsg (bfd_get_error ()));
+}
+
+/* After a false return from bfd_check_format_matches with
+   bfd_get_error () == bfd_error_file_ambiguously_recognized, print
+   the possible matching targets.  */
+
+void
+list_matching_formats (p)
+     char **p;
+{
+  fprintf (stderr, _("%s: Matching formats:"), program_name);
+  while (*p)
+    fprintf (stderr, " %s", *p++);
+  fputc ('\n', stderr);
+}
+
+/* List the supported targets.  */
+
+void
+list_supported_targets (name, f)
+     const char *name;
+     FILE *f;
+{
+  extern bfd_target *bfd_target_vector[];
+  int t;
+
+  if (name == NULL)
+    fprintf (f, _("Supported targets:"));
+  else
+    fprintf (f, _("%s: supported targets:"), name);
+  for (t = 0; bfd_target_vector[t] != NULL; t++)
+    fprintf (f, " %s", bfd_target_vector[t]->name);
+  fprintf (f, "\n");
+}
+\f
+/* Display the archive header for an element as if it were an ls -l listing:
+
+   Mode       User\tGroup\tSize\tDate               Name */
+
+void
+print_arelt_descr (file, abfd, verbose)
+     FILE *file;
+     bfd *abfd;
+     boolean verbose;
+{
+  struct stat buf;
+
+  if (verbose)
+    {
+      if (bfd_stat_arch_elt (abfd, &buf) == 0)
+       {
+         char modebuf[11];
+         char timebuf[40];
+         time_t when = buf.st_mtime;
+         CONST char *ctime_result = (CONST char *) ctime (&when);
+
+         /* POSIX format:  skip weekday and seconds from ctime output.  */
+         sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
+
+         mode_string (buf.st_mode, modebuf);
+         modebuf[10] = '\0';
+         /* POSIX 1003.2/D11 says to skip first character (entry type).  */
+         fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1,
+                  (long) buf.st_uid, (long) buf.st_gid,
+                  (long) buf.st_size, timebuf);
+       }
+    }
+
+  fprintf (file, "%s\n", bfd_get_filename (abfd));
+}
+
+/* Return the name of a temporary file in the same directory as FILENAME.  */
+
+char *
+make_tempname (filename)
+     char *filename;
+{
+  static char template[] = "stXXXXXX";
+  char *tmpname;
+  char *slash = strrchr (filename, '/');
+
+#if defined (__DJGPP__) || defined (__GO32__) || defined (_WIN32)
+  if (slash == NULL)
+    slash = strrchr (filename, '\\');
+#endif
+
+  if (slash != (char *) NULL)
+    {
+      char c;
+
+      c = *slash;
+      *slash = 0;
+      tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
+      strcpy (tmpname, filename);
+      strcat (tmpname, "/");
+      strcat (tmpname, template);
+      mktemp (tmpname);
+      *slash = c;
+    }
+  else
+    {
+      tmpname = xmalloc (sizeof (template));
+      strcpy (tmpname, template);
+      mktemp (tmpname);
+    }
+  return tmpname;
+}
+
+/* Parse a string into a VMA, with a fatal error if it can't be
+   parsed.  */
+
+bfd_vma
+parse_vma (s, arg)
+     const char *s;
+     const char *arg;
+{
+  bfd_vma ret;
+  const char *end;
+
+  ret = bfd_scan_vma (s, &end, 0);
+  
+  if (*end != '\0')
+    fatal (_("%s: bad number: %s"), arg, s);
+
+  return ret;
+}
diff --git a/binutils/bucomm.h b/binutils/bucomm.h
new file mode 100644 (file)
index 0000000..36e6a79
--- /dev/null
@@ -0,0 +1,183 @@
+/* bucomm.h -- binutils common include file.
+   Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+\f
+#ifndef _BUCOMM_H
+#define _BUCOMM_H
+
+#include "ansidecl.h"
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "config.h"
+
+#ifdef USE_BINARY_FOPEN
+#include "fopen-bin.h"
+#else
+#include "fopen-same.h"
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#else
+extern char *strchr ();
+extern char *strrchr ();
+#endif
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#endif
+
+#ifdef NEED_DECLARATION_STRSTR
+extern char *strstr ();
+#endif
+
+#ifdef HAVE_SBRK
+#ifdef NEED_DECLARATION_SBRK
+extern char *sbrk ();
+#endif
+#endif
+
+#ifdef NEED_DECLARATION_GETENV
+extern char *getenv ();
+#endif
+
+#ifdef NEED_DECLARATION_ENVIRON
+extern char **environ;
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+
+#ifndef O_RDWR
+#define O_RDWR 2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#if defined(__GNUC__) && !defined(C_ALLOCA)
+# undef alloca
+# define alloca __builtin_alloca
+#else
+# if defined(HAVE_ALLOCA_H) && !defined(C_ALLOCA)
+#  include <alloca.h>
+# else
+#  ifndef alloca /* predefined by HP cc +Olibcalls */
+#   if !defined (__STDC__) && !defined (__hpux)
+char *alloca ();
+#   else
+void *alloca ();
+#   endif /* __STDC__, __hpux */
+#  endif /* alloca */
+# endif /* HAVE_ALLOCA_H */
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(String) gettext (String)
+# ifdef gettext_noop
+#  define N_(String) gettext_noop (String)
+# else
+#  define N_(String) (String)
+# endif
+#else
+/* Stubs that do something close enough.  */
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+# define bindtextdomain(Domain,Directory) (Domain)
+# define _(String) (String)
+# define N_(String) (String)
+#endif
+
+/* bucomm.c */
+void bfd_nonfatal PARAMS ((CONST char *));
+
+void bfd_fatal PARAMS ((CONST char *));
+
+void fatal PARAMS ((CONST char *, ...));
+
+void non_fatal PARAMS ((CONST char *, ...));
+
+void set_default_bfd_target PARAMS ((void));
+
+void list_matching_formats PARAMS ((char **p));
+
+void list_supported_targets PARAMS ((const char *, FILE *));
+
+void print_arelt_descr PARAMS ((FILE *file, bfd *abfd, boolean verbose));
+
+char *make_tempname PARAMS ((char *));
+
+bfd_vma parse_vma PARAMS ((const char *, const char *));
+
+extern char *program_name;
+
+/* filemode.c */
+void mode_string PARAMS ((unsigned long mode, char *buf));
+
+/* version.c */
+extern void print_version PARAMS ((const char *));
+
+/* rename.c */
+extern void set_times PARAMS ((const char *, const struct stat *));
+
+extern int smart_rename PARAMS ((const char *, const char *, int));
+
+/* libiberty */
+PTR xmalloc PARAMS ((size_t));
+
+PTR xrealloc PARAMS ((PTR, size_t));
+
+#endif /* _BUCOMM_H */
diff --git a/binutils/budbg.h b/binutils/budbg.h
new file mode 100644 (file)
index 0000000..d8ee889
--- /dev/null
@@ -0,0 +1,58 @@
+/* budbg.c -- Interfaces to the generic debugging information routines.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#ifndef BUDBG_H
+#define BUDBG_H
+
+#include <stdio.h>
+
+/* Routine used to read generic debugging information.  */
+
+extern PTR read_debugging_info PARAMS ((bfd *, asymbol **, long));
+
+/* Routine used to print generic debugging information.  */
+
+extern boolean print_debugging_info PARAMS ((FILE *, PTR));
+
+/* Routines used to read and write stabs information.  */
+
+extern PTR start_stab PARAMS ((PTR, bfd *, boolean, asymbol **, long));
+
+extern boolean finish_stab PARAMS ((PTR, PTR));
+
+extern boolean parse_stab PARAMS ((PTR, PTR, int, int, bfd_vma, const char *));
+
+extern boolean write_stabs_in_sections_debugging_info
+  PARAMS ((bfd *, PTR, bfd_byte **, bfd_size_type *, bfd_byte **,
+          bfd_size_type *));
+
+/* Routines used to read and write IEEE debugging information.  */
+
+extern boolean parse_ieee
+  PARAMS ((PTR, bfd *, const bfd_byte *, bfd_size_type));
+
+extern boolean write_ieee_debugging_info PARAMS ((bfd *, PTR));
+
+/* Routine used to read COFF debugging information.  */
+
+extern boolean parse_coff PARAMS ((bfd *, asymbol **, long, PTR));
+
+#endif
diff --git a/binutils/coffdump.c b/binutils/coffdump.c
new file mode 100644 (file)
index 0000000..dc84d50
--- /dev/null
@@ -0,0 +1,541 @@
+/* Coff file dumper.
+   Copyright (C) 1994, 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Written by Steve Chamberlain <sac@cygnus.com>
+
+   This module reads a type tree generated by coffgrok and prints
+   it out so we can test the grokker.
+*/
+
+#include <bfd.h>
+#include <getopt.h>
+#include <libiberty.h>
+
+#include "coffgrok.h"
+#include "bucomm.h"
+
+#define PROGRAM_VERSION "1.0"
+
+static int atnl;
+static void dump_coff_scope ();
+
+static void
+tab (x)
+int x;
+{
+  static int indent;
+  int i;
+
+  if (atnl)
+    {
+      if (x < 0)
+       {
+         printf (")");
+         indent += x;
+
+         return;
+       }
+      else
+       {
+         printf ("\n");
+         atnl = 0;
+       }
+    }
+
+  if (x == -1)
+    {
+      for (i = 0; i < indent; i++)
+       printf ("   ");
+
+      indent += x;
+      printf (")");
+      return;
+    }
+
+  indent += x;
+
+  for (i = 0; i < indent; i++)
+    printf ("   ");
+
+  if (x)
+    {
+      printf ("(");
+    }
+}
+
+static void nl ()
+{
+  atnl = 1;
+}
+
+static void
+dump_coff_lines (p)
+     struct coff_line *p;
+{
+  int i;
+  int online = 0;
+  tab(1);
+  printf(_("#lines %d "),p->nlines);
+  for (i = 0; i < p->nlines; i++) 
+    {
+      printf("(%d 0x%x)", p->lines[i], p->addresses[i]);
+      online++;
+      if (online > 6)
+       {
+         nl();
+         tab(0);
+         online = 0;
+       }
+    }
+  nl();
+  tab(-1);
+}
+
+static void
+dump_coff_type (p)
+     struct coff_type *p;
+{
+  tab (1);
+  printf ("size %d ", p->size);
+  switch (p->type)
+    {
+    case coff_secdef_type:
+      printf ("section definition at %x size %x\n", 
+             p->u.asecdef.address,
+             p->u.asecdef.size);
+      nl();
+      break;
+    case coff_pointer_type:
+      printf ("pointer to");
+      nl ();
+      dump_coff_type (p->u.pointer.points_to);
+      break;
+    case coff_array_type:
+      printf ("array [%d] of", p->u.array.dim);
+      nl ();
+      dump_coff_type (p->u.array.array_of);
+      break;
+    case coff_function_type:
+      printf ("function returning");
+      nl ();
+      dump_coff_type (p->u.function.function_returns);
+      dump_coff_lines (p->u.function.lines);
+      printf ("arguments");
+      nl ();
+      dump_coff_scope (p->u.function.parameters);
+      tab (0);
+      printf ("code");
+      nl ();
+      dump_coff_scope (p->u.function.code);
+      tab(0);
+      break;
+    case coff_structdef_type:
+      printf ("structure definition");
+      nl ();
+      dump_coff_scope (p->u.astructdef.elements);
+      break;
+    case coff_structref_type:
+      if (!p->u.aenumref.ref)
+       printf ("structure ref to UNKNOWN struct");
+      else
+       printf ("structure ref to %s", p->u.aenumref.ref->name);
+      break;
+    case coff_enumref_type:
+      printf ("enum ref to %s", p->u.astructref.ref->name);
+      break;
+    case coff_enumdef_type:
+      printf ("enum definition");
+      nl ();
+      dump_coff_scope (p->u.aenumdef.elements);
+      break;
+    case coff_basic_type:
+      switch (p->u.basic)
+       {
+       case T_NULL:
+         printf ("NULL");
+         break;
+       case T_VOID:
+         printf ("VOID");
+         break;
+       case T_CHAR:
+         printf ("CHAR");
+         break;
+       case T_SHORT:
+         printf ("SHORT");
+         break;
+       case T_INT:
+         printf ("INT ");
+         break;
+       case T_LONG:
+         printf ("LONG");
+         break;
+       case T_FLOAT:
+         printf ("FLOAT");
+         break;
+       case T_DOUBLE:
+         printf ("DOUBLE");
+         break;
+       case T_STRUCT:
+         printf ("STRUCT");
+         break;
+       case T_UNION:
+         printf ("UNION");
+         break;
+       case T_ENUM:
+         printf ("ENUM");
+         break;
+       case T_MOE:
+         printf ("MOE ");
+         break;
+       case T_UCHAR:
+         printf ("UCHAR");
+         break;
+       case T_USHORT:
+         printf ("USHORT");
+         break;
+       case T_UINT:
+         printf ("UINT");
+         break;
+       case T_ULONG:
+         printf ("ULONG");
+         break;
+       case T_LNGDBL:
+         printf ("LNGDBL");
+         break;
+       default:
+         abort ();
+       }
+    }
+  nl ();
+  tab (-1);
+}
+
+static void
+dump_coff_where (p)
+     struct coff_where *p;
+{
+  tab (1);
+  switch (p->where)
+    {
+    case coff_where_stack:
+      printf ("Stack offset %x", p->offset);
+      break;
+    case coff_where_memory:
+      printf ("Memory section %s+%x", p->section->name, p->offset);
+      break;
+    case coff_where_register:
+      printf ("Register %d", p->offset);
+      break;
+    case coff_where_member_of_struct:
+      printf ("Struct Member offset %x", p->offset);
+      break;
+    case coff_where_member_of_enum:
+      printf ("Enum Member offset %x", p->offset);
+      break;
+    case coff_where_unknown:
+      printf ("Undefined symbol");
+      break;
+    case coff_where_strtag:
+      printf ("STRTAG");
+    case coff_where_entag:
+      printf ("ENTAG");
+      break;
+    case coff_where_typedef:
+      printf ("TYPEDEF");
+      break;
+    default:
+      abort ();
+    }
+  nl ();
+  tab (-1);
+}
+
+static void
+dump_coff_visible (p)
+     struct coff_visible *p;
+{
+  tab (1);
+  switch (p->type)
+    {
+    case coff_vis_ext_def:
+      printf ("coff_vis_ext_def");
+      break;
+    case coff_vis_ext_ref:
+      printf ("coff_vis_ext_ref");
+      break;
+    case coff_vis_int_def:
+      printf ("coff_vis_int_def");
+      break;
+    case coff_vis_common:
+      printf ("coff_vis_common");
+      break;
+    case coff_vis_auto:
+      printf ("coff_vis_auto");
+      break;
+    case coff_vis_autoparam:
+      printf ("coff_vis_autoparam");
+      break;
+    case coff_vis_regparam:
+      printf ("coff_vis_regparam");
+      break;
+    case coff_vis_register:
+      printf ("coff_vis_register");
+      break;
+    case coff_vis_tag:
+      printf ("coff_vis_tag");
+      break;
+    case coff_vis_member_of_struct:
+      printf ("coff_vis_member_of_struct");
+      break;
+    case coff_vis_member_of_enum:
+      printf ("coff_vis_member_of_enum");
+      break;
+    default:
+      abort ();
+    }
+  nl ();
+  tab (-1);
+}
+
+
+void
+dump_coff_symbol (p)
+     struct coff_symbol *p;
+{
+  tab (1);
+  printf ("List of symbols");
+  nl ();
+  while (p)
+    {
+      tab (1);
+      tab (1);
+      printf ("Symbol  %s, tag %d, number %d", p->name, p->tag, p->number);
+      nl ();
+      tab (-1);
+      tab (1);
+      printf ("Type");
+      nl ();
+      dump_coff_type (p->type);
+      tab (-1);
+      tab (1);
+      printf ("Where");
+      dump_coff_where (p->where);
+      tab (-1);
+      tab (1);
+      printf ("Visible");
+      dump_coff_visible (p->visible);
+      tab (-1);
+      p = p->next;
+      tab (-1);
+    }
+  tab (-1);
+}
+
+static void
+dump_coff_scope (p)
+     struct coff_scope *p;
+{
+if (p) {
+  tab (1);
+  printf ("List of blocks %lx ",(unsigned long) p);
+
+  if (p->sec) {
+    printf( "  %s %x..%x",  p->sec->name,p->offset, p->offset + p->size -1);
+  }
+  nl ();
+  tab (0);
+  printf ("*****************");
+  nl ();
+  while (p)
+    {
+      tab (0);
+      printf ("vars %d", p->nvars);
+      nl ();
+      dump_coff_symbol (p->vars_head);
+      printf ("blocks");
+      nl ();
+      dump_coff_scope (p->list_head);
+      nl ();
+      p = p->next;
+    }
+
+  tab (0);
+  printf ("*****************");
+  nl ();
+  tab (-1);
+}
+}
+
+static void
+dump_coff_sfile (p)
+     struct coff_sfile *p;
+{
+  tab (1);
+  printf ("List of source files");
+  nl ();
+  while (p)
+    {
+      tab (0);
+      printf ("Source file %s", p->name);
+      nl ();
+      dump_coff_scope (p->scope);
+      p = p->next;
+    }
+  tab (-1);
+}
+
+static void
+dump_coff_section(ptr)
+struct coff_section *ptr;
+{
+  int i;
+  tab(1);
+  printf("section %s %d %d address %x size %x number %d nrelocs %d", 
+        ptr->name, ptr->code, ptr->data, ptr->address,ptr->size, ptr->number, ptr->nrelocs);
+  nl();
+
+  for (i = 0; i < ptr->nrelocs; i++) 
+    {
+      tab(0);    
+      printf("(%x %s %x)",
+            ptr->relocs[i].offset,
+            ptr->relocs[i].symbol->name,
+            ptr->relocs[i].addend);
+      nl();
+    }
+  tab(-1);
+
+}
+
+void
+coff_dump (ptr)
+     struct coff_ofile *ptr;
+{
+  int i;
+  printf ("Coff dump");
+  nl ();
+  printf ("#souces %d", ptr->nsources);
+  nl ();
+  dump_coff_sfile (ptr->source_head);
+  for (i = 0; i < ptr->nsections; i++)
+    dump_coff_section(ptr->sections + i);
+}
+
+
+
+char * program_name;
+
+static void
+show_usage (file, status)
+     FILE *file;
+     int status;
+{
+  fprintf (file, "Usage: %s [-hV] in-file\n",   program_name);
+  exit (status);
+}
+
+static void
+show_help ()
+{
+  printf (_("%s: Print a human readable interpretation of a SYSROFF object file\n"),
+         program_name);
+  show_usage (stdout, 0);
+}
+
+
+int
+main (ac, av)
+     int ac;
+     char *av[];
+{
+  bfd *abfd;
+  struct coff_ofile *tree;
+  char **matching;
+  char *input_file = NULL;
+  int opt;
+  static struct option long_options[] =
+    {
+      { "help", no_argument, 0, 'h' },
+      { "version", no_argument, 0, 'V' },
+      { NULL, no_argument, 0, 0 }
+    };
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = av[0];
+  xmalloc_set_program_name (program_name);
+
+  while ((opt = getopt_long (ac, av, "hV", long_options,
+                            (int *) NULL))
+        != EOF)
+    {
+      switch (opt)
+       {
+       case 'h':
+         show_help ();
+         /*NOTREACHED*/
+       case 'V':
+         printf (_("GNU %s version %s\n"), program_name, PROGRAM_VERSION);
+         exit (0);
+         /*NOTREACHED*/
+       case 0:
+         break;
+       default:
+         show_usage (stderr, 1);
+         /*NOTREACHED*/
+       }
+    }
+
+  if (optind < ac)
+    {
+      input_file = av[optind];
+    }
+
+  if (!input_file)
+    {
+      fprintf (stderr,_("%s: no input file specified\n"),
+              program_name);
+      exit(1);
+    }
+  abfd = bfd_openr (input_file, 0);
+
+  if (!abfd)
+    bfd_fatal (input_file);
+
+  if (! bfd_check_format_matches (abfd, bfd_object, &matching))
+    {
+      bfd_nonfatal (input_file);
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      exit (1);
+    }
+
+  tree = coff_grok (abfd);
+
+  coff_dump(tree);
+  printf("\n");
+  return 0;
+}
diff --git a/binutils/coffgrok.c b/binutils/coffgrok.c
new file mode 100644 (file)
index 0000000..8c4e6c9
--- /dev/null
@@ -0,0 +1,737 @@
+/* coffgrok.c
+   Copyright (C) 1994, 95, 97, 1998 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Written by Steve Chamberlain (sac@cygnus.com)
+
+   This module reads a coff file and builds a really simple type tree
+   which can be read by other programs.  The first application is a
+   coff->sysroff converter.  It can be tested with coffdump.c.
+
+*/
+
+#include <bfd.h>
+#include "bucomm.h"
+
+#include "coff/internal.h"
+#include "../bfd/libcoff.h"
+#include "coffgrok.h"
+int lofile = 1;
+static struct coff_scope *top_scope;
+static struct coff_scope *file_scope;
+static struct coff_ofile *ofile;
+
+struct coff_symbol *last_function_symbol;
+struct coff_type *last_function_type;
+struct coff_type *last_struct;
+struct coff_type *last_enum;
+struct coff_sfile *cur_sfile;
+
+static struct coff_symbol **tindex;
+
+
+static asymbol **syms;
+static long symcount;
+
+#define N(x) ((x)->_n._n_nptr[1])
+
+static struct coff_ptr_struct *rawsyms;
+static int rawcount;
+static bfd *abfd;
+extern char *xcalloc ();
+#define PTR_SIZE       4
+#define SHORT_SIZE     2
+#define INT_SIZE       4
+#define LONG_SIZE      4
+#define FLOAT_SIZE     4
+#define DOUBLE_SIZE    8
+
+#define INDEXOF(p)  ((struct coff_ptr_struct *)(p)-(rawsyms))
+
+static struct coff_scope *
+empty_scope ()
+{
+  struct coff_scope *l;
+  l = (struct coff_scope *) (xcalloc (sizeof (struct coff_scope), 1));
+  return l;
+}
+
+static struct coff_symbol *
+empty_symbol ()
+{
+  return (struct coff_symbol *) (xcalloc (sizeof (struct coff_symbol), 1));
+}
+
+/*int l;*/
+static void
+push_scope (link)
+     int link;
+{
+  struct coff_scope *n = empty_scope ();
+  if (link)
+    {
+      if (top_scope)
+       {
+         if (top_scope->list_tail)
+           {
+             top_scope->list_tail->next = n;
+           }
+         else
+           {
+             top_scope->list_head = n;
+           }
+         top_scope->list_tail = n;
+       }
+    }
+  n->parent = top_scope;
+
+  top_scope = n;
+}
+
+static void
+pop_scope ()
+{
+  top_scope = top_scope->parent;
+}
+
+static void
+do_sections_p1 (head)
+     struct coff_ofile *head;
+{
+  asection *section;
+  int idx;
+  struct coff_section *all = (struct coff_section *) (xcalloc (abfd->section_count + 1,
+                                            sizeof (struct coff_section)));
+  head->nsections = abfd->section_count + 1;
+  head->sections = all;
+
+  for (idx = 0, section = abfd->sections; section; section = section->next, idx++)
+    {
+      long relsize;
+      int i = section->target_index;
+      arelent **relpp;
+      long relcount;
+
+      relsize = bfd_get_reloc_upper_bound (abfd, section);
+      if (relsize < 0)
+       bfd_fatal (bfd_get_filename (abfd));
+      if (relsize == 0)
+        continue;
+      relpp = (arelent **) xmalloc (relsize);
+      relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
+      if (relcount < 0)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      head->sections[i].name = (char *) (section->name);
+      head->sections[i].code = section->flags & SEC_CODE;
+      head->sections[i].data = section->flags & SEC_DATA;
+      if (strcmp (section->name, ".bss") == 0)
+       head->sections[i].data = 1;
+      head->sections[i].address = section->lma;
+      head->sections[i].size = section->_raw_size;
+      head->sections[i].number = idx;
+      head->sections[i].nrelocs = section->reloc_count;
+      head->sections[i].relocs =
+       (struct coff_reloc *) (xcalloc (section->reloc_count,
+                                       sizeof (struct coff_reloc)));
+      head->sections[i].bfd_section = section;
+    }
+  head->sections[0].name = "ABSOLUTE";
+  head->sections[0].code = 0;
+  head->sections[0].data = 0;
+  head->sections[0].address = 0;
+  head->sections[0].size = 0;
+  head->sections[0].number = 0;
+}
+
+static void
+do_sections_p2 (head)
+     struct coff_ofile *head;
+{
+  asection *section;
+  for (section = abfd->sections; section; section = section->next)
+    {
+      unsigned int j;
+
+      for (j = 0; j < section->reloc_count; j++)
+       {
+         int idx;
+         int i = section->target_index;
+         struct coff_reloc *r = head->sections[i].relocs + j;
+         arelent *sr = section->relocation + j;
+         r->offset = sr->address;
+         r->addend = sr->addend;
+         idx = ((coff_symbol_type *) (sr->sym_ptr_ptr[0]))->native - rawsyms;
+         r->symbol = tindex[idx];
+       }
+    }
+}
+
+static struct coff_where *
+do_where (i)
+     int i;
+{
+  struct internal_syment *sym = &rawsyms[i].u.syment;
+  struct coff_where *where =
+    (struct coff_where *) (xmalloc (sizeof (struct coff_where)));
+  where->offset = sym->n_value;
+
+  if (sym->n_scnum == -1)
+    sym->n_scnum = 0;
+
+  switch (sym->n_sclass)
+    {
+    case C_FIELD:
+      where->where = coff_where_member_of_struct;
+      where->offset = sym->n_value / 8;
+      where->bitoffset = sym->n_value % 8;
+      where->bitsize = rawsyms[i + 1].u.auxent.x_sym.x_misc.x_lnsz.x_size;
+      break;
+    case C_MOE:
+      where->where = coff_where_member_of_enum;
+      break;
+    case C_MOS:
+    case C_MOU:
+      where->where = coff_where_member_of_struct;
+      break;
+    case C_AUTO:
+    case C_ARG:
+      where->where = coff_where_stack;
+      break;
+    case C_EXT:
+    case C_STAT:
+    case C_EXTDEF:
+    case C_LABEL:
+      where->where = coff_where_memory;
+      where->section = &ofile->sections[sym->n_scnum];
+      break;
+    case C_REG:
+    case C_REGPARM:
+      where->where = coff_where_register;
+      break;
+    case C_ENTAG:
+      where->where = coff_where_entag;
+      break;
+    case C_STRTAG:
+    case C_UNTAG:
+      where->where = coff_where_strtag;
+      break;
+    case C_TPDEF:
+      where->where = coff_where_typedef;
+      break;
+    default:
+      abort ();
+      break;
+    }
+  return where;
+}
+
+static
+struct coff_line *
+do_lines (i, name)
+     int i;
+     char *name;
+{
+  struct coff_line *res = (struct coff_line *) xcalloc (sizeof (struct coff_line), 1);
+  asection *s;
+  unsigned int l;
+
+  /* Find out if this function has any line numbers in the table */
+  for (s = abfd->sections; s; s = s->next)
+    {
+      for (l = 0; l < s->lineno_count; l++)
+       {
+         if (s->lineno[l].line_number == 0)
+           {
+             if (rawsyms + i == ((coff_symbol_type *) (&(s->lineno[l].u.sym[0])))->native)
+               {
+                 /* These lines are for this function - so count them and stick them on */
+                 int c = 0;
+                 /* Find the linenumber of the top of the function, since coff linenumbers
+                    are relative to the start of the function. */
+                 int start_line = rawsyms[i + 3].u.auxent.x_sym.x_misc.x_lnsz.x_lnno;
+
+                 l++;
+                 for (c = 0; s->lineno[l + c + 1].line_number; c++)
+                   ;
+
+                 /* Add two extra records, one for the prologue and one for the epilogue */
+                 c += 1;
+                 res->nlines = c;
+                 res->lines = (int *) (xcalloc (sizeof (int), c));
+                 res->addresses = (int *) (xcalloc (sizeof (int), c));
+                 res->lines[0] = start_line;
+                 res->addresses[0] = rawsyms[i].u.syment.n_value - s->vma;
+                 for (c = 0; s->lineno[l + c + 1].line_number; c++)
+                   {
+                     res->lines[c + 1] = s->lineno[l + c].line_number + start_line - 1;
+                     res->addresses[c + 1] = s->lineno[l + c].u.offset;
+                   }
+                 return res;
+               }
+           }
+       }
+    }
+  return res;
+}
+
+static
+struct coff_type *
+do_type (i)
+     int i;
+{
+  struct internal_syment *sym = &rawsyms[i].u.syment;
+  union internal_auxent *aux = &rawsyms[i + 1].u.auxent;
+  struct coff_type *res =
+    (struct coff_type *) xmalloc (sizeof (struct coff_type));
+  int type = sym->n_type;
+  int which_dt = 0;
+  int dimind = 0;
+
+  res->type = coff_basic_type;
+  res->u.basic = type & 0xf;
+
+  switch (type & 0xf)
+    {
+    case T_NULL:
+    case T_VOID:
+      if (sym->n_numaux && sym->n_sclass == C_STAT)
+       {
+         /* This is probably a section definition */
+         res->type = coff_secdef_type;
+         res->size = aux->x_scn.x_scnlen;
+       }
+      else
+       {
+         if (type == 0)
+           {
+             /* Don't know what this is, let's make it a simple int */
+             res->size = INT_SIZE;
+             res->u.basic = T_UINT;
+           }
+         else
+           {
+             /* Else it could be a function or pointer to void */
+             res->size = 0;
+           }
+       }
+      break;
+
+
+      break;
+    case T_UCHAR:
+    case T_CHAR:
+      res->size = 1;
+      break;
+    case T_USHORT:
+    case T_SHORT:
+      res->size = SHORT_SIZE;
+      break;
+    case T_UINT:
+    case T_INT:
+      res->size = INT_SIZE;
+      break;
+    case T_ULONG:
+    case T_LONG:
+      res->size = LONG_SIZE;
+      break;
+    case T_FLOAT:
+      res->size = FLOAT_SIZE;
+      break;
+    case T_DOUBLE:
+      res->size = DOUBLE_SIZE;
+      break;
+    case T_STRUCT:
+    case T_UNION:
+      if (sym->n_numaux)
+       {
+         if (aux->x_sym.x_tagndx.p)
+           {
+             /* Refering to a struct defined elsewhere */
+             res->type = coff_structref_type;
+             res->u.astructref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)];
+             res->size = res->u.astructref.ref ?
+               res->u.astructref.ref->type->size : 0;
+           }
+         else
+           {
+             /* A definition of a struct */
+             last_struct = res;
+             res->type = coff_structdef_type;
+             res->u.astructdef.elements = empty_scope ();
+             res->u.astructdef.idx = 0;
+             res->u.astructdef.isstruct = (type & 0xf) == T_STRUCT;
+             res->size = aux->x_sym.x_misc.x_lnsz.x_size;
+           }
+       }
+      else
+       {
+         /* No auxents - it's anonynmous */
+         res->type = coff_structref_type;
+         res->u.astructref.ref = 0;
+         res->size = 0;
+       }
+      break;
+    case T_ENUM:
+      if (aux->x_sym.x_tagndx.p)
+       {
+         /* Refering to a enum defined elsewhere */
+         res->type = coff_enumref_type;
+         res->u.aenumref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)];
+         res->size = res->u.aenumref.ref->type->size;
+       }
+      else
+       {
+         /* A definition of an enum */
+         last_enum = res;
+         res->type = coff_enumdef_type;
+         res->u.aenumdef.elements = empty_scope ();
+         res->size = aux->x_sym.x_misc.x_lnsz.x_size;
+       }
+      break;
+    case T_MOE:
+      break;
+    }
+
+  for (which_dt = 5; which_dt >= 0; which_dt--)
+    {
+      switch ((type >> ((which_dt * 2) + 4)) & 0x3)
+       {
+       case 0:
+         break;
+       case DT_ARY:
+         {
+           struct coff_type *ptr = ((struct coff_type *)
+                                    xmalloc (sizeof (struct coff_type)));
+           int els = (dimind < DIMNUM
+                      ? aux->x_sym.x_fcnary.x_ary.x_dimen[dimind]
+                      : 0);
+           ++dimind;
+           ptr->type = coff_array_type;
+           ptr->size = els * res->size;
+           ptr->u.array.dim = els;
+           ptr->u.array.array_of = res;
+           res = ptr;
+           break;
+         }
+       case DT_PTR:
+         {
+           struct coff_type *ptr =
+             (struct coff_type *) xmalloc (sizeof (struct coff_type));
+           ptr->size = PTR_SIZE;
+           ptr->type = coff_pointer_type;
+           ptr->u.pointer.points_to = res;
+           res = ptr;
+           break;
+         }
+       case DT_FCN:
+         {
+           struct coff_type *ptr
+             = (struct coff_type *) xmalloc (sizeof (struct coff_type));
+           ptr->size = 0;
+           ptr->type = coff_function_type;
+           ptr->u.function.function_returns = res;
+           ptr->u.function.parameters = empty_scope ();
+           ptr->u.function.lines = do_lines (i, sym->_n._n_nptr[1]);
+           ptr->u.function.code = 0;
+           last_function_type = ptr;
+           res = ptr;
+           break;
+         }
+       }
+    }
+  return res;
+}
+
+static struct coff_visible *
+do_visible (i)
+     int i;
+{
+  struct internal_syment *sym = &rawsyms[i].u.syment;
+  struct coff_visible *visible =
+    (struct coff_visible *) (xmalloc (sizeof (struct coff_visible)));
+  enum coff_vis_type t;
+  switch (sym->n_sclass)
+    {
+    case C_MOS:
+    case C_MOU:
+    case C_FIELD:
+      t = coff_vis_member_of_struct;
+      break;
+    case C_MOE:
+      t = coff_vis_member_of_enum;
+      break;
+
+    case C_REGPARM:
+      t = coff_vis_regparam;
+      break;
+
+    case C_REG:
+      t = coff_vis_register;
+      break;
+    case C_STRTAG:
+    case C_UNTAG:
+    case C_ENTAG:
+    case C_TPDEF:
+      t = coff_vis_tag;
+      break;
+    case C_AUTOARG:
+    case C_ARG:
+      t = coff_vis_autoparam;
+      break;
+    case C_AUTO:
+
+
+      t = coff_vis_auto;
+      break;
+    case C_LABEL:
+    case C_STAT:
+      t = coff_vis_int_def;
+      break;
+    case C_EXT:
+      if (sym->n_scnum == N_UNDEF)
+       {
+         if (sym->n_value)
+           t = coff_vis_common;
+         else
+           t = coff_vis_ext_ref;
+       }
+      else
+       t = coff_vis_ext_def;
+      break;
+    default:
+      abort ();
+      break;
+
+    }
+  visible->type = t;
+  return visible;
+}
+
+static int
+do_define (i, b)
+     int i;
+     struct coff_scope *b;
+{
+  static int symbol_index;
+  struct internal_syment *sym = &rawsyms[i].u.syment;
+
+  /* Define a symbol and attach to block b */
+  struct coff_symbol *s = empty_symbol ();
+
+  s->number = ++symbol_index;
+  s->name = sym->_n._n_nptr[1];
+  s->sfile = cur_sfile;
+  /* Glue onto the ofile list */
+  if (lofile >= 0)
+    {
+      if (ofile->symbol_list_tail)
+       ofile->symbol_list_tail->next_in_ofile_list = s;
+      else
+       ofile->symbol_list_head = s;
+      ofile->symbol_list_tail = s;
+      /* And the block list */
+    }
+  if (b->vars_tail)
+    b->vars_tail->next = s;
+  else
+    b->vars_head = s;
+
+  b->vars_tail = s;
+  b->nvars++;
+  s->type = do_type (i);
+  s->where = do_where (i);
+  s->visible = do_visible (i);
+
+  tindex[i] = s;
+
+  /* We remember the lowest address in each section for each source file */
+
+  if (s->where->where == coff_where_memory
+      && s->type->type == coff_secdef_type)
+    {
+      struct coff_isection *is = cur_sfile->section + s->where->section->number;
+
+      if (!is->init)
+       {
+         is->low = s->where->offset;
+         is->high = s->where->offset + s->type->size;
+         is->init = 1;
+         is->parent = s->where->section;
+       }
+
+    }
+
+  if (s->type->type == coff_function_type)
+    last_function_symbol = s;
+
+  return i + sym->n_numaux + 1;
+}
+
+
+static
+struct coff_ofile *
+doit ()
+{
+  int i;
+  int infile = 0;
+  struct coff_ofile *head =
+  (struct coff_ofile *) xmalloc (sizeof (struct coff_ofile));
+  ofile = head;
+  head->source_head = 0;
+  head->source_tail = 0;
+  head->nsources = 0;
+  head->symbol_list_tail = 0;
+  head->symbol_list_head = 0;
+  do_sections_p1 (head);
+  push_scope (1);
+
+  for (i = 0; i < rawcount;)
+    {
+      struct internal_syment *sym = &rawsyms[i].u.syment;
+      switch (sym->n_sclass)
+       {
+       case C_FILE:
+         {
+           /* new source file announced */
+           struct coff_sfile *n =
+             (struct coff_sfile *) xmalloc (sizeof (struct coff_sfile));
+           n->section = (struct coff_isection *) xcalloc (sizeof (struct coff_isection), abfd->section_count + 1);
+           cur_sfile = n;
+           n->name = sym->_n._n_nptr[1];
+           n->next = 0;
+
+           if (infile)
+             {
+               pop_scope ();
+             }
+           infile = 1;
+           push_scope (1);
+           file_scope = n->scope = top_scope;
+
+           if (head->source_tail)
+             head->source_tail->next = n;
+           else
+             head->source_head = n;
+           head->source_tail = n;
+           head->nsources++;
+           i += sym->n_numaux + 1;
+         }
+         break;
+       case C_FCN:
+         {
+           char *name = sym->_n._n_nptr[1];
+           if (name[1] == 'b')
+             {
+               /* Function start */
+               push_scope (0);
+               last_function_type->u.function.code = top_scope;
+               top_scope->sec = ofile->sections + sym->n_scnum;
+               top_scope->offset = sym->n_value;
+             }
+           else
+             {
+               top_scope->size = sym->n_value - top_scope->offset + 1;
+               pop_scope ();
+
+             }
+           i += sym->n_numaux + 1;
+         }
+         break;
+
+       case C_BLOCK:
+         {
+           char *name = sym->_n._n_nptr[1];
+           if (name[1] == 'b')
+             {
+               /* Block start */
+               push_scope (1);
+               top_scope->sec = ofile->sections + sym->n_scnum;
+               top_scope->offset = sym->n_value;
+
+             }
+           else
+             {
+               top_scope->size = sym->n_value - top_scope->offset + 1;
+               pop_scope ();
+             }
+           i += sym->n_numaux + 1;
+         }
+         break;
+       case C_REGPARM:
+       case C_ARG:
+         i = do_define (i, last_function_symbol->type->u.function.parameters);
+         break;
+       case C_MOS:
+       case C_MOU:
+       case C_FIELD:
+         i = do_define (i, last_struct->u.astructdef.elements);
+         break;
+       case C_MOE:
+         i = do_define (i, last_enum->u.aenumdef.elements);
+         break;
+       case C_STRTAG:
+       case C_ENTAG:
+       case C_UNTAG:
+         /* Various definition */
+         i = do_define (i, top_scope);
+         break;
+       case C_EXT:
+       case C_LABEL:
+         i = do_define (i, file_scope);
+         break;
+       case C_STAT:
+       case C_TPDEF:
+       case C_AUTO:
+       case C_REG:
+         i = do_define (i, top_scope);
+         break;
+       default:
+         abort ();
+       case C_EOS:
+         i += sym->n_numaux + 1;
+         break;
+       }
+    }
+  do_sections_p2 (head);
+  return head;
+}
+
+struct coff_ofile *
+coff_grok (inabfd)
+     bfd *inabfd;
+{
+  long storage;
+  struct coff_ofile *p;
+  abfd = inabfd;
+  storage = bfd_get_symtab_upper_bound (abfd);
+
+  if (storage < 0)
+    bfd_fatal (abfd->filename);
+
+  syms = (asymbol **) xmalloc (storage);
+  symcount = bfd_canonicalize_symtab (abfd, syms);
+  if (symcount < 0)
+    bfd_fatal (abfd->filename);
+  rawsyms = obj_raw_syments (abfd);
+  rawcount = obj_raw_syment_count (abfd);;
+  tindex = (struct coff_symbol **) (xcalloc (sizeof (struct coff_symbol *), rawcount));
+
+  p = doit ();
+  return p;
+}
diff --git a/binutils/coffgrok.h b/binutils/coffgrok.h
new file mode 100644 (file)
index 0000000..c0ade42
--- /dev/null
@@ -0,0 +1,206 @@
+#define T_NULL         0
+#define T_VOID         1       /* function argument (only used by compiler) */
+#define T_CHAR         2       /* character            */
+#define T_SHORT                3       /* short integer        */
+#define T_INT          4       /* integer              */
+#define T_LONG         5       /* long integer         */
+#define T_FLOAT                6       /* floating point       */
+#define T_DOUBLE       7       /* double word          */
+#define T_STRUCT       8       /* structure            */
+#define T_UNION                9       /* union                */
+#define T_ENUM         10      /* enumeration          */
+#define T_MOE          11      /* member of enumeration*/
+#define T_UCHAR                12      /* unsigned character   */
+#define T_USHORT       13      /* unsigned short       */
+#define T_UINT         14      /* unsigned integer     */
+#define T_ULONG                15      /* unsigned long        */
+#define T_LNGDBL       16      /* long double          */
+
+
+ struct coff_reloc
+ {
+   int offset;
+   struct coff_symbol *symbol;
+   int addend;
+ };
+
+ struct coff_section 
+ {
+   char *name;
+   int code;
+   int data;
+   int address;
+   int number;  /* 0..n, .text = 0 */
+   int nrelocs;
+   int size;
+   struct coff_reloc *relocs;
+   struct sec *bfd_section;
+ };
+
+struct coff_ofile
+{
+  int nsources;
+  struct coff_sfile *source_head;
+  struct coff_sfile *source_tail;
+  int nsections;
+  struct coff_section *sections;
+  struct coff_symbol *symbol_list_head;
+  struct coff_symbol *symbol_list_tail;
+};
+
+struct coff_isection {
+  int low;
+  int high;
+  int init;
+  struct coff_section *parent;
+};
+
+struct coff_sfile
+{
+  char *name;
+  struct coff_scope *scope;
+  struct coff_sfile *next;
+
+  /* Vector which maps where in each output section
+     the input file has it's data */
+  struct coff_isection *section; 
+
+};
+
+
+ struct coff_type
+{
+  int size;
+  enum
+    {
+      coff_pointer_type, coff_function_type, coff_array_type, coff_structdef_type, coff_basic_type,
+      coff_structref_type, coff_enumref_type, coff_enumdef_type, coff_secdef_type
+      } type;
+  union
+    {
+      struct 
+       {
+       int address;
+       int size;
+      } asecdef;
+
+      struct
+       {
+         int isstruct;
+         struct coff_scope *elements;
+         int idx;
+       }
+      astructdef;
+      struct
+       {
+         struct coff_symbol *ref;
+       } astructref;
+
+      struct
+       {
+         struct coff_scope *elements;
+         int idx;
+       } aenumdef;
+      struct
+       {
+         struct coff_symbol *ref;
+       } aenumref;
+
+      struct
+       {
+         struct coff_type *points_to;
+       } pointer;
+      struct
+       {
+         int dim;
+         struct coff_type *array_of;
+       } array;
+
+      struct
+       {
+         struct coff_type *function_returns;
+         struct coff_scope *parameters;
+         struct coff_scope *code;
+         struct coff_line *lines;
+       } function;
+      int basic;               /* One of T_VOID.. T_UINT */
+    }  u;
+};
+
+
+ struct coff_line 
+ {
+   int nlines;
+   int *lines;
+   int *addresses;
+ };
+
+
+ struct coff_scope
+   {
+     struct coff_section *sec; /* What section */
+     int offset; /* where */
+     int size; /* How big */
+     struct coff_scope *parent;        /* one up */
+
+     struct coff_scope *next;  /*next along */
+
+     int nvars;
+
+     struct coff_symbol *vars_head;    /* symbols */
+     struct coff_symbol *vars_tail;
+
+     struct coff_scope *list_head;     /* children */
+     struct coff_scope *list_tail;
+
+   };
+
+
+ struct coff_visible
+   {
+     enum coff_vis_type
+       {
+        coff_vis_ext_def,
+        coff_vis_ext_ref,
+        coff_vis_int_def,
+        coff_vis_common,
+        coff_vis_auto,
+        coff_vis_register,
+        coff_vis_tag,
+        coff_vis_member_of_struct,
+        coff_vis_member_of_enum,
+        coff_vis_autoparam,    
+        coff_vis_regparam,
+       } type;
+   };
+
+ struct coff_where
+   {
+     enum
+       {
+        coff_where_stack, coff_where_memory, coff_where_register, coff_where_unknown,
+        coff_where_strtag, coff_where_member_of_struct,
+        coff_where_member_of_enum, coff_where_entag, coff_where_typedef
+
+       } where;
+     int offset;
+     int bitoffset;
+     int bitsize;
+     struct coff_section *section;
+   };
+
+ struct coff_symbol
+   {
+     char *name;
+     int tag;
+     struct coff_type *type;
+     struct coff_where *where;
+     struct coff_visible *visible;
+     struct coff_symbol *next;
+     struct coff_symbol *next_in_ofile_list; /* For the ofile list */
+     int number;
+     int er_number;
+     struct coff_sfile *sfile;
+  };
+
+struct coff_ofile *coff_grok();
diff --git a/binutils/config.in b/binutils/config.in
new file mode 100644 (file)
index 0000000..38272dd
--- /dev/null
@@ -0,0 +1,183 @@
+/* config.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if using alloca.c.  */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro.  */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have a working `mmap' system call.  */
+#undef HAVE_MMAP
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+#undef HAVE_SYS_WAIT_H
+
+/* Define as __inline if that's what the C compiler calls it.  */
+#undef inline
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if lex declares yytext as a char * by default, not a char[].  */
+#undef YYTEXT_POINTER
+
+/* Define if you have the __argz_count function.  */
+#undef HAVE___ARGZ_COUNT
+
+/* Define if you have the __argz_next function.  */
+#undef HAVE___ARGZ_NEXT
+
+/* Define if you have the __argz_stringify function.  */
+#undef HAVE___ARGZ_STRINGIFY
+
+/* Define if you have the dcgettext function.  */
+#undef HAVE_DCGETTEXT
+
+/* Define if you have the getcwd function.  */
+#undef HAVE_GETCWD
+
+/* Define if you have the getpagesize function.  */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the munmap function.  */
+#undef HAVE_MUNMAP
+
+/* Define if you have the putenv function.  */
+#undef HAVE_PUTENV
+
+/* Define if you have the sbrk function.  */
+#undef HAVE_SBRK
+
+/* Define if you have the setenv function.  */
+#undef HAVE_SETENV
+
+/* Define if you have the setlocale function.  */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the stpcpy function.  */
+#undef HAVE_STPCPY
+
+/* Define if you have the strcasecmp function.  */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strchr function.  */
+#undef HAVE_STRCHR
+
+/* Define if you have the utimes function.  */
+#undef HAVE_UTIMES
+
+/* Define if you have the <argz.h> header file.  */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file.  */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file.  */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <nl_types.h> header file.  */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have the <stdlib.h> header file.  */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file.  */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/file.h> header file.  */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <sys/param.h> header file.  */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <values.h> header file.  */
+#undef HAVE_VALUES_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
+/* Define if you have the stpcpy function */
+#undef HAVE_STPCPY
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define to 1 if NLS is requested */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+#undef HAVE_GETTEXT
+
+/* Is the type time_t defined in <time.h>? */
+#undef HAVE_TIME_T_IN_TIME_H
+
+/* Is the type time_t defined in <sys/types.h>? */
+#undef HAVE_TIME_T_IN_TYPES_H
+
+/* Does <utime.h> define struct utimbuf? */
+#undef HAVE_GOOD_UTIME_H
+
+/* Define if fprintf is not declared in system header files. */
+#undef NEED_DECLARATION_FPRINTF
+
+/* Define if strstr is not declared in system header files. */
+#undef NEED_DECLARATION_STRSTR
+
+/* Define if sbrk is not declared in system header files. */
+#undef NEED_DECLARATION_SBRK
+
+/* Define if getenv is not declared in system header files. */
+#undef NEED_DECLARATION_GETENV
+
+/* Define if environ is not declared in system header files. */
+#undef NEED_DECLARATION_ENVIRON
+
+/* Use b modifier when opening binary files? */
+#undef USE_BINARY_FOPEN
+
+/* Configured target name. */
+#undef TARGET
+
diff --git a/binutils/configure b/binutils/configure
new file mode 100755 (executable)
index 0000000..594e154
--- /dev/null
@@ -0,0 +1,5567 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+  --enable-shared[=PKGS]  build shared libraries [default=yes]"
+ac_help="$ac_help
+  --enable-static[=PKGS]  build static libraries [default=yes]"
+ac_help="$ac_help
+  --enable-fast-install[=PKGS]  optimize for fast installation [default=yes]"
+ac_help="$ac_help
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]"
+ac_help="$ac_help
+  --disable-libtool-lock  force libtool not to do file locking"
+ac_help="$ac_help
+  --enable-targets        alternative target configurations"
+ac_help="$ac_help
+  --enable-commonbfdlib   build shared BFD/opcodes/libiberty library"
+ac_help="$ac_help
+  --disable-nls           do not use Native Language Support"
+ac_help="$ac_help
+  --with-included-gettext use the GNU gettext library included here"
+ac_help="$ac_help
+  --enable-maintainer-mode enable make rules and dependencies not useful
+                          (and sometimes confusing) to the casual installer"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=ar.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+#    configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+#    same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+#    as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:594: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+  case $nonopt in
+  NONE)
+    if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+    fi ;;
+  *) host_alias=$nonopt ;;
+  esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:615: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+  case $nonopt in
+  NONE) target_alias=$host_alias ;;
+  *) target_alias=$nonopt ;;
+  esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:633: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+  case $nonopt in
+  NONE) build_alias=$host_alias ;;
+  *) build_alias=$nonopt ;;
+  esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:668: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:721: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "$*" != "X $srcdir/configure conftestfile" \
+      && test "$*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { echo "configure: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+   fi
+
+   test "$2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+  program_transform_name=
+else
+  # Double any \ or $.  echo might interpret backslashes.
+  cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+  program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+  rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:778: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+       @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+PACKAGE=binutils
+
+VERSION=2.9.4
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:824: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+   ACLOCAL=aclocal
+   echo "$ac_t""found" 1>&6
+else
+   ACLOCAL="$missing_dir/missing aclocal"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:837: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+   AUTOCONF=autoconf
+   echo "$ac_t""found" 1>&6
+else
+   AUTOCONF="$missing_dir/missing autoconf"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:850: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+   AUTOMAKE=automake
+   echo "$ac_t""found" 1>&6
+else
+   AUTOMAKE="$missing_dir/missing automake"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:863: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+   AUTOHEADER=autoheader
+   echo "$ac_t""found" 1>&6
+else
+   AUTOHEADER="$missing_dir/missing autoheader"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:876: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+   MAKEINFO=makeinfo
+   echo "$ac_t""found" 1>&6
+else
+   MAKEINFO="$missing_dir/missing makeinfo"
+   echo "$ac_t""missing" 1>&6
+fi
+
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval="$enable_shared"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_shared=yes
+fi
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval="$enable_static"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_static=yes
+fi
+
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval="$enable_fast_install"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_fast_install=yes
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:962: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_RANLIB="ranlib"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+  echo "$ac_t""$RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:992: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1022: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1073: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1105: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1116 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1147: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1152: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1161: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1180: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+echo "configure:1223: checking for ld used by GCC" >&5
+  ac_prog=`($CC -print-prog-name=ld) 2>&5`
+  case "$ac_prog" in
+    # Accept absolute paths.
+    /* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+echo "configure:1247: checking for GNU ld" >&5
+else
+  echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+echo "configure:1250: checking for non-GNU ld" >&5
+fi
+if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog"; then
+      ac_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+  echo "$ac_t""$LD" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+
+echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+echo "configure:1286: checking if the linker ($LD) is GNU ld" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  ac_cv_prog_gnu_ld=yes
+else
+  ac_cv_prog_gnu_ld=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6
+
+
+echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+echo "configure:1302: checking for BSD-compatible nm" >&5
+if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  ac_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/nm; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -B"
+       break
+      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -p"
+       break
+      else
+       ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi
+fi
+
+NM="$ac_cv_path_NM"
+echo "$ac_t""$NM" 1>&6
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6
+echo "configure:1340: checking command to parse $NM output" >&5
+if eval "test \"`echo '$''{'ac_cv_sys_global_symbol_pipe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # These are sane defaults that work on at least a few old systems.
+# {They come from Ultrix.  What could be older than Ultrix?!! ;)}
+
+# Character class describing NM global symbol codes.
+ac_symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+ac_symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+  ac_symcode='[BCDT]'
+  ;;
+cygwin* | mingw*)
+  ac_symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+  ;;
+irix*)
+  ac_symcode='[BCDEGRST]'
+  ;;
+solaris*)
+  ac_symcode='[BDT]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  ac_symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.*       \($ac_symcode\)                 *\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  ac_pipe_works=no
+  rm -f conftest.$ac_ext
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func;return 0;}
+EOF
+
+  if { (eval echo configure:1403: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+  
+    if { (eval echo configure:1407: \"$NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5; } && test -s "$ac_nlist"; then
+
+      # Try sorting and uniquifying the output.
+      if sort "$ac_nlist" | uniq > "$ac_nlist"T; then
+       mv -f "$ac_nlist"T "$ac_nlist"
+      else
+       rm -f "$ac_nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then
+       if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then
+         cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c'
+
+         cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+       sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c
+       cat <<\EOF >> conftest.c
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftestm.$ac_objext
+         ac_save_LIBS="$LIBS"
+         ac_save_CFLAGS="$CFLAGS"
+         LIBS="conftestm.$ac_objext"
+         CFLAGS="$CFLAGS$no_builtin_flag"
+         if { (eval echo configure:1459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+           ac_pipe_works=yes
+         else
+           echo "configure: failed program was:" >&5
+           cat conftest.c >&5
+         fi
+         LIBS="$ac_save_LIBS"
+         CFLAGS="$ac_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $ac_nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $ac_nlist" >&5
+      fi
+    else
+      echo "cannot run $ac_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.c >&5
+  fi
+  rm -rf conftest*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$ac_pipe_works" = yes; then
+    if test x"$ac_symprfx" = x"_"; then
+      ac_cv_sys_symbol_underscore=yes
+    else
+      ac_cv_sys_symbol_underscore=no
+    fi
+    break
+  else
+    ac_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+
+ac_result=yes
+if test -z "$ac_cv_sys_global_symbol_pipe"; then
+   ac_result=no
+fi
+echo "$ac_t""$ac_result" 1>&6
+
+echo $ac_n "checking for _ prefix in compiled symbols""... $ac_c" 1>&6
+echo "configure:1505: checking for _ prefix in compiled symbols" >&5
+if eval "test \"`echo '$''{'ac_cv_sys_symbol_underscore'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_sys_symbol_underscore=no
+cat > conftest.$ac_ext <<EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+EOF
+if { (eval echo configure:1514: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  # Now try to grab the symbols.
+  ac_nlist=conftest.nm
+  if { (eval echo configure:1517: \"$NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5; } && test -s "$ac_nlist"; then
+    # See whether the symbols have a leading underscore.
+    if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+      ac_cv_sys_symbol_underscore=yes
+    else
+      if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+       :
+      else
+       echo "configure: cannot find nm_test_func in $ac_nlist" >&5
+      fi
+    fi
+  else
+    echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&5
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.c >&5
+fi
+rm -rf conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_sys_symbol_underscore" 1>&6
+USE_SYMBOL_UNDERSCORE=${ac_cv_sys_symbol_underscore=no}
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1543: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+  rm -f conftestdata
+  ac_cv_prog_LN_S="ln -s"
+else
+  ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+  echo "$ac_t""yes" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test $host != $build; then
+  ac_tool_prefix=${host_alias}-
+else
+  ac_tool_prefix=
+fi
+
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags="--cache-file=$cache_file"
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$lt_dlopen" = yes && libtool_flags="$libtool_flags --enable-dlopen"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$host" in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 1585 "configure"' > conftest.$ac_ext
+  if { (eval echo configure:1586: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
+echo "configure:1607: checking whether the C compiler needs -belf" >&5
+if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1612 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1619: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  lt_cv_cc_needs_belf=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  lt_cv_cc_needs_belf=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+*-*-cygwin*)
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1642: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+DLLTOOL="$ac_cv_prog_DLLTOOL"
+if test -n "$DLLTOOL"; then
+  echo "$ac_t""$DLLTOOL" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_DLLTOOL"; then
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1674: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_DLLTOOL="dlltool"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_DLLTOOL" && ac_cv_prog_DLLTOOL="false"
+fi
+fi
+DLLTOOL="$ac_cv_prog_DLLTOOL"
+if test -n "$DLLTOOL"; then
+  echo "$ac_t""$DLLTOOL" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  DLLTOOL="false"
+fi
+fi
+
+# Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1709: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$AS"; then
+  ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_AS="${ac_tool_prefix}as"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+AS="$ac_cv_prog_AS"
+if test -n "$AS"; then
+  echo "$ac_t""$AS" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_AS"; then
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1741: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$AS"; then
+  ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_AS="as"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_AS" && ac_cv_prog_AS="false"
+fi
+fi
+AS="$ac_cv_prog_AS"
+if test -n "$AS"; then
+  echo "$ac_t""$AS" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  AS="false"
+fi
+fi
+
+
+  ;;
+
+esac
+
+# enable the --disable-libtool-lock switch
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval="$enable_libtool_lock"
+  need_locks=$enableval
+else
+  need_locks=yes
+fi
+
+
+if test x"$need_locks" = xno; then
+  libtool_flags="$libtool_flags --disable-lock"
+fi
+
+
+# Save cache, so that ltconfig can load it
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+DLLTOOL="$DLLTOOL" AS="$AS" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; }
+
+# Reload cache, that may have been modified by ltconfig
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+
+
+# Check whether --enable-targets or --disable-targets was given.
+if test "${enable_targets+set}" = set; then
+  enableval="$enable_targets"
+  case "${enableval}" in
+  yes | "") { echo "configure: error: enable-targets option must specify target names or 'all'" 1>&2; exit 1; }
+            ;;
+  no)       enable_targets= ;;
+  *)        enable_targets=$enableval ;;
+esac
+fi
+# Check whether --enable-commonbfdlib or --disable-commonbfdlib was given.
+if test "${enable_commonbfdlib+set}" = set; then
+  enableval="$enable_commonbfdlib"
+  case "${enableval}" in
+  yes) commonbfdlib=true ;;
+  no)  commonbfdlib=false ;;
+  *)   { echo "configure: error: bad value ${enableval} for BFD commonbfdlib option" 1>&2; exit 1; } ;;
+esac
+fi
+
+
+
+
+
+if test -z "$target" ; then
+    { echo "configure: error: Unrecognized target system type; please check config.sub." 1>&2; exit 1; }
+fi
+if test -z "$host" ; then
+    { echo "configure: error: Unrecognized host system type; please check config.sub." 1>&2; exit 1; }
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1906: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1936: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1987: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:2019: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 2030 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:2035: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:2061: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:2066: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2075: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:2094: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+
+
+for ac_prog in 'bison -y' byacc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2131: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_YACC="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+  echo "$ac_t""$YACC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:2162: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 2177 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2183: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 2194 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2200: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 2211 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2217: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+missing_dir=`cd $ac_aux_dir && pwd`
+for ac_prog in flex lex
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2247: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LEX="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+  echo "$ac_t""$LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=""$missing_dir/missing flex""
+
+# Extract the first word of "flex", so it can be a program name with args.
+set dummy flex; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2280: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LEX="flex"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+  echo "$ac_t""$LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$LEXLIB"
+then
+  case "$LEX" in
+  flex*) ac_lib=fl ;;
+  *) ac_lib=l ;;
+  esac
+  echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
+echo "configure:2314: checking for yywrap in -l$ac_lib" >&5
+ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-l$ac_lib  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2322 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char yywrap();
+
+int main() {
+yywrap()
+; return 0; }
+EOF
+if { (eval echo configure:2333: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LEXLIB="-l$ac_lib"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking lex output file root""... $ac_c" 1>&6
+echo "configure:2356: checking lex output file root" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # The minimal lex program is just a single line: %%.  But some broken lexes
+# (Solaris, I think it was) want two %% lines, so accommodate them.
+echo '%%
+%%' | $LEX
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  { echo "configure: error: cannot find output from $LEX; giving up" 1>&2; exit 1; }
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_root" 1>&6
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6
+echo "configure:2377: checking whether yytext is a pointer" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c
+ac_save_LIBS="$LIBS"
+LIBS="$LIBS $LEXLIB"
+cat > conftest.$ac_ext <<EOF
+#line 2389 "configure"
+#include "confdefs.h"
+`cat $LEX_OUTPUT_ROOT.c`
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:2396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_prog_lex_yytext_pointer=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+rm -f "${LEX_OUTPUT_ROOT}.c"
+
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_yytext_pointer" 1>&6
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+  cat >> confdefs.h <<\EOF
+#define YYTEXT_POINTER 1
+EOF
+
+fi
+
+
+ALL_LINGUAS=
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+echo "configure:2420: checking for POSIXized ISC" >&5
+if test -d /etc/conf/kconfig.d &&
+  grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+  echo "$ac_t""yes" 1>&6
+  ISC=yes # If later tests want to check for ISC.
+  cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+  if test "$GCC" = yes; then
+    CC="$CC -posix"
+  else
+    CC="$CC -Xp"
+  fi
+else
+  echo "$ac_t""no" 1>&6
+  ISC=
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2441: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2446 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2454: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2471 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2489 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+  :
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2510 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:2521: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2545: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2550 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this.  */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this.  */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this.  */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+   It does not let you subtract one const X* pointer from another in an arm
+   of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this.  */
+  char *t;
+  char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+  *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+  int x[] = {25, 17};
+  const int *foo = &x[0];
+  ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+  typedef const int *iptr;
+  iptr p = 0;
+  ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+     "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+  struct s { int j; const int *ap[3]; };
+  struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+  const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:2599: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_const=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+  cat >> confdefs.h <<\EOF
+#define const 
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:2620: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat > conftest.$ac_ext <<EOF
+#line 2627 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:2634: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_inline=$ac_kw; break
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+  inline | yes) ;;
+  no) cat >> confdefs.h <<\EOF
+#define inline 
+EOF
+ ;;
+  *)  cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:2660: checking for off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2665 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_off_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+  cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:2693: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2698 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_size_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+  cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:2728: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2733 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:2740: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_header_alloca_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:2761: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2766 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:2794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_func_alloca_works=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+  # that cause trouble.  Some versions do not even contain alloca or
+  # contain a buggy version.  If you still want to use their alloca,
+  # use ar to extract alloca.o from them instead of compiling alloca.c.
+  ALLOCA=alloca.${ac_objext}
+  cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:2826: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2831 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "webecray" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_os_cray=yes
+else
+  rm -rf conftest*
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+  echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2856: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2861 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2884: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+  break
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:2911: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2919 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+  exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:2938: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_c_stack_direction=1
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2963: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2968 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3002: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3007 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:3055: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_mmap_fixed_mapped=no
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3063 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+   Here is a matrix of mmap possibilities:
+       mmap private not fixed
+       mmap private fixed at somewhere currently unmapped
+       mmap private fixed at somewhere already mapped
+       mmap shared not fixed
+       mmap shared fixed at somewhere currently unmapped
+       mmap shared fixed at somewhere already mapped
+   For private mappings, we should verify that changes cannot be read()
+   back from the file, nor mmap's back from the file at a different
+   address.  (There have been systems where private was not correctly
+   implemented like the infamous i386 svr4.0, and systems where the
+   VM page cache was not coherent with the filesystem buffer cache
+   like early versions of FreeBSD and possibly contemporary NetBSD.)
+   For shared mappings, we should conversely verify that changes get
+   propogated back to all the places they're supposed to be.
+
+   Grep wants private fixed already mapped.
+   The main things grep needs to know about mmap are:
+   * does it exist and is it safe to write into the mmap'd area
+   * how to use it (BSD variants)  */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h.  */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h.  */
+# ifndef HAVE_SYS_PARAM_H
+#  define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+#  define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+#  ifdef HAVE_SYS_PARAM_H
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else /* no EXEC_PAGESIZE */
+#    ifdef NBPG
+#     define getpagesize() NBPG * CLSIZE
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif /* no CLSIZE */
+#    else /* no NBPG */
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     else /* no NBPC */
+#      ifdef PAGESIZE
+#       define getpagesize() PAGESIZE
+#      endif /* PAGESIZE */
+#     endif /* no NBPC */
+#    endif /* no NBPG */
+#   endif /* no EXEC_PAGESIZE */
+#  else /* no HAVE_SYS_PARAM_H */
+#   define getpagesize() 8192  /* punt totally */
+#  endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+       char *data, *data2, *data3;
+       int i, pagesize;
+       int fd;
+
+       pagesize = getpagesize();
+
+       /*
+        * First, make a file with some known garbage in it.
+        */
+       data = malloc(pagesize);
+       if (!data)
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               *(data + i) = rand();
+       umask(0);
+       fd = creat("conftestmmap", 0600);
+       if (fd < 0)
+               exit(1);
+       if (write(fd, data, pagesize) != pagesize)
+               exit(1);
+       close(fd);
+
+       /*
+        * Next, try to mmap the file at a fixed address which
+        * already has something else allocated at it.  If we can,
+        * also make sure that we see the same garbage.
+        */
+       fd = open("conftestmmap", O_RDWR);
+       if (fd < 0)
+               exit(1);
+       data2 = malloc(2 * pagesize);
+       if (!data2)
+               exit(1);
+       data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+       if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+           MAP_PRIVATE | MAP_FIXED, fd, 0L))
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               if (*(data + i) != *(data2 + i))
+                       exit(1);
+
+       /*
+        * Finally, make sure that changes to the mapped area
+        * do not percolate back to the file as seen by read().
+        * (This is a bug on some variants of i386 svr4.0.)
+        */
+       for (i = 0; i < pagesize; ++i)
+               *(data2 + i) = *(data2 + i) + 1;
+       data3 = malloc(pagesize);
+       if (!data3)
+               exit(1);
+       if (read(fd, data3, pagesize) != pagesize)
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               if (*(data + i) != *(data3 + i))
+                       exit(1);
+       close(fd);
+       unlink("conftestmmap");
+       exit(0);
+}
+
+EOF
+if { (eval echo configure:3203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_func_mmap_fixed_mapped=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+                              
+   for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:3231: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3236 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+   for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3271: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3276 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3299: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+   if test "${ac_cv_func_stpcpy+set}" != "set"; then
+     for ac_func in stpcpy
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3328: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3333 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+   fi
+   if test "${ac_cv_func_stpcpy}" = "yes"; then
+     cat >> confdefs.h <<\EOF
+#define HAVE_STPCPY 1
+EOF
+
+   fi
+
+   if test $ac_cv_header_locale_h = yes; then
+    echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
+echo "configure:3390: checking for LC_MESSAGES" >&5
+if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3395 "configure"
+#include "confdefs.h"
+#include <locale.h>
+int main() {
+return LC_MESSAGES
+; return 0; }
+EOF
+if { (eval echo configure:3402: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  am_cv_val_LC_MESSAGES=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  am_cv_val_LC_MESSAGES=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6
+    if test $am_cv_val_LC_MESSAGES = yes; then
+      cat >> confdefs.h <<\EOF
+#define HAVE_LC_MESSAGES 1
+EOF
+
+    fi
+  fi
+   echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
+echo "configure:3423: checking whether NLS is requested" >&5
+        # Check whether --enable-nls or --disable-nls was given.
+if test "${enable_nls+set}" = set; then
+  enableval="$enable_nls"
+  USE_NLS=$enableval
+else
+  USE_NLS=yes
+fi
+
+    echo "$ac_t""$USE_NLS" 1>&6
+    
+
+    USE_INCLUDED_LIBINTL=no
+
+        if test "$USE_NLS" = "yes"; then
+      cat >> confdefs.h <<\EOF
+#define ENABLE_NLS 1
+EOF
+
+      echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
+echo "configure:3443: checking whether included gettext is requested" >&5
+      # Check whether --with-included-gettext or --without-included-gettext was given.
+if test "${with_included_gettext+set}" = set; then
+  withval="$with_included_gettext"
+  nls_cv_force_use_gnu_gettext=$withval
+else
+  nls_cv_force_use_gnu_gettext=no
+fi
+
+      echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6
+
+      nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+      if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+                                       nls_cv_header_intl=
+       nls_cv_header_libgt=
+       CATOBJEXT=NONE
+
+       ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
+echo "configure:3462: checking for libintl.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3467 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3472: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6
+echo "configure:3489: checking for gettext in libc" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3494 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:3501: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  gt_cv_func_gettext_libc=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  gt_cv_func_gettext_libc=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6
+
+          if test "$gt_cv_func_gettext_libc" != "yes"; then
+            echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6
+echo "configure:3517: checking for bindtextdomain in -lintl" >&5
+ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lintl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3525 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char bindtextdomain();
+
+int main() {
+bindtextdomain()
+; return 0; }
+EOF
+if { (eval echo configure:3536: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6
+echo "configure:3552: checking for gettext in libintl" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3557 "configure"
+#include "confdefs.h"
+
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:3564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  gt_cv_func_gettext_libintl=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  gt_cv_func_gettext_libintl=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+          fi
+
+          if test "$gt_cv_func_gettext_libc" = "yes" \
+             || test "$gt_cv_func_gettext_libintl" = "yes"; then
+             cat >> confdefs.h <<\EOF
+#define HAVE_GETTEXT 1
+EOF
+
+             # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3592: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$MSGFMT" in
+  /*)
+  ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+       ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no"
+  ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+  echo "$ac_t""$MSGFMT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+             if test "$MSGFMT" != "no"; then
+               for ac_func in dcgettext
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3626: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3631 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+               # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3681: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$GMSGFMT" in
+  /*)
+  ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+  ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+  echo "$ac_t""$GMSGFMT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+               # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3717: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$XGETTEXT" in
+  /*)
+  ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+       ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+  ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+  echo "$ac_t""$XGETTEXT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+               cat > conftest.$ac_ext <<EOF
+#line 3749 "configure"
+#include "confdefs.h"
+
+int main() {
+extern int _nl_msg_cat_cntr;
+                              return _nl_msg_cat_cntr
+; return 0; }
+EOF
+if { (eval echo configure:3757: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  CATOBJEXT=.gmo
+                  DATADIRNAME=share
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CATOBJEXT=.mo
+                  DATADIRNAME=lib
+fi
+rm -f conftest*
+               INSTOBJEXT=.mo
+             fi
+           fi
+       
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+               
+        if test "$CATOBJEXT" = "NONE"; then
+                         nls_cv_use_gnu_gettext=yes
+        fi
+      fi
+
+      if test "$nls_cv_use_gnu_gettext" = "yes"; then
+                INTLOBJS="\$(GETTOBJS)"
+        # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3789: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$MSGFMT" in
+  /*)
+  ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+       ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt"
+  ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+  echo "$ac_t""$MSGFMT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+        # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3823: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$GMSGFMT" in
+  /*)
+  ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+  ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+  echo "$ac_t""$GMSGFMT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+        # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3859: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$XGETTEXT" in
+  /*)
+  ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+       ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+  ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+  echo "$ac_t""$XGETTEXT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+        
+       USE_INCLUDED_LIBINTL=yes
+        CATOBJEXT=.gmo
+        INSTOBJEXT=.mo
+        DATADIRNAME=share
+       INTLDEPS='$(top_builddir)/../intl/libintl.a'
+       INTLLIBS=$INTLDEPS
+       LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+        nls_cv_header_intl=libintl.h
+        nls_cv_header_libgt=libgettext.h
+      fi
+
+            if test "$XGETTEXT" != ":"; then
+                       if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+         : ;
+       else
+         echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6
+         XGETTEXT=":"
+       fi
+      fi
+
+      # We need to process the po/ directory.
+      POSUB=po
+    else
+      DATADIRNAME=share
+      nls_cv_header_intl=libintl.h
+      nls_cv_header_libgt=libgettext.h
+    fi
+
+    # If this is used in GNU gettext we have to set USE_NLS to `yes'
+    # because some of the sources are only built for this goal.
+    if test "$PACKAGE" = gettext; then
+      USE_NLS=yes
+      USE_INCLUDED_LIBINTL=yes
+    fi
+
+                for lang in $ALL_LINGUAS; do
+      GMOFILES="$GMOFILES $lang.gmo"
+      POFILES="$POFILES $lang.po"
+    done
+
+        
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  
+
+   if test "x$CATOBJEXT" != "x"; then
+     if test "x$ALL_LINGUAS" = "x"; then
+       LINGUAS=
+     else
+       echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
+echo "configure:3949: checking for catalogs to be installed" >&5
+       NEW_LINGUAS=
+       for lang in ${LINGUAS=$ALL_LINGUAS}; do
+         case "$ALL_LINGUAS" in
+          *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+         esac
+       done
+       LINGUAS=$NEW_LINGUAS
+       echo "$ac_t""$LINGUAS" 1>&6
+     fi
+
+          if test -n "$LINGUAS"; then
+       for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+     fi
+   fi
+
+            if test $ac_cv_header_locale_h = yes; then
+     INCLUDE_LOCALE_H="#include <locale.h>"
+   else
+     INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>.  Take care yourself.  */"
+   fi
+   
+
+            if test -f $srcdir/po2tbl.sed.in; then
+      if test "$CATOBJEXT" = ".cat"; then
+        ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6
+echo "configure:3977: checking for linux/version.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3982 "configure"
+#include "confdefs.h"
+#include <linux/version.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3987: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  msgformat=linux
+else
+  echo "$ac_t""no" 1>&6
+msgformat=xopen
+fi
+
+
+                        sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed
+      fi
+            sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+        $srcdir/po2tbl.sed.in > po2tbl.sed
+   fi
+
+            if test "$PACKAGE" = "gettext"; then
+     GT_NO="#NO#"
+     GT_YES=
+   else
+     GT_NO=
+     GT_YES="#YES#"
+   fi
+   
+   
+
+   MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs"
+   
+
+      l=
+   
+
+            if test -d $srcdir/po; then
+      test -d po || mkdir po
+      if test "x$srcdir" != "x."; then
+        if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+           posrcprefix="$srcdir/"
+        else
+           posrcprefix="../$srcdir/"
+        fi
+      else
+        posrcprefix="../"
+      fi
+      rm -f po/POTFILES
+      sed -e "/^#/d" -e "/^\$/d" -e "s,.*,     $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+        < $srcdir/po/POTFILES.in > po/POTFILES
+   fi
+  
+
+echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
+echo "configure:4050: checking whether to enable maintainer-specific portions of Makefiles" >&5
+    # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+  enableval="$enable_maintainer_mode"
+  USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6
+  
+
+if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+  MAINT=$MAINTAINER_MODE_TRUE
+  
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:4073: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4078 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:4089: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_cygwin=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:4106: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4111 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:4118: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_mingw32=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:4137: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+  ac_cv_exeext=.exe
+else
+  rm -f conftest*
+  echo 'int main () { return 0; }' > conftest.$ac_ext
+  ac_cv_exeext=
+  if { (eval echo configure:4147: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+    for file in conftest.*; do
+      case $file in
+      *.c | *.o | *.obj | *.ilk | *.pdb) ;;
+      *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+      esac
+    done
+  else
+    { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+  fi
+  rm -f conftest*
+  test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+
+# host-specific stuff:
+
+HDEFINES=
+
+. ${srcdir}/../bfd/configure.host
+
+
+AR=${AR-ar}
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4180: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_RANLIB="ranlib"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+  echo "$ac_t""$RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:4219: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+# Put a plausible default for CC_FOR_BUILD in Makefile.
+if test -z "$CC_FOR_BUILD"; then
+  if test "x$cross_compiling" = "xno"; then
+    CC_FOR_BUILD='$(CC)'
+  else
+    CC_FOR_BUILD=gcc
+  fi
+fi
+
+# Also set EXEEXT_FOR_BUILD.
+if test "x$cross_compiling" = "xno"; then
+  EXEEXT_FOR_BUILD='$(EXEEXT)'
+else
+  echo $ac_n "checking for build system executable suffix""... $ac_c" 1>&6
+echo "configure:4286: checking for build system executable suffix" >&5
+if eval "test \"`echo '$''{'bfd_cv_build_exeext'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > ac_c_test.c << 'EOF'
+int main() {
+/* Nothing needed here */
+}
+EOF
+    ${CC_FOR_BUILD} -o ac_c_test am_c_test.c 1>&5 2>&5
+    bfd_cv_build_exeext=`echo ac_c_test.* | grep -v ac_c_test.c | sed -e s/ac_c_test//`
+    rm -f ac_c_test*
+    test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no
+fi
+
+echo "$ac_t""$bfd_cv_build_exeext" 1>&6
+  EXEEXT_FOR_BUILD=""
+  test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}
+fi
+
+
+for ac_hdr in string.h strings.h stdlib.h unistd.h fcntl.h sys/file.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4311: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4316 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4321: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:4348: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4353 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:4369: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_header_sys_wait_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:4392: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4397 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:4404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_header_alloca_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:4425: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4430 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:4458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_func_alloca_works=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+  # that cause trouble.  Some versions do not even contain alloca or
+  # contain a buggy version.  If you still want to use their alloca,
+  # use ar to extract alloca.o from them instead of compiling alloca.c.
+  ALLOCA=alloca.${ac_objext}
+  cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:4490: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4495 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "webecray" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_os_cray=yes
+else
+  rm -rf conftest*
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+  echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:4520: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4525 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4548: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+  break
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:4575: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4583 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+  exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:4602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_c_stack_direction=1
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+for ac_func in sbrk utimes
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:4626: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4631 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for time_t in time.h""... $ac_c" 1>&6
+echo "configure:4680: checking for time_t in time.h" >&5
+if eval "test \"`echo '$''{'bu_cv_decl_time_t_time_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4685 "configure"
+#include "confdefs.h"
+#include <time.h>
+int main() {
+time_t i;
+; return 0; }
+EOF
+if { (eval echo configure:4692: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  bu_cv_decl_time_t_time_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  bu_cv_decl_time_t_time_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bu_cv_decl_time_t_time_h" 1>&6
+if test $bu_cv_decl_time_t_time_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_TIME_T_IN_TIME_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for time_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:4713: checking for time_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'bu_cv_decl_time_t_types_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4718 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() {
+time_t i;
+; return 0; }
+EOF
+if { (eval echo configure:4725: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  bu_cv_decl_time_t_types_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  bu_cv_decl_time_t_types_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bu_cv_decl_time_t_types_h" 1>&6
+if test $bu_cv_decl_time_t_types_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_TIME_T_IN_TYPES_H 1
+EOF
+
+fi
+
+# Under Next 3.2 <utime.h> apparently does not define struct utimbuf
+# by default.
+echo $ac_n "checking for utime.h""... $ac_c" 1>&6
+echo "configure:4748: checking for utime.h" >&5
+if eval "test \"`echo '$''{'bu_cv_header_utime_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4753 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#include <utime.h>
+int main() {
+struct utimbuf s;
+; return 0; }
+EOF
+if { (eval echo configure:4764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  bu_cv_header_utime_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  bu_cv_header_utime_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bu_cv_header_utime_h" 1>&6
+if test $bu_cv_header_utime_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_GOOD_UTIME_H 1
+EOF
+
+fi
+
+echo $ac_n "checking whether fprintf must be declared""... $ac_c" 1>&6
+echo "configure:4785: checking whether fprintf must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_fprintf'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4790 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) fprintf
+; return 0; }
+EOF
+if { (eval echo configure:4811: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  bfd_cv_decl_needed_fprintf=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  bfd_cv_decl_needed_fprintf=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_fprintf" 1>&6
+if test $bfd_cv_decl_needed_fprintf = yes; then
+  cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_FPRINTF 1
+EOF
+
+fi
+
+echo $ac_n "checking whether strstr must be declared""... $ac_c" 1>&6
+echo "configure:4832: checking whether strstr must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_strstr'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4837 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) strstr
+; return 0; }
+EOF
+if { (eval echo configure:4858: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  bfd_cv_decl_needed_strstr=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  bfd_cv_decl_needed_strstr=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_strstr" 1>&6
+if test $bfd_cv_decl_needed_strstr = yes; then
+  cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_STRSTR 1
+EOF
+
+fi
+
+echo $ac_n "checking whether sbrk must be declared""... $ac_c" 1>&6
+echo "configure:4879: checking whether sbrk must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_sbrk'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4884 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) sbrk
+; return 0; }
+EOF
+if { (eval echo configure:4905: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  bfd_cv_decl_needed_sbrk=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  bfd_cv_decl_needed_sbrk=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_sbrk" 1>&6
+if test $bfd_cv_decl_needed_sbrk = yes; then
+  cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_SBRK 1
+EOF
+
+fi
+
+echo $ac_n "checking whether getenv must be declared""... $ac_c" 1>&6
+echo "configure:4926: checking whether getenv must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_getenv'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4931 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) getenv
+; return 0; }
+EOF
+if { (eval echo configure:4952: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  bfd_cv_decl_needed_getenv=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  bfd_cv_decl_needed_getenv=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_getenv" 1>&6
+if test $bfd_cv_decl_needed_getenv = yes; then
+  cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_GETENV 1
+EOF
+
+fi
+
+echo $ac_n "checking whether environ must be declared""... $ac_c" 1>&6
+echo "configure:4973: checking whether environ must be declared" >&5
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_environ'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 4978 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *(*pfn) = (char *(*)) environ
+; return 0; }
+EOF
+if { (eval echo configure:4999: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  bfd_cv_decl_needed_environ=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  bfd_cv_decl_needed_environ=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_environ" 1>&6
+if test $bfd_cv_decl_needed_environ = yes; then
+  cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_ENVIRON 1
+EOF
+
+fi
+
+
+
+case "${host}" in
+*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows)
+  cat >> confdefs.h <<\EOF
+#define USE_BINARY_FOPEN 1
+EOF
+ ;;
+esac
+
+# target-specific stuff:
+
+# Canonicalize the secondary target names.
+if test -n "$enable_targets"; then
+    for targ in `echo $enable_targets | sed 's/,/ /g'`
+    do
+       result=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $targ 2>/dev/null`
+       if test -n "$result"; then
+           canon_targets="$canon_targets $result"
+       else
+           # Allow targets that config.sub doesn't recognize, like "all".
+           canon_targets="$canon_targets $targ"
+       fi
+    done
+fi
+
+all_targets=false
+BUILD_NLMCONV=
+NLMCONV_DEFS=
+BUILD_SRCONV=
+BUILD_DLLTOOL=
+DLLTOOL_DEFS=
+BUILD_WINDRES=
+BUILD_DLLWRAP=
+BUILD_MISC=
+
+for targ in $target $canon_targets
+do
+    if test "x$targ" = "xall"; then
+        all_targets=true
+       BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+       BUILD_SRCONV='$(SRCONV_PROG)'
+       NLMCONV_DEFS="-DNLMCONV_I386 -DNLMCONV_ALPHA -DNLMCONV_POWERPC -DNLMCONV_SPARC"
+    else
+       case $targ in
+       i[3456]86*-*-netware*) 
+         BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+         NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_I386"
+         ;;
+       alpha*-*-netware*)
+         BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+         NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_ALPHA"
+         ;;
+       powerpc*-*-netware*)
+         BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+         NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_POWERPC"
+         ;;
+       sparc*-*-netware*)
+         BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+         NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_SPARC"
+         ;;
+       esac
+       case $targ in
+       *-*-hms*) BUILD_SRCONV='$(SRCONV_PROG)' ;;
+       esac
+       case $targ in
+       arm-*pe*)
+         BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+         DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM"
+         BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+        ;;
+       thumb-*pe*)
+         BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+         DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM"
+         BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+        ;;
+       i[3-6]86-*pe* | i[3-6]86-*-cygwin* | i[3-6]86-*-mingw32*)
+         BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+         DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386"
+         BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+         BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+        ;;
+       powerpc*-*-*pe* | powerpc*-*-cygwin*)
+         BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+         DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC"
+         BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+        ;;
+       esac
+    fi
+done
+
+
+
+
+
+
+
+
+
+
+cat >> confdefs.h <<EOF
+#define TARGET "${target}"
+EOF
+
+
+targ=$target
+. $srcdir/../bfd/config.bfd
+if test "x$targ_underscore" = "xyes"; then
+    UNDERSCORE=1
+else
+    UNDERSCORE=0
+fi
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile po/Makefile.in:po/Make-in config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@RANLIB@%$RANLIB%g
+s%@CC@%$CC%g
+s%@LD@%$LD%g
+s%@NM@%$NM%g
+s%@USE_SYMBOL_UNDERSCORE@%$USE_SYMBOL_UNDERSCORE%g
+s%@LN_S@%$LN_S%g
+s%@DLLTOOL@%$DLLTOOL%g
+s%@AS@%$AS%g
+s%@LIBTOOL@%$LIBTOOL%g
+s%@YACC@%$YACC%g
+s%@LEX@%$LEX%g
+s%@LEXLIB@%$LEXLIB%g
+s%@CPP@%$CPP%g
+s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g
+s%@ALLOCA@%$ALLOCA%g
+s%@USE_NLS@%$USE_NLS%g
+s%@MSGFMT@%$MSGFMT%g
+s%@GMSGFMT@%$GMSGFMT%g
+s%@XGETTEXT@%$XGETTEXT%g
+s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g
+s%@CATALOGS@%$CATALOGS%g
+s%@CATOBJEXT@%$CATOBJEXT%g
+s%@DATADIRNAME@%$DATADIRNAME%g
+s%@GMOFILES@%$GMOFILES%g
+s%@INSTOBJEXT@%$INSTOBJEXT%g
+s%@INTLDEPS@%$INTLDEPS%g
+s%@INTLLIBS@%$INTLLIBS%g
+s%@INTLOBJS@%$INTLOBJS%g
+s%@POFILES@%$POFILES%g
+s%@POSUB@%$POSUB%g
+s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g
+s%@GT_NO@%$GT_NO%g
+s%@GT_YES@%$GT_YES%g
+s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g
+s%@l@%$l%g
+s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g
+s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g
+s%@MAINT@%$MAINT%g
+s%@EXEEXT@%$EXEEXT%g
+s%@HDEFINES@%$HDEFINES%g
+s%@AR@%$AR%g
+s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g
+s%@EXEEXT_FOR_BUILD@%$EXEEXT_FOR_BUILD%g
+s%@NLMCONV_DEFS@%$NLMCONV_DEFS%g
+s%@BUILD_NLMCONV@%$BUILD_NLMCONV%g
+s%@BUILD_SRCONV@%$BUILD_SRCONV%g
+s%@BUILD_DLLTOOL@%$BUILD_DLLTOOL%g
+s%@DLLTOOL_DEFS@%$DLLTOOL_DEFS%g
+s%@BUILD_WINDRES@%$BUILD_WINDRES%g
+s%@BUILD_DLLWRAP@%$BUILD_DLLWRAP%g
+s%@BUILD_MISC@%$BUILD_MISC%g
+s%@UNDERSCORE@%$UNDERSCORE%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile po/Makefile.in:po/Make-in"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='\([     ][      ]*\)[^  ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h:config.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
+
+case "x$CONFIG_FILES" in
+*) sed -e '/POTFILES =/r po/POTFILES' po/Makefile.in > po/Makefile ;;
+esac
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/binutils/configure.bat b/binutils/configure.bat
new file mode 100755 (executable)
index 0000000..f7d70f1
--- /dev/null
@@ -0,0 +1,63 @@
+@echo off\r
+if "%1" == "h8/300" goto h8300\r
+\r
+echo Configuring binutils for go32\r
+update ../bfd/hosts/go32.h sysdep.h\r
+goto common\r
+\r
+:h8300\r
+echo Configuring binutils for H8/300\r
+update ..\bfd\hosts\h-go32.h sysdep.h\r
+\r
+:common\r
+\r
+echo # Makefile generated by "configure.bat"> Makefile\r
+\r
+if exist config.sed del config.sed\r
+\r
+sed -n "/^VERSION=/ p" Makefile.in | sed -e "s/^/s^/" -e "s/=/^\"/" -e "s/$/\"^/" > config.sed\r
+sed -f config.sed version.c > version2.c\r
+\r
+if exist config.sed del config.sed\r
+\r
+echo "s/version\./version2\./g                         ">> config.sed\r
+echo "s/-DVERSION=[^ ]* //                             ">> config.sed\r
+\r
+echo "s/^      \$(srcdir)\/move-if-change/     update/ ">> config.sed\r
+echo "/^###$/ i\                                       ">> config.sed\r
+echo "CC = gcc                                         ">> config.sed\r
+echo "s/:\([^  ]\)/: \1/g                              ">> config.sed\r
+echo "s/^      \ *\.\//        go32 /                  ">> config.sed\r
+echo "s/`echo \$(srcdir)\///g                          ">> config.sed\r
+echo "s/ | sed 's,\^\\\.\/,,'`//g                      ">> config.sed\r
+echo "s/^      cd \$(srcdir)[  ]*;//                   ">> config.sed\r
+\r
+echo "/^arparse\.c/ i\                                 ">> config.sed\r
+echo "arparse.o: arparse.c\                            ">> config.sed\r
+echo " $(CC) -c $(CFLAGS) $(INCLUDES) $(HDEFINES) $(TDEFINES) arparse.c ">> config.sed\r
+echo "/\$(BISON)/ c\                                   ">> config.sed\r
+echo " bison $(BISONFLAGS) -o $@ arparse.y             ">> config.sed\r
+echo "/y\.tab\./ d                                     ">> config.sed\r
+\r
+echo "/^arlex.c/ {                                     ">> config.sed\r
+echo " i\                                              ">> config.sed\r
+echo "arlex.o: arlex.c                                 ">> config.sed\r
+echo " i\                                              ">> config.sed\r
+echo " $(CC) -c $(CFLAGS) $(INCLUDES) $(HDEFINES) $(TDEFINES) arlex.c ">> config.sed\r
+echo "}                                                        ">> config.sed\r
+echo "/\$(LEX)/ c\                                     ">> config.sed\r
+echo " flex $(LEX_OPTIONS) arlex.l                     ">> config.sed\r
+echo "s/lex\.yy\./lexyy./g                             ">> config.sed\r
+\r
+echo "s/'"/\\"/g                                       ">> config.sed\r
+echo "s/"'/\\"/g                                       ">> config.sed\r
+\r
+echo "s/c++filt/cxxfilt/g                              ">> config.sed\r
+\r
+sed -e "s/^\"//" -e "s/\"$//" -e "s/[  ]*$//" config.sed > config2.sed\r
+sed -f config2.sed Makefile.in >> Makefile\r
+del config.sed\r
+del config2.sed\r
+\r
+echo int prepends_underscore = 1; > underscore.c\r
+\r
diff --git a/binutils/configure.com b/binutils/configure.com
new file mode 100644 (file)
index 0000000..99463d5
--- /dev/null
@@ -0,0 +1,76 @@
+$!
+$! This file configures binutils for use with openVMS/Alpha
+$! We do not use the configure script, since we do not have /bin/sh
+$! to execute it.
+$!
+$! Written by Klaus K"ampf (kkaempf@rmi.de)
+$!
+$arch_indx = 1 + ((f$getsyi("CPU").ge.128).and.1)      ! vax==1, alpha==2
+$arch = f$element(arch_indx,"|","|VAX|Alpha|")
+$!
+$!
+$! Generate config.h
+$!
+$ create []config.h
+/* config.h.  Generated automatically by configure.  */
+/* config.in.  Generated automatically from configure.in by autoheader.  */
+/* Is the type time_t defined in <time.h>?  */
+#define HAVE_TIME_T_IN_TIME_H 1
+/* Is the type time_t defined in <sys/types.h>?  */
+#define HAVE_TIME_T_IN_TYPES_H 1
+/* Does <utime.h> define struct utimbuf?  */
+#define HAVE_GOOD_UTIME_H 1
+/* Whether fprintf must be declared even if <stdio.h> is included.  */
+#define NEED_DECLARATION_FPRINTF 1
+/* Whether sbrk must be declared even if <unistd.h> is included.  */
+#undef NEED_DECLARATION_SBRK
+/* Do we need to use the b modifier when opening binary files?  */
+/* #undef USE_BINARY_FOPEN */
+/* Define if you have the sbrk function.  */
+/* #undef HAVE_SBRK 1 */
+/* Define if you have the utimes function.  */
+#define HAVE_UTIMES 1
+/* Define if you have the <fcntl.h> header file.  */
+#define HAVE_FCNTL_H 1
+/* Define if you have the <stdlib.h> header file.  */
+#define HAVE_STDLIB_H 1
+/* Define if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+/* Define if you have the <strings.h> header file.  */
+#define HAVE_STRINGS_H 1
+/* Define if you have the <sys/file.h> header file.  */
+#define HAVE_SYS_FILE_H 1
+/* Define if you have the <unistd.h> header file.  */
+#define HAVE_UNISTD_H 1
+$ write sys$output "Generated `config.h'"
+$!
+$!
+$! Edit VERSION in makefile.vms-in
+$!
+$ edit/tpu/nojournal/nosection/nodisplay/command=sys$input -
+        []makefile.vms-in /output=[]makefile.vms
+$DECK
+!
+! Get VERSION from configure.in
+!
+   mfile := CREATE_BUFFER("mfile", "CONFIGURE.IN");
+   rang := CREATE_RANGE(BEGINNING_OF(mfile), END_OF(mfile));
+   match_pos := SEARCH_QUIETLY('AM_INIT_AUTOMAKE(binutils, ', FORWARD, EXACT, rang);
+   IF match_pos <> 0 THEN;
+     POSITION(BEGINNING_OF(match_pos));
+     ERASE(match_pos);
+     vers := CURRENT_LINE-")";
+   ELSE;
+     vers := "unknown";
+   ENDIF;
+
+   file := CREATE_BUFFER("file", GET_INFO(COMMAND_LINE, "file_name"));
+   rang := CREATE_RANGE(BEGINNING_OF(file), END_OF(file));
+   match_pos := SEARCH_QUIETLY('@VERSION@', FORWARD, EXACT, rang);
+   POSITION(BEGINNING_OF(match_pos));
+   ERASE(match_pos);
+   COPY_TEXT(vers);
+   WRITE_FILE(file, GET_INFO(COMMAND_LINE, "output_file"));
+   QUIT
+$  EOD
+$ write sys$output "Created `makefile.vms'"
diff --git a/binutils/configure.in b/binutils/configure.in
new file mode 100644 (file)
index 0000000..298dcd8
--- /dev/null
@@ -0,0 +1,221 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl
+AC_PREREQ(2.13)
+AC_INIT(ar.c)
+
+AC_CANONICAL_SYSTEM
+
+AM_INIT_AUTOMAKE(binutils, 2.9.4)
+
+AM_PROG_LIBTOOL
+
+AC_ARG_ENABLE(targets,
+[  --enable-targets        alternative target configurations],
+[case "${enableval}" in
+  yes | "") AC_ERROR(enable-targets option must specify target names or 'all')
+            ;;
+  no)       enable_targets= ;;
+  *)        enable_targets=$enableval ;;
+esac])dnl
+AC_ARG_ENABLE(commonbfdlib,
+[  --enable-commonbfdlib   build shared BFD/opcodes/libiberty library],
+[case "${enableval}" in
+  yes) commonbfdlib=true ;;
+  no)  commonbfdlib=false ;;
+  *)   AC_MSG_ERROR([bad value ${enableval} for BFD commonbfdlib option]) ;;
+esac])dnl
+
+AM_CONFIG_HEADER(config.h:config.in)
+
+if test -z "$target" ; then
+    AC_MSG_ERROR(Unrecognized target system type; please check config.sub.)
+fi
+if test -z "$host" ; then
+    AC_MSG_ERROR(Unrecognized host system type; please check config.sub.)
+fi
+
+AC_PROG_CC
+
+AC_PROG_YACC
+AM_PROG_LEX
+
+ALL_LINGUAS=
+CY_GNU_GETTEXT
+
+AM_MAINTAINER_MODE
+AC_EXEEXT
+
+# host-specific stuff:
+
+HDEFINES=
+
+. ${srcdir}/../bfd/configure.host
+
+AC_SUBST(HDEFINES)
+AR=${AR-ar}
+AC_SUBST(AR)
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+
+BFD_CC_FOR_BUILD
+
+AC_CHECK_HEADERS(string.h strings.h stdlib.h unistd.h fcntl.h sys/file.h)
+AC_HEADER_SYS_WAIT
+AC_FUNC_ALLOCA
+AC_CHECK_FUNCS(sbrk utimes)
+
+AC_MSG_CHECKING(for time_t in time.h)
+AC_CACHE_VAL(bu_cv_decl_time_t_time_h,
+[AC_TRY_COMPILE([#include <time.h>], [time_t i;],
+bu_cv_decl_time_t_time_h=yes, bu_cv_decl_time_t_time_h=no)])
+AC_MSG_RESULT($bu_cv_decl_time_t_time_h)
+if test $bu_cv_decl_time_t_time_h = yes; then
+  AC_DEFINE([HAVE_TIME_T_IN_TIME_H], 1,
+           [Is the type time_t defined in <time.h>?])
+fi
+
+AC_MSG_CHECKING(for time_t in sys/types.h)
+AC_CACHE_VAL(bu_cv_decl_time_t_types_h,
+[AC_TRY_COMPILE([#include <sys/types.h>], [time_t i;],
+bu_cv_decl_time_t_types_h=yes, bu_cv_decl_time_t_types_h=no)])
+AC_MSG_RESULT($bu_cv_decl_time_t_types_h)
+if test $bu_cv_decl_time_t_types_h = yes; then
+  AC_DEFINE([HAVE_TIME_T_IN_TYPES_H], 1,
+           [Is the type time_t defined in <sys/types.h>?])
+fi
+
+# Under Next 3.2 <utime.h> apparently does not define struct utimbuf
+# by default.
+AC_MSG_CHECKING([for utime.h])
+AC_CACHE_VAL(bu_cv_header_utime_h,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#include <utime.h>],
+[struct utimbuf s;],
+bu_cv_header_utime_h=yes, bu_cv_header_utime_h=no)])
+AC_MSG_RESULT($bu_cv_header_utime_h)
+if test $bu_cv_header_utime_h = yes; then
+  AC_DEFINE(HAVE_GOOD_UTIME_H, 1, [Does <utime.h> define struct utimbuf?])
+fi
+
+BFD_NEED_DECLARATION(fprintf)
+BFD_NEED_DECLARATION(strstr)
+BFD_NEED_DECLARATION(sbrk)
+BFD_NEED_DECLARATION(getenv)
+BFD_NEED_DECLARATION(environ)
+
+BFD_BINARY_FOPEN
+
+# target-specific stuff:
+
+# Canonicalize the secondary target names.
+if test -n "$enable_targets"; then
+    for targ in `echo $enable_targets | sed 's/,/ /g'`
+    do
+       result=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $targ 2>/dev/null`
+       if test -n "$result"; then
+           canon_targets="$canon_targets $result"
+       else
+           # Allow targets that config.sub doesn't recognize, like "all".
+           canon_targets="$canon_targets $targ"
+       fi
+    done
+fi
+
+all_targets=false
+BUILD_NLMCONV=
+NLMCONV_DEFS=
+BUILD_SRCONV=
+BUILD_DLLTOOL=
+DLLTOOL_DEFS=
+BUILD_WINDRES=
+BUILD_DLLWRAP=
+BUILD_MISC=
+
+for targ in $target $canon_targets
+do
+    if test "x$targ" = "xall"; then
+        all_targets=true
+       BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+       BUILD_SRCONV='$(SRCONV_PROG)'
+       NLMCONV_DEFS="-DNLMCONV_I386 -DNLMCONV_ALPHA -DNLMCONV_POWERPC -DNLMCONV_SPARC"
+    else
+       case $targ in
+changequote(,)dnl
+       i[3456]86*-*-netware*) 
+changequote([,])dnl
+         BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+         NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_I386"
+         ;;
+       alpha*-*-netware*)
+         BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+         NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_ALPHA"
+         ;;
+       powerpc*-*-netware*)
+         BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+         NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_POWERPC"
+         ;;
+       sparc*-*-netware*)
+         BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)'
+         NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_SPARC"
+         ;;
+       esac
+       case $targ in
+       *-*-hms*) BUILD_SRCONV='$(SRCONV_PROG)' ;;
+       esac
+       case $targ in
+       arm-*pe*)
+         BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+         DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM"
+         BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+        ;;
+       thumb-*pe*)
+         BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+         DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM"
+         BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+        ;;
+changequote(,)dnl
+       i[3-6]86-*pe* | i[3-6]86-*-cygwin* | i[3-6]86-*-mingw32*)
+changequote([,])dnl
+         BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+         DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386"
+         BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+         BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+        ;;
+       powerpc*-*-*pe* | powerpc*-*-cygwin*)
+         BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+         DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC"
+         BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+        ;;
+       esac
+    fi
+done
+
+AC_SUBST(NLMCONV_DEFS)
+AC_SUBST(BUILD_NLMCONV)
+AC_SUBST(BUILD_SRCONV)
+AC_SUBST(BUILD_DLLTOOL)
+AC_SUBST(DLLTOOL_DEFS)
+AC_SUBST(BUILD_WINDRES)
+AC_SUBST(BUILD_DLLWRAP)
+AC_SUBST(BUILD_MISC)
+
+AC_DEFINE_UNQUOTED(TARGET, "${target}", [Configured target name.])
+
+targ=$target
+. $srcdir/../bfd/config.bfd
+if test "x$targ_underscore" = "xyes"; then
+    UNDERSCORE=1
+else
+    UNDERSCORE=0
+fi
+AC_SUBST(UNDERSCORE)
+
+AC_OUTPUT(Makefile po/Makefile.in:po/Make-in,
+[
+case "x$CONFIG_FILES" in
+*) sed -e '/POTFILES =/r po/POTFILES' po/Makefile.in > po/Makefile ;;
+esac
+])
diff --git a/binutils/cxxfilt.man b/binutils/cxxfilt.man
new file mode 100644 (file)
index 0000000..a4d5d45
--- /dev/null
@@ -0,0 +1,114 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH @PROGRAM@ 1 "June 1993" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+@PROGRAM@ \- demangle C++ symbols
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B @PROGRAM@
+.RB "[\|" \-_ | \-\-strip-underscores "\|]"
+.RB "[\|" "\-s {gnu,lucid,arm} " | " \-\-format={gnu,lucid,arm}" "\|]"
+.RB "[\|" \-\-help "\|]"
+.RB "[\|" \-\-version "\|]"
+.RB "[\|" symbol "...\|]"
+.SH DESCRIPTION
+The C++ language provides function overloading, which means that you can
+write many functions with the same name (providing each takes parameters
+of different types).  All C++ function names are encoded into a
+low-level assembly label (this process is known as
+.I mangling\c
+).  The 
+.B @PROGRAM@
+program does the inverse mapping: it decodes (\fIdemangles\fR)
+low-level names into user-level names so that the linker can keep
+these overloaded functions from clashing.
+.PP
+Every alphanumeric word (consisting of letters, digits, underscores,
+dollars, or periods) seen in the input is a potential label.  If the
+label decodes into a C++ name, the C++ name replaces the low-level
+name in the output.
+.PP
+You can use
+.B @PROGRAM@
+to decipher individual symbols by specifying these symbols on the
+command line.
+.PP
+If no
+.B symbol
+arguments are given,
+.B @PROGRAM@
+reads symbol names from the standard input and writes the demangled
+names to the standard output.  All results are printed on the standard
+output.
+.SH OPTIONS
+.TP
+.B \-_
+.TP
+.B \-\-strip\-underscores
+On some systems, both the C and C++ compilers put an
+underscore in front of every name.  For example, the C name 
+.B foo
+gets the low-level name 
+.BR _foo .
+This option removes the leading underscore.
+
+.TP
+.B "\-s {gnu,lucid,arm}"
+.TP
+.B \-\-format={gnu,lucid,arm}
+GNU
+.B nm
+can decode three different methods of mangling, used by different C++
+compilers.  This option selects which method it uses: the one used by
+the GNU compiler, the one used by the Lucid compiler, or the one
+specified by the C++ Annotated Reference Manual.  The default is the
+GNU style.
+
+.TP
+.B \-\-help
+Print a summary of the options to
+.B @PROGRAM@
+and exit.
+
+.TP
+.B \-\-version
+Print the version number of
+.B @PROGRAM@
+and exit.
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'" 
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (June 1993).
+
+.SH COPYING
+Copyright (c) 1993 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/debug.c b/binutils/debug.c
new file mode 100644 (file)
index 0000000..173d627
--- /dev/null
@@ -0,0 +1,3568 @@
+/* debug.c -- Handle generic debugging information.
+   Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file implements a generic debugging format.  We may eventually
+   have readers which convert different formats into this generic
+   format, and writers which write it out.  The initial impetus for
+   this was writing a convertor from stabs to HP IEEE-695 debugging
+   format.  */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+
+/* Global information we keep for debugging.  A pointer to this
+   structure is the debugging handle passed to all the routines.  */
+
+struct debug_handle
+{
+  /* A linked list of compilation units.  */
+  struct debug_unit *units;
+  /* The current compilation unit.  */
+  struct debug_unit *current_unit;
+  /* The current source file.  */
+  struct debug_file *current_file;
+  /* The current function.  */
+  struct debug_function *current_function;
+  /* The current block.  */
+  struct debug_block *current_block;
+  /* The current line number information for the current unit.  */
+  struct debug_lineno *current_lineno;
+  /* Mark.  This is used by debug_write.  */
+  unsigned int mark;
+  /* A struct/class ID used by debug_write.  */
+  unsigned int class_id;
+  /* The base for class_id for this call to debug_write.  */
+  unsigned int base_id;
+  /* The current line number in debug_write.  */
+  struct debug_lineno *current_write_lineno;
+  unsigned int current_write_lineno_index;
+  /* A list of classes which have assigned ID's during debug_write.
+     This is linked through the next_id field of debug_class_type.  */
+  struct debug_class_id *id_list;
+  /* A list used to avoid recursion during debug_type_samep.  */
+  struct debug_type_compare_list *compare_list;
+};
+
+/* Information we keep for a single compilation unit.  */
+
+struct debug_unit
+{
+  /* The next compilation unit.  */
+  struct debug_unit *next;
+  /* A list of files included in this compilation unit.  The first
+     file is always the main one, and that is where the main file name
+     is stored.  */
+  struct debug_file *files;
+  /* Line number information for this compilation unit.  This is not
+     stored by function, because assembler code may have line number
+     information without function information.  */
+  struct debug_lineno *linenos;
+};
+
+/* Information kept for a single source file.  */
+
+struct debug_file
+{
+  /* The next source file in this compilation unit.  */
+  struct debug_file *next;
+  /* The name of the source file.  */
+  const char *filename;
+  /* Global functions, variables, types, etc.  */
+  struct debug_namespace *globals;
+};
+
+/* A type.  */
+
+struct debug_type
+{
+  /* Kind of type.  */
+  enum debug_type_kind kind;
+  /* Size of type (0 if not known).  */
+  unsigned int size;
+  /* Type which is a pointer to this type.  */
+  debug_type pointer;
+  /* Tagged union with additional information about the type.  */
+  union
+    {
+      /* DEBUG_KIND_INDIRECT.  */
+      struct debug_indirect_type *kindirect;
+      /* DEBUG_KIND_INT.  */
+      /* Whether the integer is unsigned.  */
+      boolean kint;
+      /* DEBUG_KIND_STRUCT, DEBUG_KIND_UNION, DEBUG_KIND_CLASS,
+         DEBUG_KIND_UNION_CLASS.  */
+      struct debug_class_type *kclass;
+      /* DEBUG_KIND_ENUM.  */
+      struct debug_enum_type *kenum;
+      /* DEBUG_KIND_POINTER.  */
+      struct debug_type *kpointer;
+      /* DEBUG_KIND_FUNCTION.  */
+      struct debug_function_type *kfunction;
+      /* DEBUG_KIND_REFERENCE.  */
+      struct debug_type *kreference;
+      /* DEBUG_KIND_RANGE.  */
+      struct debug_range_type *krange;
+      /* DEBUG_KIND_ARRAY.  */
+      struct debug_array_type *karray;
+      /* DEBUG_KIND_SET.  */
+      struct debug_set_type *kset;
+      /* DEBUG_KIND_OFFSET.  */
+      struct debug_offset_type *koffset;
+      /* DEBUG_KIND_METHOD.  */
+      struct debug_method_type *kmethod;
+      /* DEBUG_KIND_CONST.  */
+      struct debug_type *kconst;
+      /* DEBUG_KIND_VOLATILE.  */
+      struct debug_type *kvolatile;
+      /* DEBUG_KIND_NAMED, DEBUG_KIND_TAGGED.  */
+      struct debug_named_type *knamed;
+    } u;
+};
+
+/* Information kept for an indirect type.  */
+
+struct debug_indirect_type
+{
+  /* Slot where the final type will appear.  */
+  debug_type *slot;
+  /* Tag.  */
+  const char *tag;
+};
+
+/* Information kept for a struct, union, or class.  */
+
+struct debug_class_type
+{
+  /* NULL terminated array of fields.  */
+  debug_field *fields;
+  /* A mark field which indicates whether the struct has already been
+     printed.  */
+  unsigned int mark;
+  /* This is used to uniquely identify unnamed structs when printing.  */
+  unsigned int id;
+  /* The remaining fields are only used for DEBUG_KIND_CLASS and
+     DEBUG_KIND_UNION_CLASS.  */
+  /* NULL terminated array of base classes.  */
+  debug_baseclass *baseclasses;
+  /* NULL terminated array of methods.  */
+  debug_method *methods;
+  /* The type of the class providing the virtual function table for
+     this class.  This may point to the type itself.  */
+  debug_type vptrbase;
+};
+
+/* Information kept for an enum.  */
+
+struct debug_enum_type
+{
+  /* NULL terminated array of names.  */
+  const char **names;
+  /* Array of corresponding values.  */
+  bfd_signed_vma *values;
+};
+
+/* Information kept for a function.  FIXME: We should be able to
+   record the parameter types.  */
+
+struct debug_function_type
+{
+  /* Return type.  */
+  debug_type return_type;
+  /* NULL terminated array of argument types.  */
+  debug_type *arg_types;
+  /* Whether the function takes a variable number of arguments.  */
+  boolean varargs;
+};
+
+/* Information kept for a range.  */
+
+struct debug_range_type
+{
+  /* Range base type.  */
+  debug_type type;
+  /* Lower bound.  */
+  bfd_signed_vma lower;
+  /* Upper bound.  */
+  bfd_signed_vma upper;
+};
+
+/* Information kept for an array.  */
+
+struct debug_array_type
+{
+  /* Element type.  */
+  debug_type element_type;
+  /* Range type.  */
+  debug_type range_type;
+  /* Lower bound.  */
+  bfd_signed_vma lower;
+  /* Upper bound.  */
+  bfd_signed_vma upper;
+  /* Whether this array is really a string.  */
+  boolean stringp;
+};
+
+/* Information kept for a set.  */
+
+struct debug_set_type
+{
+  /* Base type.  */
+  debug_type type;
+  /* Whether this set is really a bitstring.  */
+  boolean bitstringp;
+};
+
+/* Information kept for an offset type (a based pointer).  */
+
+struct debug_offset_type
+{
+  /* The type the pointer is an offset from.  */
+  debug_type base_type;
+  /* The type the pointer points to.  */
+  debug_type target_type;
+};
+
+/* Information kept for a method type.  */
+
+struct debug_method_type
+{
+  /* The return type.  */
+  debug_type return_type;
+  /* The object type which this method is for.  */
+  debug_type domain_type;
+  /* A NULL terminated array of argument types.  */
+  debug_type *arg_types;
+  /* Whether the method takes a variable number of arguments.  */
+  boolean varargs;
+};
+
+/* Information kept for a named type.  */
+
+struct debug_named_type
+{
+  /* Name.  */
+  struct debug_name *name;
+  /* Real type.  */
+  debug_type type;
+};
+
+/* A field in a struct or union.  */
+
+struct debug_field
+{
+  /* Name of the field.  */
+  const char *name;
+  /* Type of the field.  */
+  struct debug_type *type;
+  /* Visibility of the field.  */
+  enum debug_visibility visibility;
+  /* Whether this is a static member.  */
+  boolean static_member;
+  union
+    {
+      /* If static_member is false.  */
+      struct
+       {
+         /* Bit position of the field in the struct.  */
+         unsigned int bitpos;
+         /* Size of the field in bits.  */
+         unsigned int bitsize;
+       } f;
+      /* If static_member is true.  */
+      struct
+       {
+         const char *physname;
+       } s;
+    } u;
+};
+
+/* A base class for an object.  */
+
+struct debug_baseclass
+{
+  /* Type of the base class.  */
+  struct debug_type *type;
+  /* Bit position of the base class in the object.  */
+  unsigned int bitpos;
+  /* Whether the base class is virtual.  */
+  boolean virtual;
+  /* Visibility of the base class.  */
+  enum debug_visibility visibility;
+};
+
+/* A method of an object.  */
+
+struct debug_method
+{
+  /* The name of the method.  */
+  const char *name;
+  /* A NULL terminated array of different types of variants.  */
+  struct debug_method_variant **variants;
+};
+
+/* The variants of a method function of an object.  These indicate
+   which method to run.  */
+
+struct debug_method_variant
+{
+  /* The physical name of the function.  */
+  const char *physname;
+  /* The type of the function.  */
+  struct debug_type *type;
+  /* The visibility of the function.  */
+  enum debug_visibility visibility;
+  /* Whether the function is const.  */
+  boolean constp;
+  /* Whether the function is volatile.  */
+  boolean volatilep;
+  /* The offset to the function in the virtual function table.  */
+  bfd_vma voffset;
+  /* If voffset is VOFFSET_STATIC_METHOD, this is a static method.  */
+#define VOFFSET_STATIC_METHOD ((bfd_vma) -1)
+  /* Context of a virtual method function.  */
+  struct debug_type *context;
+};
+
+/* A variable.  This is the information we keep for a variable object.
+   This has no name; a name is associated with a variable in a
+   debug_name structure.  */
+
+struct debug_variable
+{
+  /* Kind of variable.  */
+  enum debug_var_kind kind;
+  /* Type.  */
+  debug_type type;
+  /* Value.  The interpretation of the value depends upon kind.  */
+  bfd_vma val;
+};
+
+/* A function.  This has no name; a name is associated with a function
+   in a debug_name structure.  */
+
+struct debug_function
+{
+  /* Return type.  */
+  debug_type return_type;
+  /* Parameter information.  */
+  struct debug_parameter *parameters;
+  /* Block information.  The first structure on the list is the main
+     block of the function, and describes function local variables.  */
+  struct debug_block *blocks;
+};
+
+/* A function parameter.  */
+
+struct debug_parameter
+{
+  /* Next parameter.  */
+  struct debug_parameter *next;
+  /* Name.  */
+  const char *name;
+  /* Type.  */
+  debug_type type;
+  /* Kind.  */
+  enum debug_parm_kind kind;
+  /* Value (meaning depends upon kind).  */
+  bfd_vma val;
+};
+
+/* A typed constant.  */
+
+struct debug_typed_constant
+{
+  /* Type.  */
+  debug_type type;
+  /* Value.  FIXME: We may eventually need to support non-integral
+     values.  */
+  bfd_vma val;
+};
+
+/* Information about a block within a function.  */
+
+struct debug_block
+{
+  /* Next block with the same parent.  */
+  struct debug_block *next;
+  /* Parent block.  */
+  struct debug_block *parent;
+  /* List of child blocks.  */
+  struct debug_block *children;
+  /* Start address of the block.  */
+  bfd_vma start;
+  /* End address of the block.  */
+  bfd_vma end;
+  /* Local variables.  */
+  struct debug_namespace *locals;
+};
+
+/* Line number information we keep for a compilation unit.  FIXME:
+   This structure is easy to create, but can be very space
+   inefficient.  */
+
+struct debug_lineno
+{
+  /* More line number information for this block.  */
+  struct debug_lineno *next;
+  /* Source file.  */
+  struct debug_file *file;
+  /* Line numbers, terminated by a -1 or the end of the array.  */
+#define DEBUG_LINENO_COUNT 10
+  unsigned long linenos[DEBUG_LINENO_COUNT];
+  /* Addresses for the line numbers.  */
+  bfd_vma addrs[DEBUG_LINENO_COUNT];
+};
+
+/* A namespace.  This is a mapping from names to objects.  FIXME: This
+   should be implemented as a hash table.  */
+
+struct debug_namespace
+{
+  /* List of items in this namespace.  */
+  struct debug_name *list;
+  /* Pointer to where the next item in this namespace should go.  */
+  struct debug_name **tail;
+};
+
+/* Kinds of objects that appear in a namespace.  */
+
+enum debug_object_kind
+{
+  /* A type.  */
+  DEBUG_OBJECT_TYPE,
+  /* A tagged type (really a different sort of namespace).  */
+  DEBUG_OBJECT_TAG,
+  /* A variable.  */
+  DEBUG_OBJECT_VARIABLE,
+  /* A function.  */
+  DEBUG_OBJECT_FUNCTION,
+  /* An integer constant.  */
+  DEBUG_OBJECT_INT_CONSTANT,
+  /* A floating point constant.  */
+  DEBUG_OBJECT_FLOAT_CONSTANT,
+  /* A typed constant.  */
+  DEBUG_OBJECT_TYPED_CONSTANT
+};
+
+/* Linkage of an object that appears in a namespace.  */
+
+enum debug_object_linkage
+{
+  /* Local variable.  */
+  DEBUG_LINKAGE_AUTOMATIC,
+  /* Static--either file static or function static, depending upon the
+     namespace is.  */
+  DEBUG_LINKAGE_STATIC,
+  /* Global.  */
+  DEBUG_LINKAGE_GLOBAL,
+  /* No linkage.  */
+  DEBUG_LINKAGE_NONE
+};
+
+/* A name in a namespace.  */
+
+struct debug_name
+{
+  /* Next name in this namespace.  */
+  struct debug_name *next;
+  /* Name.  */
+  const char *name;
+  /* Mark.  This is used by debug_write.  */
+  unsigned int mark;
+  /* Kind of object.  */
+  enum debug_object_kind kind;
+  /* Linkage of object.  */
+  enum debug_object_linkage linkage;
+  /* Tagged union with additional information about the object.  */
+  union
+    {
+      /* DEBUG_OBJECT_TYPE.  */
+      struct debug_type *type;
+      /* DEBUG_OBJECT_TAG.  */
+      struct debug_type *tag;
+      /* DEBUG_OBJECT_VARIABLE.  */
+      struct debug_variable *variable;
+      /* DEBUG_OBJECT_FUNCTION.  */
+      struct debug_function *function;
+      /* DEBUG_OBJECT_INT_CONSTANT.  */
+      bfd_vma int_constant;
+      /* DEBUG_OBJECT_FLOAT_CONSTANT.  */
+      double float_constant;
+      /* DEBUG_OBJECT_TYPED_CONSTANT.  */
+      struct debug_typed_constant *typed_constant;
+    } u;
+};
+
+/* During debug_write, a linked list of these structures is used to
+   keep track of ID numbers that have been assigned to classes.  */
+
+struct debug_class_id
+{
+  /* Next ID number.  */
+  struct debug_class_id *next;
+  /* The type with the ID.  */
+  struct debug_type *type;
+  /* The tag; NULL if no tag.  */
+  const char *tag;
+};
+
+/* During debug_type_samep, a linked list of these structures is kept
+   on the stack to avoid infinite recursion.  */
+
+struct debug_type_compare_list
+{
+  /* Next type on list.  */
+  struct debug_type_compare_list *next;
+  /* The types we are comparing.  */
+  struct debug_type *t1;
+  struct debug_type *t2;
+};
+
+/* During debug_get_real_type, a linked list of these structures is
+   kept on the stack to avoid infinite recursion.  */
+
+struct debug_type_real_list
+{
+  /* Next type on list.  */
+  struct debug_type_real_list *next;
+  /* The type we are checking.  */
+  struct debug_type *t;
+};
+
+/* Local functions.  */
+
+static void debug_error PARAMS ((const char *));
+static struct debug_name *debug_add_to_namespace
+  PARAMS ((struct debug_handle *, struct debug_namespace **, const char *,
+          enum debug_object_kind, enum debug_object_linkage));
+static struct debug_name *debug_add_to_current_namespace
+  PARAMS ((struct debug_handle *, const char *, enum debug_object_kind,
+          enum debug_object_linkage));
+static struct debug_type *debug_make_type
+  PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int));
+static struct debug_type *debug_get_real_type
+  PARAMS ((PTR, debug_type, struct debug_type_real_list *));
+static boolean debug_write_name
+  PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+          struct debug_name *));
+static boolean debug_write_type
+  PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+          struct debug_type *, struct debug_name *));
+static boolean debug_write_class_type
+  PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+          struct debug_type *, const char *));
+static boolean debug_write_function
+  PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+          const char *, enum debug_object_linkage, struct debug_function *));
+static boolean debug_write_block
+  PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+          struct debug_block *));
+static boolean debug_write_linenos
+  PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
+          bfd_vma));
+static boolean debug_set_class_id
+  PARAMS ((struct debug_handle *, const char *, struct debug_type *));
+static boolean debug_type_samep
+  PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *));
+static boolean debug_class_type_samep
+  PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *));
+\f
+/* Issue an error message.  */
+
+static void
+debug_error (message)
+     const char *message;
+{
+  fprintf (stderr, "%s\n", message);
+}
+
+/* Add an object to a namespace.  */
+
+static struct debug_name *
+debug_add_to_namespace (info, nsp, name, kind, linkage)
+     struct debug_handle *info;
+     struct debug_namespace **nsp;
+     const char *name;
+     enum debug_object_kind kind;
+     enum debug_object_linkage linkage;
+{
+  struct debug_name *n;
+  struct debug_namespace *ns;
+
+  n = (struct debug_name *) xmalloc (sizeof *n);
+  memset (n, 0, sizeof *n);
+
+  n->name = name;
+  n->kind = kind;
+  n->linkage = linkage;
+
+  ns = *nsp;
+  if (ns == NULL)
+    {
+      ns = (struct debug_namespace *) xmalloc (sizeof *ns);
+      memset (ns, 0, sizeof *ns);
+
+      ns->tail = &ns->list;
+
+      *nsp = ns;
+    }
+
+  *ns->tail = n;
+  ns->tail = &n->next;
+
+  return n;
+}
+
+/* Add an object to the current namespace.  */
+
+static struct debug_name *
+debug_add_to_current_namespace (info, name, kind, linkage)
+     struct debug_handle *info;
+     const char *name;
+     enum debug_object_kind kind;
+     enum debug_object_linkage linkage;
+{
+  struct debug_namespace **nsp;
+
+  if (info->current_unit == NULL
+      || info->current_file == NULL)
+    {
+      debug_error (_("debug_add_to_current_namespace: no current file"));
+      return NULL;
+    }
+
+  if (info->current_block != NULL)
+    nsp = &info->current_block->locals;
+  else
+    nsp = &info->current_file->globals;
+
+  return debug_add_to_namespace (info, nsp, name, kind, linkage);
+}
+\f
+/* Return a handle for debugging information.  */
+
+PTR
+debug_init ()
+{
+  struct debug_handle *ret;
+
+  ret = (struct debug_handle *) xmalloc (sizeof *ret);
+  memset (ret, 0, sizeof *ret);
+  return (PTR) ret;
+}
+
+/* Set the source filename.  This implicitly starts a new compilation
+   unit.  */
+
+boolean
+debug_set_filename (handle, name)
+     PTR handle;
+     const char *name;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_file *nfile;
+  struct debug_unit *nunit;
+
+  if (name == NULL)
+    name = "";
+
+  nfile = (struct debug_file *) xmalloc (sizeof *nfile);
+  memset (nfile, 0, sizeof *nfile);
+
+  nfile->filename = name;
+
+  nunit = (struct debug_unit *) xmalloc (sizeof *nunit);
+  memset (nunit, 0, sizeof *nunit);
+
+  nunit->files = nfile;
+  info->current_file = nfile;
+
+  if (info->current_unit != NULL)
+    info->current_unit->next = nunit;
+  else
+    {
+      assert (info->units == NULL);
+      info->units = nunit;
+    }
+
+  info->current_unit = nunit;
+
+  info->current_function = NULL;
+  info->current_block = NULL;
+  info->current_lineno = NULL;
+
+  return true;
+}
+
+/* Change source files to the given file name.  This is used for
+   include files in a single compilation unit.  */
+
+boolean
+debug_start_source (handle, name)
+     PTR handle;
+     const char *name;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_file *f, **pf;
+
+  if (name == NULL)
+    name = "";
+
+  if (info->current_unit == NULL)
+    {
+      debug_error (_("debug_start_source: no debug_set_filename call"));
+      return false;
+    }
+
+  for (f = info->current_unit->files; f != NULL; f = f->next)
+    {
+      if (f->filename[0] == name[0]
+         && f->filename[1] == name[1]
+         && strcmp (f->filename, name) == 0)
+       {
+         info->current_file = f;
+         return true;
+       }
+    }
+
+  f = (struct debug_file *) xmalloc (sizeof *f);
+  memset (f, 0, sizeof *f);
+
+  f->filename = name;
+
+  for (pf = &info->current_file->next;
+       *pf != NULL;
+       pf = &(*pf)->next)
+    ;
+  *pf = f;
+
+  info->current_file = f;
+
+  return true;
+}
+
+/* Record a function definition.  This implicitly starts a function
+   block.  The debug_type argument is the type of the return value.
+   The boolean indicates whether the function is globally visible.
+   The bfd_vma is the address of the start of the function.  Currently
+   the parameter types are specified by calls to
+   debug_record_parameter.  FIXME: There is no way to specify nested
+   functions.  */
+
+boolean
+debug_record_function (handle, name, return_type, global, addr)
+     PTR handle;
+     const char *name;
+     debug_type return_type;
+     boolean global;
+     bfd_vma addr;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_function *f;
+  struct debug_block *b;
+  struct debug_name *n;
+
+  if (name == NULL)
+    name = "";
+  if (return_type == NULL)
+    return false;
+
+  if (info->current_unit == NULL)
+    {
+      debug_error (_("debug_record_function: no debug_set_filename call"));
+      return false;
+    }
+
+  f = (struct debug_function *) xmalloc (sizeof *f);
+  memset (f, 0, sizeof *f);
+
+  f->return_type = return_type;
+
+  b = (struct debug_block *) xmalloc (sizeof *b);
+  memset (b, 0, sizeof *b);
+
+  b->start = addr;
+  b->end = (bfd_vma) -1;
+
+  f->blocks = b;
+
+  info->current_function = f;
+  info->current_block = b;
+
+  /* FIXME: If we could handle nested functions, this would be the
+     place: we would want to use a different namespace.  */
+  n = debug_add_to_namespace (info,
+                             &info->current_file->globals,
+                             name,
+                             DEBUG_OBJECT_FUNCTION,
+                             (global
+                              ? DEBUG_LINKAGE_GLOBAL
+                              : DEBUG_LINKAGE_STATIC));
+  if (n == NULL)
+    return false;
+
+  n->u.function = f;
+
+  return true;
+}
+
+/* Record a parameter for the current function.  */
+
+boolean
+debug_record_parameter (handle, name, type, kind, val)
+     PTR handle;
+     const char *name;
+     debug_type type;
+     enum debug_parm_kind kind;
+     bfd_vma val;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_parameter *p, **pp;
+
+  if (name == NULL || type == NULL)
+    return false;
+
+  if (info->current_unit == NULL
+      || info->current_function == NULL)
+    {
+      debug_error (_("debug_record_parameter: no current function"));
+      return false;
+    }
+
+  p = (struct debug_parameter *) xmalloc (sizeof *p);
+  memset (p, 0, sizeof *p);
+
+  p->name = name;
+  p->type = type;
+  p->kind = kind;
+  p->val = val;
+
+  for (pp = &info->current_function->parameters;
+       *pp != NULL;
+       pp = &(*pp)->next)
+    ;
+  *pp = p;
+
+  return true;
+}
+
+/* End a function.  FIXME: This should handle function nesting.  */
+
+boolean
+debug_end_function (handle, addr)
+     PTR handle;
+     bfd_vma addr;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+
+  if (info->current_unit == NULL
+      || info->current_block == NULL
+      || info->current_function == NULL)
+    {
+      debug_error (_("debug_end_function: no current function"));
+      return false;
+    }
+
+  if (info->current_block->parent != NULL)
+    {
+      debug_error (_("debug_end_function: some blocks were not closed"));
+      return false;
+    }
+
+  info->current_block->end = addr;
+
+  info->current_function = NULL;
+  info->current_block = NULL;
+
+  return true;
+}
+
+/* Start a block in a function.  All local information will be
+   recorded in this block, until the matching call to debug_end_block.
+   debug_start_block and debug_end_block may be nested.  The bfd_vma
+   argument is the address at which this block starts.  */
+
+boolean
+debug_start_block (handle, addr)
+     PTR handle;
+     bfd_vma addr;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_block *b, **pb;
+
+  /* We must always have a current block: debug_record_function sets
+     one up.  */
+  if (info->current_unit == NULL
+      || info->current_block == NULL)
+    {
+      debug_error (_("debug_start_block: no current block"));
+      return false;
+    }
+
+  b = (struct debug_block *) xmalloc (sizeof *b);
+  memset (b, 0, sizeof *b);
+
+  b->parent = info->current_block;
+  b->start = addr;
+  b->end = (bfd_vma) -1;
+
+  /* This new block is a child of the current block.  */
+  for (pb = &info->current_block->children;
+       *pb != NULL;
+       pb = &(*pb)->next)
+    ;
+  *pb = b;
+
+  info->current_block = b;
+
+  return true;
+}
+
+/* Finish a block in a function.  This matches the call to
+   debug_start_block.  The argument is the address at which this block
+   ends.  */
+
+boolean
+debug_end_block (handle, addr)
+     PTR handle;
+     bfd_vma addr;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_block *parent;
+
+  if (info->current_unit == NULL
+      || info->current_block == NULL)
+    {
+      debug_error (_("debug_end_block: no current block"));
+      return false;
+    }
+
+  parent = info->current_block->parent;
+  if (parent == NULL)
+    {
+      debug_error (_("debug_end_block: attempt to close top level block"));
+      return false;
+    }
+
+  info->current_block->end = addr;
+
+  info->current_block = parent;
+
+  return true;
+}
+
+/* Associate a line number in the current source file and function
+   with a given address.  */
+
+boolean
+debug_record_line (handle, lineno, addr)
+     PTR handle;
+     unsigned long lineno;
+     bfd_vma addr;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_lineno *l;
+  unsigned int i;
+
+  if (info->current_unit == NULL)
+    {
+      debug_error (_("debug_record_line: no current unit"));
+      return false;
+    }
+
+  l = info->current_lineno;
+  if (l != NULL && l->file == info->current_file)
+    {
+      for (i = 0; i < DEBUG_LINENO_COUNT; i++)
+       {
+         if (l->linenos[i] == (unsigned long) -1)
+           {
+             l->linenos[i] = lineno;
+             l->addrs[i] = addr;
+             return true;
+           }
+       }
+    }
+
+  /* If we get here, then either 1) there is no current_lineno
+     structure, which means this is the first line number in this
+     compilation unit, 2) the current_lineno structure is for a
+     different file, or 3) the current_lineno structure is full.
+     Regardless, we want to allocate a new debug_lineno structure, put
+     it in the right place, and make it the new current_lineno
+     structure.  */
+
+  l = (struct debug_lineno *) xmalloc (sizeof *l);
+  memset (l, 0, sizeof *l);
+
+  l->file = info->current_file;
+  l->linenos[0] = lineno;
+  l->addrs[0] = addr;
+  for (i = 1; i < DEBUG_LINENO_COUNT; i++)
+    l->linenos[i] = (unsigned long) -1;
+
+  if (info->current_lineno != NULL)
+    info->current_lineno->next = l;
+  else
+    info->current_unit->linenos = l;
+
+  info->current_lineno = l;
+
+  return true;
+}
+
+/* Start a named common block.  This is a block of variables that may
+   move in memory.  */
+
+boolean
+debug_start_common_block (handle, name)
+     PTR handle;
+     const char *name;
+{
+  /* FIXME */
+  debug_error (_("debug_start_common_block: not implemented"));
+  return false;
+}
+
+/* End a named common block.  */
+
+boolean
+debug_end_common_block (handle, name)
+     PTR handle;
+     const char *name;
+{
+  /* FIXME */
+  debug_error (_("debug_end_common_block: not implemented"));
+  return false;
+}
+
+/* Record a named integer constant.  */
+
+boolean
+debug_record_int_const (handle, name, val)
+     PTR handle;
+     const char *name;
+     bfd_vma val;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_name *n;
+
+  if (name == NULL)
+    return false;
+
+  n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_INT_CONSTANT,
+                                     DEBUG_LINKAGE_NONE);
+  if (n == NULL)
+    return false;
+
+  n->u.int_constant = val;
+
+  return true;
+}
+
+/* Record a named floating point constant.  */
+
+boolean
+debug_record_float_const (handle, name, val)
+     PTR handle;
+     const char *name;
+     double val;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_name *n;
+
+  if (name == NULL)
+    return false;
+
+  n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_FLOAT_CONSTANT,
+                                     DEBUG_LINKAGE_NONE);
+  if (n == NULL)
+    return false;
+
+  n->u.float_constant = val;
+
+  return true;
+}
+
+/* Record a typed constant with an integral value.  */
+
+boolean
+debug_record_typed_const (handle, name, type, val)
+     PTR handle;
+     const char *name;
+     debug_type type;
+     bfd_vma val;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_name *n;
+  struct debug_typed_constant *tc;
+
+  if (name == NULL || type == NULL)
+    return false;
+
+  n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPED_CONSTANT,
+                                     DEBUG_LINKAGE_NONE);
+  if (n == NULL)
+    return false;
+
+  tc = (struct debug_typed_constant *) xmalloc (sizeof *tc);
+  memset (tc, 0, sizeof *tc);
+
+  tc->type = type;
+  tc->val = val;
+
+  n->u.typed_constant = tc;
+
+  return true;
+}
+
+/* Record a label.  */
+
+boolean
+debug_record_label (handle, name, type, addr)
+     PTR handle;
+     const char *name;
+     debug_type type;
+     bfd_vma addr;
+{
+  /* FIXME.  */
+  debug_error (_("debug_record_label not implemented"));
+  return false;
+}
+
+/* Record a variable.  */
+
+boolean
+debug_record_variable (handle, name, type, kind, val)
+     PTR handle;
+     const char *name;
+     debug_type type;
+     enum debug_var_kind kind;
+     bfd_vma val;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_namespace **nsp;
+  enum debug_object_linkage linkage;
+  struct debug_name *n;
+  struct debug_variable *v;
+
+  if (name == NULL || type == NULL)
+    return false;
+
+  if (info->current_unit == NULL
+      || info->current_file == NULL)
+    {
+      debug_error (_("debug_record_variable: no current file"));
+      return false;
+    }
+
+  if (kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
+    {
+      nsp = &info->current_file->globals;
+      if (kind == DEBUG_GLOBAL)
+       linkage = DEBUG_LINKAGE_GLOBAL;
+      else
+       linkage = DEBUG_LINKAGE_STATIC;
+    }
+  else
+    {
+      if (info->current_block == NULL)
+       {
+         debug_error (_("debug_record_variable: no current block"));
+         return false;
+       }
+      nsp = &info->current_block->locals;
+      linkage = DEBUG_LINKAGE_AUTOMATIC;
+    }
+
+  n = debug_add_to_namespace (info, nsp, name, DEBUG_OBJECT_VARIABLE, linkage);
+  if (n == NULL)
+    return false;
+
+  v = (struct debug_variable *) xmalloc (sizeof *v);
+  memset (v, 0, sizeof *v);
+
+  v->kind = kind;
+  v->type = type;
+  v->val = val;
+
+  n->u.variable = v;
+
+  return true;  
+}
+
+/* Make a type with a given kind and size.  */
+
+/*ARGSUSED*/
+static struct debug_type *
+debug_make_type (info, kind, size)
+     struct debug_handle *info;
+     enum debug_type_kind kind;
+     unsigned int size;
+{
+  struct debug_type *t;
+
+  t = (struct debug_type *) xmalloc (sizeof *t);
+  memset (t, 0, sizeof *t);
+
+  t->kind = kind;
+  t->size = size;
+
+  return t;
+}
+
+/* Make an indirect type which may be used as a placeholder for a type
+   which is referenced before it is defined.  */
+
+debug_type
+debug_make_indirect_type (handle, slot, tag)
+     PTR handle;
+     debug_type *slot;
+     const char *tag;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_indirect_type *i;
+
+  t = debug_make_type (info, DEBUG_KIND_INDIRECT, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  i = (struct debug_indirect_type *) xmalloc (sizeof *i);
+  memset (i, 0, sizeof *i);
+
+  i->slot = slot;
+  i->tag = tag;
+
+  t->u.kindirect = i;
+
+  return t;
+}
+
+/* Make a void type.  There is only one of these.  */
+
+debug_type
+debug_make_void_type (handle)
+     PTR handle;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+
+  return debug_make_type (info, DEBUG_KIND_VOID, 0);
+}
+
+/* Make an integer type of a given size.  The boolean argument is true
+   if the integer is unsigned.  */
+
+debug_type
+debug_make_int_type (handle, size, unsignedp)
+     PTR handle;
+     unsigned int size;
+     boolean unsignedp;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+
+  t = debug_make_type (info, DEBUG_KIND_INT, size);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t->u.kint = unsignedp;
+
+  return t;
+}
+
+/* Make a floating point type of a given size.  FIXME: On some
+   platforms, like an Alpha, you probably need to be able to specify
+   the format.  */
+
+debug_type
+debug_make_float_type (handle, size)
+     PTR handle;
+     unsigned int size;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+
+  return debug_make_type (info, DEBUG_KIND_FLOAT, size);
+}
+
+/* Make a boolean type of a given size.  */
+
+debug_type
+debug_make_bool_type (handle, size)
+     PTR handle;
+     unsigned int size;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+
+  return debug_make_type (info, DEBUG_KIND_BOOL, size);
+}
+
+/* Make a complex type of a given size.  */
+
+debug_type
+debug_make_complex_type (handle, size)
+     PTR handle;
+     unsigned int size;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+
+  return debug_make_type (info, DEBUG_KIND_COMPLEX, size);
+}
+
+/* Make a structure type.  The second argument is true for a struct,
+   false for a union.  The third argument is the size of the struct.
+   The fourth argument is a NULL terminated array of fields.  */
+
+debug_type
+debug_make_struct_type (handle, structp, size, fields)
+     PTR handle;
+     boolean structp;
+     bfd_vma size;
+     debug_field *fields;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_class_type *c;
+
+  t = debug_make_type (info,
+                      structp ? DEBUG_KIND_STRUCT : DEBUG_KIND_UNION,
+                      size);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  c = (struct debug_class_type *) xmalloc (sizeof *c);
+  memset (c, 0, sizeof *c);
+
+  c->fields = fields;
+
+  t->u.kclass = c;
+
+  return t;
+}
+
+/* Make an object type.  The first three arguments after the handle
+   are the same as for debug_make_struct_type.  The next arguments are
+   a NULL terminated array of base classes, a NULL terminated array of
+   methods, the type of the object holding the virtual function table
+   if it is not this object, and a boolean which is true if this
+   object has its own virtual function table.  */
+
+debug_type
+debug_make_object_type (handle, structp, size, fields, baseclasses,
+                       methods, vptrbase, ownvptr)
+     PTR handle;
+     boolean structp;
+     bfd_vma size;
+     debug_field *fields;
+     debug_baseclass *baseclasses;
+     debug_method *methods;
+     debug_type vptrbase;
+     boolean ownvptr;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_class_type *c;
+
+  t = debug_make_type (info,
+                      structp ? DEBUG_KIND_CLASS : DEBUG_KIND_UNION_CLASS,
+                      size);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  c = (struct debug_class_type *) xmalloc (sizeof *c);
+  memset (c, 0, sizeof *c);
+
+  c->fields = fields;
+  c->baseclasses = baseclasses;
+  c->methods = methods;
+  if (ownvptr)
+    c->vptrbase = t;
+  else
+    c->vptrbase = vptrbase;
+
+  t->u.kclass = c;
+
+  return t;
+}
+
+/* Make an enumeration type.  The arguments are a null terminated
+   array of strings, and an array of corresponding values.  */
+
+debug_type
+debug_make_enum_type (handle, names, values)
+     PTR handle;
+     const char **names;
+     bfd_signed_vma *values;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_enum_type *e;
+
+  t = debug_make_type (info, DEBUG_KIND_ENUM, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  e = (struct debug_enum_type *) xmalloc (sizeof *e);
+  memset (e, 0, sizeof *e);
+
+  e->names = names;
+  e->values = values;
+
+  t->u.kenum = e;
+
+  return t;
+}
+
+/* Make a pointer to a given type.  */
+
+debug_type
+debug_make_pointer_type (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  if (type->pointer != DEBUG_TYPE_NULL)
+    return type->pointer;
+
+  t = debug_make_type (info, DEBUG_KIND_POINTER, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t->u.kpointer = type;
+
+  type->pointer = t;
+
+  return t;
+}
+
+/* Make a function returning a given type.  FIXME: We should be able
+   to record the parameter types.  */
+
+debug_type
+debug_make_function_type (handle, type, arg_types, varargs)
+     PTR handle;
+     debug_type type;
+     debug_type *arg_types;
+     boolean varargs;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_function_type *f;
+
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_FUNCTION, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  f = (struct debug_function_type *) xmalloc (sizeof *f);
+  memset (f, 0, sizeof *f);
+
+  f->return_type = type;
+  f->arg_types = arg_types;
+  f->varargs = varargs;
+
+  t->u.kfunction = f;
+
+  return t;
+}
+
+/* Make a reference to a given type.  */
+
+debug_type
+debug_make_reference_type (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_REFERENCE, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t->u.kreference = type;
+
+  return t;
+}
+
+/* Make a range of a given type from a lower to an upper bound.  */
+
+debug_type
+debug_make_range_type (handle, type, lower, upper)
+     PTR handle;
+     debug_type type;
+     bfd_signed_vma lower;
+     bfd_signed_vma upper;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_range_type *r;
+
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_RANGE, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  r = (struct debug_range_type *) xmalloc (sizeof *r);
+  memset (r, 0, sizeof *r);
+
+  r->type = type;
+  r->lower = lower;
+  r->upper = upper;
+
+  t->u.krange = r;
+
+  return t;
+}
+
+/* Make an array type.  The second argument is the type of an element
+   of the array.  The third argument is the type of a range of the
+   array.  The fourth and fifth argument are the lower and upper
+   bounds, respectively.  The sixth argument is true if this array is
+   actually a string, as in C.  */
+
+debug_type
+debug_make_array_type (handle, element_type, range_type, lower, upper,
+                      stringp)
+     PTR handle;
+     debug_type element_type;
+     debug_type range_type;
+     bfd_signed_vma lower;
+     bfd_signed_vma upper;
+     boolean stringp;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_array_type *a;
+
+  if (element_type == NULL || range_type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_ARRAY, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  a = (struct debug_array_type *) xmalloc (sizeof *a);
+  memset (a, 0, sizeof *a);
+
+  a->element_type = element_type;
+  a->range_type = range_type;
+  a->lower = lower;
+  a->upper = upper;
+  a->stringp = stringp;
+
+  t->u.karray = a;
+
+  return t;
+}
+
+/* Make a set of a given type.  For example, a Pascal set type.  The
+   boolean argument is true if this set is actually a bitstring, as in
+   CHILL.  */
+
+debug_type
+debug_make_set_type (handle, type, bitstringp)
+     PTR handle;
+     debug_type type;
+     boolean bitstringp;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_set_type *s;
+
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_SET, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  s = (struct debug_set_type *) xmalloc (sizeof *s);
+  memset (s, 0, sizeof *s);
+
+  s->type = type;
+  s->bitstringp = bitstringp;
+
+  t->u.kset = s;
+
+  return t;
+}
+
+/* Make a type for a pointer which is relative to an object.  The
+   second argument is the type of the object to which the pointer is
+   relative.  The third argument is the type that the pointer points
+   to.  */
+
+debug_type
+debug_make_offset_type (handle, base_type, target_type)
+     PTR handle;
+     debug_type base_type;
+     debug_type target_type;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_offset_type *o;
+
+  if (base_type == NULL || target_type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_OFFSET, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  o = (struct debug_offset_type *) xmalloc (sizeof *o);
+  memset (o, 0, sizeof *o);
+
+  o->base_type = base_type;
+  o->target_type = target_type;
+
+  t->u.koffset = o;
+
+  return t;
+}
+
+/* Make a type for a method function.  The second argument is the
+   return type, the third argument is the domain, and the fourth
+   argument is a NULL terminated array of argument types.  */
+
+debug_type
+debug_make_method_type (handle, return_type, domain_type, arg_types, varargs)
+     PTR handle;
+     debug_type return_type;
+     debug_type domain_type;
+     debug_type *arg_types;
+     boolean varargs;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_method_type *m;
+
+  if (return_type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_METHOD, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  m = (struct debug_method_type *) xmalloc (sizeof *m);
+  memset (m, 0, sizeof *m);
+
+  m->return_type = return_type;
+  m->domain_type = domain_type;
+  m->arg_types = arg_types;
+  m->varargs = varargs;
+
+  t->u.kmethod = m;
+
+  return t;
+}
+
+/* Make a const qualified version of a given type.  */
+
+debug_type
+debug_make_const_type (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_CONST, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t->u.kconst = type;
+
+  return t;
+}
+
+/* Make a volatile qualified version of a given type.  */
+
+debug_type
+debug_make_volatile_type (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t = debug_make_type (info, DEBUG_KIND_VOLATILE, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  t->u.kvolatile = type;
+
+  return t;
+}
+
+/* Make an undefined tagged type.  For example, a struct which has
+   been mentioned, but not defined.  */
+
+debug_type
+debug_make_undefined_tagged_type (handle, name, kind)
+     PTR handle;
+     const char *name;
+     enum debug_type_kind kind;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+
+  if (name == NULL)
+    return DEBUG_TYPE_NULL;
+
+  switch (kind)
+    {
+    case DEBUG_KIND_STRUCT:
+    case DEBUG_KIND_UNION:
+    case DEBUG_KIND_CLASS:
+    case DEBUG_KIND_UNION_CLASS:
+    case DEBUG_KIND_ENUM:
+      break;
+
+    default:
+      debug_error (_("debug_make_undefined_type: unsupported kind"));
+      return DEBUG_TYPE_NULL;
+    }
+
+  t = debug_make_type (info, kind, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  return debug_tag_type (handle, name, t);
+}
+
+/* Make a base class for an object.  The second argument is the base
+   class type.  The third argument is the bit position of this base
+   class in the object (always 0 unless doing multiple inheritance).
+   The fourth argument is whether this is a virtual class.  The fifth
+   argument is the visibility of the base class.  */
+
+/*ARGSUSED*/
+debug_baseclass
+debug_make_baseclass (handle, type, bitpos, virtual, visibility)
+     PTR handle;
+     debug_type type;
+     bfd_vma bitpos;
+     boolean virtual;
+     enum debug_visibility visibility;
+{     
+  struct debug_baseclass *b;
+
+  b = (struct debug_baseclass *) xmalloc (sizeof *b);
+  memset (b, 0, sizeof *b);
+
+  b->type = type;
+  b->bitpos = bitpos;
+  b->virtual = virtual;
+  b->visibility = visibility;
+
+  return b;
+}
+
+/* Make a field for a struct.  The second argument is the name.  The
+   third argument is the type of the field.  The fourth argument is
+   the bit position of the field.  The fifth argument is the size of
+   the field (it may be zero).  The sixth argument is the visibility
+   of the field.  */
+
+/*ARGSUSED*/
+debug_field
+debug_make_field (handle, name, type, bitpos, bitsize, visibility)
+     PTR handle;
+     const char *name;
+     debug_type type;
+     bfd_vma bitpos;
+     bfd_vma bitsize;
+     enum debug_visibility visibility;
+{
+  struct debug_field *f;
+
+  f = (struct debug_field *) xmalloc (sizeof *f);
+  memset (f, 0, sizeof *f);
+
+  f->name = name;
+  f->type = type;
+  f->static_member = false;
+  f->u.f.bitpos = bitpos;
+  f->u.f.bitsize = bitsize;
+  f->visibility = visibility;
+
+  return f;
+}
+
+/* Make a static member of an object.  The second argument is the
+   name.  The third argument is the type of the member.  The fourth
+   argument is the physical name of the member (i.e., the name as a
+   global variable).  The fifth argument is the visibility of the
+   member.  */
+
+/*ARGSUSED*/
+debug_field
+debug_make_static_member (handle, name, type, physname, visibility)
+     PTR handle;
+     const char *name;
+     debug_type type;
+     const char *physname;
+     enum debug_visibility visibility;
+{
+  struct debug_field *f;
+
+  f = (struct debug_field *) xmalloc (sizeof *f);
+  memset (f, 0, sizeof *f);
+
+  f->name = name;
+  f->type = type;
+  f->static_member = true;
+  f->u.s.physname = physname;
+  f->visibility = visibility;
+
+  return f;
+}
+
+/* Make a method.  The second argument is the name, and the third
+   argument is a NULL terminated array of method variants.  */
+
+/*ARGSUSED*/
+debug_method
+debug_make_method (handle, name, variants)
+     PTR handle;
+     const char *name;
+     debug_method_variant *variants;
+{
+  struct debug_method *m;
+
+  m = (struct debug_method *) xmalloc (sizeof *m);
+  memset (m, 0, sizeof *m);
+
+  m->name = name;
+  m->variants = variants;
+
+  return m;
+}
+
+/* Make a method argument.  The second argument is the real name of
+   the function.  The third argument is the type of the function.  The
+   fourth argument is the visibility.  The fifth argument is whether
+   this is a const function.  The sixth argument is whether this is a
+   volatile function.  The seventh argument is the offset in the
+   virtual function table, if any.  The eighth argument is the virtual
+   function context.  FIXME: Are the const and volatile arguments
+   necessary?  Could we just use debug_make_const_type?  */
+
+/*ARGSUSED*/
+debug_method_variant
+debug_make_method_variant (handle, physname, type, visibility, constp,
+                          volatilep, voffset, context)
+     PTR handle;
+     const char *physname;
+     debug_type type;
+     enum debug_visibility visibility;
+     boolean constp;
+     boolean volatilep;
+     bfd_vma voffset;
+     debug_type context;
+{
+  struct debug_method_variant *m;
+
+  m = (struct debug_method_variant *) xmalloc (sizeof *m);
+  memset (m, 0, sizeof *m);
+
+  m->physname = physname;
+  m->type = type;
+  m->visibility = visibility;
+  m->constp = constp;
+  m->volatilep = volatilep;
+  m->voffset = voffset;
+  m->context = context;
+
+  return m;
+}
+
+/* Make a static method argument.  The arguments are the same as for
+   debug_make_method_variant, except that the last two are omitted
+   since a static method can not also be virtual.  */
+
+debug_method_variant
+debug_make_static_method_variant (handle, physname, type, visibility,
+                                 constp, volatilep)
+     PTR handle;
+     const char *physname;
+     debug_type type;
+     enum debug_visibility visibility;
+     boolean constp;
+     boolean volatilep;
+{
+  struct debug_method_variant *m;
+
+  m = (struct debug_method_variant *) xmalloc (sizeof *m);
+  memset (m, 0, sizeof *m);
+
+  m->physname = physname;
+  m->type = type;
+  m->visibility = visibility;
+  m->constp = constp;
+  m->volatilep = volatilep;
+  m->voffset = VOFFSET_STATIC_METHOD;
+
+  return m;
+}
+
+/* Name a type.  */
+
+debug_type
+debug_name_type (handle, name, type)
+     PTR handle;
+     const char *name;
+     debug_type type;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_named_type *n;
+  struct debug_name *nm;
+
+  if (name == NULL || type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  if (info->current_unit == NULL
+      || info->current_file == NULL)
+    {
+      debug_error (_("debug_name_type: no current file"));
+      return DEBUG_TYPE_NULL;
+    }
+
+  t = debug_make_type (info, DEBUG_KIND_NAMED, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  n = (struct debug_named_type *) xmalloc (sizeof *n);
+  memset (n, 0, sizeof *n);
+
+  n->type = type;
+
+  t->u.knamed = n;
+
+  /* We always add the name to the global namespace.  This is probably
+     wrong in some cases, but it seems to be right for stabs.  FIXME.  */
+
+  nm = debug_add_to_namespace (info, &info->current_file->globals, name,
+                              DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE);
+  if (nm == NULL)
+    return false;
+
+  nm->u.type = t;
+
+  n->name = nm;
+
+  return t;
+}
+
+/* Tag a type.  */
+
+debug_type
+debug_tag_type (handle, name, type)
+     PTR handle;
+     const char *name;
+     debug_type type;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_type *t;
+  struct debug_named_type *n;
+  struct debug_name *nm;
+
+  if (name == NULL || type == NULL)
+    return DEBUG_TYPE_NULL;
+
+  if (info->current_file == NULL)
+    {
+      debug_error (_("debug_tag_type: no current file"));
+      return DEBUG_TYPE_NULL;
+    }
+
+  if (type->kind == DEBUG_KIND_TAGGED)
+    {
+      if (strcmp (type->u.knamed->name->name, name) == 0)
+       return type;
+      debug_error (_("debug_tag_type: extra tag attempted"));
+      return DEBUG_TYPE_NULL;
+    }
+
+  t = debug_make_type (info, DEBUG_KIND_TAGGED, 0);
+  if (t == NULL)
+    return DEBUG_TYPE_NULL;
+
+  n = (struct debug_named_type *) xmalloc (sizeof *n);
+  memset (n, 0, sizeof *n);
+
+  n->type = type;
+
+  t->u.knamed = n;
+
+  /* We keep a global namespace of tags for each compilation unit.  I
+     don't know if that is the right thing to do.  */
+
+  nm = debug_add_to_namespace (info, &info->current_file->globals, name,
+                              DEBUG_OBJECT_TAG, DEBUG_LINKAGE_NONE);
+  if (nm == NULL)
+    return false;
+
+  nm->u.tag = t;
+
+  n->name = nm;
+
+  return t;
+}
+
+/* Record the size of a given type.  */
+
+/*ARGSUSED*/
+boolean
+debug_record_type_size (handle, type, size)
+     PTR handle;
+     debug_type type;
+     unsigned int size;
+{
+  if (type->size != 0 && type->size != size)
+    fprintf (stderr, _("Warning: changing type size from %d to %d\n"),
+            type->size, size);
+
+  type->size = size;
+
+  return true;
+}
+
+/* Find a named type.  */
+
+debug_type
+debug_find_named_type (handle, name)
+     PTR handle;
+     const char *name;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_block *b;
+  struct debug_file *f;
+
+  /* We only search the current compilation unit.  I don't know if
+     this is right or not.  */
+
+  if (info->current_unit == NULL)
+    {
+      debug_error (_("debug_find_named_type: no current compilation unit"));
+      return DEBUG_TYPE_NULL;
+    }
+
+  for (b = info->current_block; b != NULL; b = b->parent)
+    {
+      if (b->locals != NULL)
+       {
+         struct debug_name *n;
+
+         for (n = b->locals->list; n != NULL; n = n->next)
+           {
+             if (n->kind == DEBUG_OBJECT_TYPE
+                 && n->name[0] == name[0]
+                 && strcmp (n->name, name) == 0)
+               return n->u.type;
+           }
+       }
+    }
+
+  for (f = info->current_unit->files; f != NULL; f = f->next)
+    {
+      if (f->globals != NULL)
+       {
+         struct debug_name *n;
+
+         for (n = f->globals->list; n != NULL; n = n->next)
+           {
+             if (n->kind == DEBUG_OBJECT_TYPE
+                 && n->name[0] == name[0]
+                 && strcmp (n->name, name) == 0)
+               return n->u.type;
+           }
+       }
+    }
+
+  return DEBUG_TYPE_NULL;        
+}
+
+/* Find a tagged type.  */
+
+debug_type
+debug_find_tagged_type (handle, name, kind)
+     PTR handle;
+     const char *name;
+     enum debug_type_kind kind;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_unit *u;
+
+  /* We search the globals of all the compilation units.  I don't know
+     if this is correct or not.  It would be easy to change.  */
+
+  for (u = info->units; u != NULL; u = u->next)
+    {
+      struct debug_file *f;
+
+      for (f = u->files; f != NULL; f = f->next)
+       {
+         struct debug_name *n;
+
+         if (f->globals != NULL)
+           {
+             for (n = f->globals->list; n != NULL; n = n->next)
+               {
+                 if (n->kind == DEBUG_OBJECT_TAG
+                     && (kind == DEBUG_KIND_ILLEGAL
+                         || n->u.tag->kind == kind)
+                     && n->name[0] == name[0]
+                     && strcmp (n->name, name) == 0)
+                   return n->u.tag;
+               }
+           }
+       }
+    }
+
+  return DEBUG_TYPE_NULL;
+}
+
+/* Get a base type.  We build a linked list on the stack to avoid
+   crashing if the type is defined circularly.  */
+
+static struct debug_type *
+debug_get_real_type (handle, type, list)
+     PTR handle;
+     debug_type type;
+     struct debug_type_real_list *list;
+{
+  struct debug_type_real_list *l;
+  struct debug_type_real_list rl;
+
+  switch (type->kind)
+    {
+    default:
+      return type;
+
+    case DEBUG_KIND_INDIRECT:
+    case DEBUG_KIND_NAMED:
+    case DEBUG_KIND_TAGGED:
+      break;
+    }
+
+  for (l = list; l != NULL; l = l->next)
+    {
+      if (l->t == type)
+       {
+         fprintf (stderr,
+                  _("debug_get_real_type: circular debug information for %s\n"),
+                  debug_get_type_name (handle, type));
+         return NULL;
+       }
+    }
+
+  rl.next = list;
+  rl.t = type;
+
+  switch (type->kind)
+    {
+      /* The default case is just here to avoid warnings.  */
+    default:
+    case DEBUG_KIND_INDIRECT:
+      if (*type->u.kindirect->slot != NULL)
+       return debug_get_real_type (handle, *type->u.kindirect->slot, &rl);
+      return type;
+    case DEBUG_KIND_NAMED:
+    case DEBUG_KIND_TAGGED:
+      return debug_get_real_type (handle, type->u.knamed->type, &rl);
+    }
+  /*NOTREACHED*/
+}
+
+/* Get the kind of a type.  */
+
+enum debug_type_kind
+debug_get_type_kind (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return DEBUG_KIND_ILLEGAL;
+  type = debug_get_real_type (handle, type, NULL);
+  if (type == NULL)
+    return DEBUG_KIND_ILLEGAL;
+  return type->kind;
+}
+
+/* Get the name of a type.  */
+
+const char *
+debug_get_type_name (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type->kind == DEBUG_KIND_INDIRECT)
+    {
+      if (*type->u.kindirect->slot != NULL)
+       return debug_get_type_name (handle, *type->u.kindirect->slot);
+      return type->u.kindirect->tag;
+    }
+  if (type->kind == DEBUG_KIND_NAMED
+      || type->kind == DEBUG_KIND_TAGGED)
+    return type->u.knamed->name->name;
+  return NULL;
+}
+
+/* Get the size of a type.  */
+
+bfd_vma
+debug_get_type_size (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return 0;
+
+  /* We don't call debug_get_real_type, because somebody might have
+     called debug_record_type_size on a named or indirect type.  */
+
+  if (type->size != 0)
+    return type->size;
+
+  switch (type->kind)
+    {
+    default:
+      return 0;
+    case DEBUG_KIND_INDIRECT:
+      if (*type->u.kindirect->slot != NULL)
+       return debug_get_type_size (handle, *type->u.kindirect->slot);
+      return 0;
+    case DEBUG_KIND_NAMED:
+    case DEBUG_KIND_TAGGED:
+      return debug_get_type_size (handle, type->u.knamed->type);
+    }
+  /*NOTREACHED*/
+}
+
+/* Get the return type of a function or method type.  */
+
+debug_type
+debug_get_return_type (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+  type = debug_get_real_type (handle, type, NULL);
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+  switch (type->kind)
+    {
+    default:
+      return DEBUG_TYPE_NULL;
+    case DEBUG_KIND_FUNCTION:
+      return type->u.kfunction->return_type;
+    case DEBUG_KIND_METHOD:
+      return type->u.kmethod->return_type;
+    }
+  /*NOTREACHED*/      
+}
+
+/* Get the parameter types of a function or method type (except that
+   we don't currently store the parameter types of a function).  */
+
+const debug_type *
+debug_get_parameter_types (handle, type, pvarargs)
+     PTR handle;
+     debug_type type;
+     boolean *pvarargs;
+{
+  if (type == NULL)
+    return NULL;
+  type = debug_get_real_type (handle, type, NULL);
+  if (type == NULL)
+    return NULL;
+  switch (type->kind)
+    {
+    default:
+      return NULL;
+    case DEBUG_KIND_FUNCTION:
+      *pvarargs = type->u.kfunction->varargs;
+      return type->u.kfunction->arg_types;
+    case DEBUG_KIND_METHOD:
+      *pvarargs = type->u.kmethod->varargs;
+      return type->u.kmethod->arg_types;
+    }
+  /*NOTREACHED*/
+}
+
+/* Get the target type of a type.  */
+
+debug_type
+debug_get_target_type (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return NULL;
+  type = debug_get_real_type (handle, type, NULL);
+  if (type == NULL)
+    return NULL;
+  switch (type->kind)
+    {
+    default:
+      return NULL;
+    case DEBUG_KIND_POINTER:
+      return type->u.kpointer;
+    case DEBUG_KIND_REFERENCE:
+      return type->u.kreference;
+    case DEBUG_KIND_CONST:
+      return type->u.kconst;
+    case DEBUG_KIND_VOLATILE:
+      return type->u.kvolatile;
+    }
+  /*NOTREACHED*/
+}
+
+/* Get the NULL terminated array of fields for a struct, union, or
+   class.  */
+
+const debug_field *
+debug_get_fields (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return NULL;
+  type = debug_get_real_type (handle, type, NULL);
+  if (type == NULL)
+    return NULL;
+  switch (type->kind)
+    {
+    default:
+      return NULL;
+    case DEBUG_KIND_STRUCT:
+    case DEBUG_KIND_UNION:
+    case DEBUG_KIND_CLASS:
+    case DEBUG_KIND_UNION_CLASS:
+      return type->u.kclass->fields;
+    }
+  /*NOTREACHED*/
+}
+
+/* Get the type of a field.  */
+
+/*ARGSUSED*/
+debug_type
+debug_get_field_type (handle, field)
+     PTR handle;
+     debug_field field;
+{
+  if (field == NULL)
+    return NULL;
+  return field->type;
+}
+
+/* Get the name of a field.  */
+
+/*ARGSUSED*/
+const char *
+debug_get_field_name (handle, field)
+     PTR handle;
+     debug_field field;
+{
+  if (field == NULL)
+    return NULL;
+  return field->name;
+}
+
+/* Get the bit position of a field.  */
+
+/*ARGSUSED*/
+bfd_vma
+debug_get_field_bitpos (handle, field)
+     PTR handle;
+     debug_field field;
+{
+  if (field == NULL || field->static_member)
+    return (bfd_vma) -1;
+  return field->u.f.bitpos;
+}
+
+/* Get the bit size of a field.  */
+
+/*ARGSUSED*/
+bfd_vma
+debug_get_field_bitsize (handle, field)
+     PTR handle;
+     debug_field field;
+{
+  if (field == NULL || field->static_member)
+    return (bfd_vma) -1;
+  return field->u.f.bitsize;
+}
+
+/* Get the visibility of a field.  */
+
+/*ARGSUSED*/
+enum debug_visibility
+debug_get_field_visibility (handle, field)
+     PTR handle;
+     debug_field field;
+{
+  if (field == NULL)
+    return DEBUG_VISIBILITY_IGNORE;
+  return field->visibility;
+}
+
+/* Get the physical name of a field.  */
+
+const char *
+debug_get_field_physname (handle, field)
+     PTR handle;
+     debug_field field;
+{
+  if (field == NULL || ! field->static_member)
+    return NULL;
+  return field->u.s.physname;
+}
+\f
+/* Write out the debugging information.  This is given a handle to
+   debugging information, and a set of function pointers to call.  */
+
+boolean
+debug_write (handle, fns, fhandle)
+     PTR handle;
+     const struct debug_write_fns *fns;
+     PTR fhandle;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_unit *u;
+
+  /* We use a mark to tell whether we have already written out a
+     particular name.  We use an integer, so that we don't have to
+     clear the mark fields if we happen to write out the same
+     information more than once.  */
+  ++info->mark;
+
+  /* The base_id field holds an ID value which will never be used, so
+     that we can tell whether we have assigned an ID during this call
+     to debug_write.  */
+  info->base_id = info->class_id;
+
+  /* We keep a linked list of classes for which was have assigned ID's
+     during this call to debug_write.  */
+  info->id_list = NULL;
+
+  for (u = info->units; u != NULL; u = u->next)
+    {
+      struct debug_file *f;
+      boolean first_file;
+
+      info->current_write_lineno = u->linenos;
+      info->current_write_lineno_index = 0;
+
+      if (! (*fns->start_compilation_unit) (fhandle, u->files->filename))
+       return false;
+
+      first_file = true;
+      for (f = u->files; f != NULL; f = f->next)
+       {
+         struct debug_name *n;
+
+         if (first_file)
+           first_file = false;
+         else
+           {
+             if (! (*fns->start_source) (fhandle, f->filename))
+               return false;
+           }
+
+         if (f->globals != NULL)
+           {
+             for (n = f->globals->list; n != NULL; n = n->next)
+               {
+                 if (! debug_write_name (info, fns, fhandle, n))
+                   return false;
+               }
+           }
+       }
+
+      /* Output any line number information which hasn't already been
+         handled.  */
+      if (! debug_write_linenos (info, fns, fhandle, (bfd_vma) -1))
+       return false;
+    }
+
+  return true;
+}
+
+/* Write out an element in a namespace.  */
+
+static boolean
+debug_write_name (info, fns, fhandle, n)
+     struct debug_handle *info;
+     const struct debug_write_fns *fns;
+     PTR fhandle;
+     struct debug_name *n;
+{
+  switch (n->kind)
+    {
+    case DEBUG_OBJECT_TYPE:
+      if (! debug_write_type (info, fns, fhandle, n->u.type, n)
+         || ! (*fns->typdef) (fhandle, n->name))
+       return false;
+      return true;
+    case DEBUG_OBJECT_TAG:
+      if (! debug_write_type (info, fns, fhandle, n->u.tag, n))
+       return false;
+      return (*fns->tag) (fhandle, n->name);
+    case DEBUG_OBJECT_VARIABLE:
+      if (! debug_write_type (info, fns, fhandle, n->u.variable->type,
+                             (struct debug_name *) NULL))
+       return false;
+      return (*fns->variable) (fhandle, n->name, n->u.variable->kind,
+                              n->u.variable->val);
+    case DEBUG_OBJECT_FUNCTION:
+      return debug_write_function (info, fns, fhandle, n->name,
+                                  n->linkage, n->u.function);
+    case DEBUG_OBJECT_INT_CONSTANT:
+      return (*fns->int_constant) (fhandle, n->name, n->u.int_constant);
+    case DEBUG_OBJECT_FLOAT_CONSTANT:
+      return (*fns->float_constant) (fhandle, n->name, n->u.float_constant);
+    case DEBUG_OBJECT_TYPED_CONSTANT:
+      if (! debug_write_type (info, fns, fhandle, n->u.typed_constant->type,
+                             (struct debug_name *) NULL))
+       return false;
+      return (*fns->typed_constant) (fhandle, n->name,
+                                    n->u.typed_constant->val);
+    default:
+      abort ();
+      return false;
+    }
+  /*NOTREACHED*/
+}
+
+/* Write out a type.  If the type is DEBUG_KIND_NAMED or
+   DEBUG_KIND_TAGGED, then the name argument is the name for which we
+   are about to call typedef or tag.  If the type is anything else,
+   then the name argument is a tag from a DEBUG_KIND_TAGGED type which
+   points to this one.  */
+
+static boolean
+debug_write_type (info, fns, fhandle, type, name)
+     struct debug_handle *info;
+     const struct debug_write_fns *fns;
+     PTR fhandle;
+     struct debug_type *type;
+     struct debug_name *name;
+{
+  unsigned int i;
+  int is;
+  const char *tag;
+
+  /* If we have a name for this type, just output it.  We only output
+     typedef names after they have been defined.  We output type tags
+     whenever we are not actually defining them.  */
+  if ((type->kind == DEBUG_KIND_NAMED
+       || type->kind == DEBUG_KIND_TAGGED)
+      && (type->u.knamed->name->mark == info->mark
+         || (type->kind == DEBUG_KIND_TAGGED
+             && type->u.knamed->name != name)))
+    {
+      if (type->kind == DEBUG_KIND_NAMED)
+       return (*fns->typedef_type) (fhandle, type->u.knamed->name->name);
+      else
+       {
+         struct debug_type *real;
+         unsigned int id;
+
+         real = debug_get_real_type ((PTR) info, type, NULL);
+         if (real == NULL)
+           return (*fns->empty_type) (fhandle);
+         id = 0;
+         if ((real->kind == DEBUG_KIND_STRUCT
+              || real->kind == DEBUG_KIND_UNION
+              || real->kind == DEBUG_KIND_CLASS
+              || real->kind == DEBUG_KIND_UNION_CLASS)
+             && real->u.kclass != NULL)
+           {
+             if (real->u.kclass->id <= info->base_id)
+               {
+                 if (! debug_set_class_id (info,
+                                           type->u.knamed->name->name,
+                                           real))
+                   return false;
+               }
+             id = real->u.kclass->id;
+           }
+
+         return (*fns->tag_type) (fhandle, type->u.knamed->name->name, id,
+                                  real->kind);
+       }
+    }
+
+  /* Mark the name after we have already looked for a known name, so
+     that we don't just define a type in terms of itself.  We need to
+     mark the name here so that a struct containing a pointer to
+     itself will work.  */
+  if (name != NULL)
+    name->mark = info->mark;
+
+  tag = NULL;
+  if (name != NULL
+      && type->kind != DEBUG_KIND_NAMED
+      && type->kind != DEBUG_KIND_TAGGED)
+    {
+      assert (name->kind == DEBUG_OBJECT_TAG);
+      tag = name->name;
+    }
+
+  switch (type->kind)
+    {
+    case DEBUG_KIND_ILLEGAL:
+      debug_error (_("debug_write_type: illegal type encountered"));
+      return false;
+    case DEBUG_KIND_INDIRECT:
+      if (*type->u.kindirect->slot == DEBUG_TYPE_NULL)
+       return (*fns->empty_type) (fhandle);
+      return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot,
+                              name);
+    case DEBUG_KIND_VOID:
+      return (*fns->void_type) (fhandle);
+    case DEBUG_KIND_INT:
+      return (*fns->int_type) (fhandle, type->size, type->u.kint);
+    case DEBUG_KIND_FLOAT:
+      return (*fns->float_type) (fhandle, type->size);
+    case DEBUG_KIND_COMPLEX:
+      return (*fns->complex_type) (fhandle, type->size);
+    case DEBUG_KIND_BOOL:
+      return (*fns->bool_type) (fhandle, type->size);
+    case DEBUG_KIND_STRUCT:
+    case DEBUG_KIND_UNION:
+      if (type->u.kclass != NULL)
+       {
+         if (type->u.kclass->id <= info->base_id)
+           {
+             if (! debug_set_class_id (info, tag, type))
+               return false;
+           }
+
+         if (info->mark == type->u.kclass->mark)
+           {
+             /* We are currently outputting this struct, or we have
+                already output it.  I don't know if this can happen,
+                but it can happen for a class.  */
+             assert (type->u.kclass->id > info->base_id);
+             return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
+                                      type->kind);
+           }
+         type->u.kclass->mark = info->mark;
+       }
+
+      if (! (*fns->start_struct_type) (fhandle, tag,
+                                      (type->u.kclass != NULL
+                                       ? type->u.kclass->id
+                                       : 0),
+                                      type->kind == DEBUG_KIND_STRUCT,
+                                      type->size))
+       return false;
+      if (type->u.kclass != NULL
+         && type->u.kclass->fields != NULL)
+       {
+         for (i = 0; type->u.kclass->fields[i] != NULL; i++)
+           {
+             struct debug_field *f;
+
+             f = type->u.kclass->fields[i];
+             if (! debug_write_type (info, fns, fhandle, f->type,
+                                     (struct debug_name *) NULL)
+                 || ! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos,
+                                            f->u.f.bitsize, f->visibility))
+               return false;
+           }
+       }
+      return (*fns->end_struct_type) (fhandle);
+    case DEBUG_KIND_CLASS:
+    case DEBUG_KIND_UNION_CLASS:
+      return debug_write_class_type (info, fns, fhandle, type, tag);
+    case DEBUG_KIND_ENUM:
+      if (type->u.kenum == NULL)
+       return (*fns->enum_type) (fhandle, tag, (const char **) NULL,
+                                 (bfd_signed_vma *) NULL);
+      return (*fns->enum_type) (fhandle, tag, type->u.kenum->names,
+                               type->u.kenum->values);
+    case DEBUG_KIND_POINTER:
+      if (! debug_write_type (info, fns, fhandle, type->u.kpointer,
+                             (struct debug_name *) NULL))
+       return false;
+      return (*fns->pointer_type) (fhandle);
+    case DEBUG_KIND_FUNCTION:
+      if (! debug_write_type (info, fns, fhandle,
+                             type->u.kfunction->return_type,
+                             (struct debug_name *) NULL))
+       return false;
+      if (type->u.kfunction->arg_types == NULL)
+       is = -1;
+      else
+       {
+         for (is = 0; type->u.kfunction->arg_types[is] != NULL; is++)
+           if (! debug_write_type (info, fns, fhandle,
+                                   type->u.kfunction->arg_types[is],
+                                   (struct debug_name *) NULL))
+             return false;
+       }
+      return (*fns->function_type) (fhandle, is,
+                                   type->u.kfunction->varargs);
+    case DEBUG_KIND_REFERENCE:
+      if (! debug_write_type (info, fns, fhandle, type->u.kreference,
+                             (struct debug_name *) NULL))
+       return false;
+      return (*fns->reference_type) (fhandle);
+    case DEBUG_KIND_RANGE:
+      if (! debug_write_type (info, fns, fhandle, type->u.krange->type,
+                             (struct debug_name *) NULL))
+       return false;
+      return (*fns->range_type) (fhandle, type->u.krange->lower,
+                                type->u.krange->upper);
+    case DEBUG_KIND_ARRAY:
+      if (! debug_write_type (info, fns, fhandle, type->u.karray->element_type,
+                             (struct debug_name *) NULL)
+         || ! debug_write_type (info, fns, fhandle,
+                                type->u.karray->range_type,
+                                (struct debug_name *) NULL))
+       return false;
+      return (*fns->array_type) (fhandle, type->u.karray->lower,
+                                type->u.karray->upper,
+                                type->u.karray->stringp);
+    case DEBUG_KIND_SET:
+      if (! debug_write_type (info, fns, fhandle, type->u.kset->type,
+                             (struct debug_name *) NULL))
+       return false;
+      return (*fns->set_type) (fhandle, type->u.kset->bitstringp);
+    case DEBUG_KIND_OFFSET:
+      if (! debug_write_type (info, fns, fhandle, type->u.koffset->base_type,
+                             (struct debug_name *) NULL)
+         || ! debug_write_type (info, fns, fhandle,
+                                type->u.koffset->target_type,
+                                (struct debug_name *) NULL))
+       return false;
+      return (*fns->offset_type) (fhandle);
+    case DEBUG_KIND_METHOD:
+      if (! debug_write_type (info, fns, fhandle,
+                             type->u.kmethod->return_type,
+                             (struct debug_name *) NULL))
+       return false;
+      if (type->u.kmethod->arg_types == NULL)
+       is = -1;
+      else
+       {
+         for (is = 0; type->u.kmethod->arg_types[is] != NULL; is++)
+           if (! debug_write_type (info, fns, fhandle,
+                                   type->u.kmethod->arg_types[is],
+                                   (struct debug_name *) NULL))
+             return false;
+       }
+      if (type->u.kmethod->domain_type != NULL)
+       {
+         if (! debug_write_type (info, fns, fhandle,
+                                 type->u.kmethod->domain_type,
+                                 (struct debug_name *) NULL))
+           return false;
+       }
+      return (*fns->method_type) (fhandle,
+                                 type->u.kmethod->domain_type != NULL,
+                                 is,
+                                 type->u.kmethod->varargs);
+    case DEBUG_KIND_CONST:
+      if (! debug_write_type (info, fns, fhandle, type->u.kconst,
+                             (struct debug_name *) NULL))
+       return false;
+      return (*fns->const_type) (fhandle);
+    case DEBUG_KIND_VOLATILE:
+      if (! debug_write_type (info, fns, fhandle, type->u.kvolatile,
+                             (struct debug_name *) NULL))
+       return false;
+      return (*fns->volatile_type) (fhandle);
+    case DEBUG_KIND_NAMED:
+      return debug_write_type (info, fns, fhandle, type->u.knamed->type,
+                              (struct debug_name *) NULL);
+    case DEBUG_KIND_TAGGED:
+      return debug_write_type (info, fns, fhandle, type->u.knamed->type,
+                              type->u.knamed->name);
+    default:
+      abort ();
+      return false;
+    }
+}
+
+/* Write out a class type.  */
+
+static boolean
+debug_write_class_type (info, fns, fhandle, type, tag)
+     struct debug_handle *info;
+     const struct debug_write_fns *fns;
+     PTR fhandle;
+     struct debug_type *type;
+     const char *tag;
+{
+  unsigned int i;
+  unsigned int id;
+  struct debug_type *vptrbase;
+
+  if (type->u.kclass == NULL)
+    {
+      id = 0;
+      vptrbase = NULL;
+    }
+  else
+    {
+      if (type->u.kclass->id <= info->base_id)
+       {
+         if (! debug_set_class_id (info, tag, type))
+           return false;
+       }
+
+      if (info->mark == type->u.kclass->mark)
+       {
+         /* We are currently outputting this class, or we have
+            already output it.  This can happen when there are
+            methods for an anonymous class.  */
+         assert (type->u.kclass->id > info->base_id);
+         return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
+                                  type->kind);
+       }
+      type->u.kclass->mark = info->mark;
+      id = type->u.kclass->id;
+
+      vptrbase = type->u.kclass->vptrbase;
+      if (vptrbase != NULL && vptrbase != type)
+       {
+         if (! debug_write_type (info, fns, fhandle, vptrbase,
+                                 (struct debug_name *) NULL))
+           return false;
+       }
+    }
+
+  if (! (*fns->start_class_type) (fhandle, tag, id,
+                                 type->kind == DEBUG_KIND_CLASS,
+                                 type->size,
+                                 vptrbase != NULL,
+                                 vptrbase == type))
+    return false;
+
+  if (type->u.kclass != NULL)
+    {
+      if (type->u.kclass->fields != NULL)
+       {
+         for (i = 0; type->u.kclass->fields[i] != NULL; i++)
+           {
+             struct debug_field *f;
+
+             f = type->u.kclass->fields[i];
+             if (! debug_write_type (info, fns, fhandle, f->type,
+                                     (struct debug_name *) NULL))
+               return false;
+             if (f->static_member)
+               {
+                 if (! (*fns->class_static_member) (fhandle, f->name,
+                                                    f->u.s.physname,
+                                                    f->visibility))
+                   return false;
+               }
+             else
+               {
+                 if (! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos,
+                                             f->u.f.bitsize, f->visibility))
+                   return false;
+               }
+           }
+       }
+
+      if (type->u.kclass->baseclasses != NULL)
+       {
+         for (i = 0; type->u.kclass->baseclasses[i] != NULL; i++)
+           {
+             struct debug_baseclass *b;
+
+             b = type->u.kclass->baseclasses[i];
+             if (! debug_write_type (info, fns, fhandle, b->type,
+                                     (struct debug_name *) NULL))
+               return false;
+             if (! (*fns->class_baseclass) (fhandle, b->bitpos, b->virtual,
+                                            b->visibility))
+               return false;
+           }
+       }
+
+      if (type->u.kclass->methods != NULL)
+       {
+         for (i = 0; type->u.kclass->methods[i] != NULL; i++)
+           {
+             struct debug_method *m;
+             unsigned int j;
+
+             m = type->u.kclass->methods[i];
+             if (! (*fns->class_start_method) (fhandle, m->name))
+               return false;
+             for (j = 0; m->variants[j] != NULL; j++)
+               {
+                 struct debug_method_variant *v;
+
+                 v = m->variants[j];
+                 if (v->context != NULL)
+                   {
+                     if (! debug_write_type (info, fns, fhandle, v->context,
+                                             (struct debug_name *) NULL))
+                       return false;
+                   }
+                 if (! debug_write_type (info, fns, fhandle, v->type,
+                                         (struct debug_name *) NULL))
+                   return false;
+                 if (v->voffset != VOFFSET_STATIC_METHOD)
+                   {
+                     if (! (*fns->class_method_variant) (fhandle, v->physname,
+                                                         v->visibility,
+                                                         v->constp,
+                                                         v->volatilep,
+                                                         v->voffset,
+                                                         v->context != NULL))
+                       return false;
+                   }
+                 else
+                   {
+                     if (! (*fns->class_static_method_variant) (fhandle,
+                                                                v->physname,
+                                                                v->visibility,
+                                                                v->constp,
+                                                                v->volatilep))
+                       return false;
+                   }
+               }
+             if (! (*fns->class_end_method) (fhandle))
+               return false;
+           }
+       }
+    }
+
+  return (*fns->end_class_type) (fhandle);
+}
+
+/* Write out information for a function.  */
+
+static boolean
+debug_write_function (info, fns, fhandle, name, linkage, function)
+     struct debug_handle *info;
+     const struct debug_write_fns *fns;
+     PTR fhandle;
+     const char *name;
+     enum debug_object_linkage linkage;
+     struct debug_function *function;
+{
+  struct debug_parameter *p;
+  struct debug_block *b;
+
+  if (! debug_write_linenos (info, fns, fhandle, function->blocks->start))
+    return false;
+
+  if (! debug_write_type (info, fns, fhandle, function->return_type,
+                         (struct debug_name *) NULL))
+    return false;
+
+  if (! (*fns->start_function) (fhandle, name,
+                               linkage == DEBUG_LINKAGE_GLOBAL))
+    return false;
+
+  for (p = function->parameters; p != NULL; p = p->next)
+    {
+      if (! debug_write_type (info, fns, fhandle, p->type,
+                             (struct debug_name *) NULL)
+         || ! (*fns->function_parameter) (fhandle, p->name, p->kind, p->val))
+       return false;
+    }
+
+  for (b = function->blocks; b != NULL; b = b->next)
+    {
+      if (! debug_write_block (info, fns, fhandle, b))
+       return false;
+    }
+
+  return (*fns->end_function) (fhandle);
+}
+
+/* Write out information for a block.  */
+
+static boolean
+debug_write_block (info, fns, fhandle, block)
+     struct debug_handle *info;
+     const struct debug_write_fns *fns;
+     PTR fhandle;
+     struct debug_block *block;
+{
+  struct debug_name *n;
+  struct debug_block *b;
+
+  if (! debug_write_linenos (info, fns, fhandle, block->start))
+    return false;
+
+  /* I can't see any point to writing out a block with no local
+     variables, so we don't bother, except for the top level block.  */
+  if (block->locals != NULL || block->parent == NULL)
+    {
+      if (! (*fns->start_block) (fhandle, block->start))
+       return false;
+    }
+
+  if (block->locals != NULL)
+    {
+      for (n = block->locals->list; n != NULL; n = n->next)
+       {
+         if (! debug_write_name (info, fns, fhandle, n))
+           return false;
+       }
+    }
+
+  for (b = block->children; b != NULL; b = b->next)
+    {
+      if (! debug_write_block (info, fns, fhandle, b))
+       return false;
+    }
+
+  if (! debug_write_linenos (info, fns, fhandle, block->end))
+    return false;
+
+  if (block->locals != NULL || block->parent == NULL)
+    {
+      if (! (*fns->end_block) (fhandle, block->end))
+       return false;
+    }
+
+  return true;
+}
+
+/* Write out line number information up to ADDRESS.  */
+
+static boolean
+debug_write_linenos (info, fns, fhandle, address)
+     struct debug_handle *info;
+     const struct debug_write_fns *fns;
+     PTR fhandle;
+     bfd_vma address;
+{
+  while (info->current_write_lineno != NULL)
+    {
+      struct debug_lineno *l;
+
+      l = info->current_write_lineno;
+
+      while (info->current_write_lineno_index < DEBUG_LINENO_COUNT)
+       {
+         if (l->linenos[info->current_write_lineno_index]
+             == (unsigned long) -1)
+           break;
+
+         if (l->addrs[info->current_write_lineno_index] >= address)
+           return true;
+
+         if (! (*fns->lineno) (fhandle, l->file->filename,
+                               l->linenos[info->current_write_lineno_index],
+                               l->addrs[info->current_write_lineno_index]))
+           return false;
+
+         ++info->current_write_lineno_index;
+       }
+
+      info->current_write_lineno = l->next;
+      info->current_write_lineno_index = 0;
+    }
+
+  return true;
+}
+
+/* Get the ID number for a class.  If during the same call to
+   debug_write we find a struct with the same definition with the same
+   name, we use the same ID.  This type of things happens because the
+   same struct will be defined by multiple compilation units.  */
+
+static boolean
+debug_set_class_id (info, tag, type)
+     struct debug_handle *info;
+     const char *tag;
+     struct debug_type *type;
+{
+  struct debug_class_type *c;
+  struct debug_class_id *l;
+
+  assert (type->kind == DEBUG_KIND_STRUCT
+         || type->kind == DEBUG_KIND_UNION
+         || type->kind == DEBUG_KIND_CLASS
+         || type->kind == DEBUG_KIND_UNION_CLASS);
+
+  c = type->u.kclass;
+
+  if (c->id > info->base_id)
+    return true;
+
+  for (l = info->id_list; l != NULL; l = l->next)
+    {
+      if (l->type->kind != type->kind)
+       continue;
+
+      if (tag == NULL)
+       {
+         if (l->tag != NULL)
+           continue;
+       }
+      else
+       {
+         if (l->tag == NULL
+             || l->tag[0] != tag[0]
+             || strcmp (l->tag, tag) != 0)
+           continue;
+       }
+
+      if (debug_type_samep (info, l->type, type))
+       {
+         c->id = l->type->u.kclass->id;
+         return true;
+       }
+    }
+
+  /* There are no identical types.  Use a new ID, and add it to the
+     list.  */
+  ++info->class_id;
+  c->id = info->class_id;
+
+  l = (struct debug_class_id *) xmalloc (sizeof *l);
+  memset (l, 0, sizeof *l);
+
+  l->type = type;
+  l->tag = tag;
+
+  l->next = info->id_list;
+  info->id_list = l;
+
+  return true;
+}
+
+/* See if two types are the same.  At this point, we don't care about
+   tags and the like.  */
+
+static boolean
+debug_type_samep (info, t1, t2)
+     struct debug_handle *info;
+     struct debug_type *t1;
+     struct debug_type *t2;
+{
+  struct debug_type_compare_list *l;
+  struct debug_type_compare_list top;
+  boolean ret;
+
+  if (t1 == NULL)
+    return t2 == NULL;
+  if (t2 == NULL)
+    return false;
+
+  while (t1->kind == DEBUG_KIND_INDIRECT)
+    {
+      t1 = *t1->u.kindirect->slot;
+      if (t1 == NULL)
+       return false;
+    }
+  while (t2->kind == DEBUG_KIND_INDIRECT)
+    {
+      t2 = *t2->u.kindirect->slot;
+      if (t2 == NULL)
+       return false;
+    }
+
+  if (t1 == t2)
+    return true;
+
+  /* As a special case, permit a typedef to match a tag, since C++
+     debugging output will sometimes add a typedef where C debugging
+     output will not.  */
+  if (t1->kind == DEBUG_KIND_NAMED
+      && t2->kind == DEBUG_KIND_TAGGED)
+    return debug_type_samep (info, t1->u.knamed->type, t2);
+  else if (t1->kind == DEBUG_KIND_TAGGED
+          && t2->kind == DEBUG_KIND_NAMED)
+    return debug_type_samep (info, t1, t2->u.knamed->type);
+
+  if (t1->kind != t2->kind
+      || t1->size != t2->size)
+    return false;
+
+  /* Get rid of the trivial cases first.  */
+  switch (t1->kind)
+    {
+    default:
+      break;
+    case DEBUG_KIND_VOID:
+    case DEBUG_KIND_FLOAT:
+    case DEBUG_KIND_COMPLEX:
+    case DEBUG_KIND_BOOL:
+      return true;
+    case DEBUG_KIND_INT:
+      return t1->u.kint == t2->u.kint;
+    }
+
+  /* We have to avoid an infinite recursion.  We do this by keeping a
+     list of types which we are comparing.  We just keep the list on
+     the stack.  If we encounter a pair of types we are currently
+     comparing, we just assume that they are equal.  */
+  for (l = info->compare_list; l != NULL; l = l->next)
+    {
+      if (l->t1 == t1 && l->t2 == t2)
+       return true;
+    }
+
+  top.t1 = t1;
+  top.t2 = t2;
+  top.next = info->compare_list;
+  info->compare_list = &top;
+
+  switch (t1->kind)
+    {
+    default:
+      abort ();
+      ret = false;
+      break;
+
+    case DEBUG_KIND_STRUCT:
+    case DEBUG_KIND_UNION:
+    case DEBUG_KIND_CLASS:
+    case DEBUG_KIND_UNION_CLASS:
+      if (t1->u.kclass == NULL)
+       ret = t2->u.kclass == NULL;
+      else if (t2->u.kclass == NULL)
+       ret = false;
+      else if (t1->u.kclass->id > info->base_id
+              && t1->u.kclass->id == t2->u.kclass->id)
+       ret = true;
+      else
+       ret = debug_class_type_samep (info, t1, t2);
+      break;
+
+    case DEBUG_KIND_ENUM:
+      if (t1->u.kenum == NULL)
+       ret = t2->u.kenum == NULL;
+      else if (t2->u.kenum == NULL)
+       ret = false;
+      else
+       {
+         const char **pn1, **pn2;
+         bfd_signed_vma *pv1, *pv2;
+
+         pn1 = t1->u.kenum->names;
+         pn2 = t2->u.kenum->names;
+         pv1 = t1->u.kenum->values;
+         pv2 = t2->u.kenum->values;
+         while (*pn1 != NULL && *pn2 != NULL)
+           {
+             if (**pn1 != **pn2
+                 || *pv1 != *pv2
+                 || strcmp (*pn1, *pn2) != 0)
+               break;
+             ++pn1;
+             ++pn2;
+             ++pv1;
+             ++pv2;
+           }
+         ret = *pn1 == NULL && *pn2 == NULL;
+       }
+      break;
+
+    case DEBUG_KIND_POINTER:
+      ret = debug_type_samep (info, t1->u.kpointer, t2->u.kpointer);
+      break;
+            
+    case DEBUG_KIND_FUNCTION:
+      if (t1->u.kfunction->varargs != t2->u.kfunction->varargs
+         || ! debug_type_samep (info, t1->u.kfunction->return_type,
+                                t2->u.kfunction->return_type)
+         || ((t1->u.kfunction->arg_types == NULL)
+             != (t2->u.kfunction->arg_types == NULL)))
+       ret = false;
+      else if (t1->u.kfunction->arg_types == NULL)
+       ret = true;
+      else
+       {
+         struct debug_type **a1, **a2;
+
+         a1 = t1->u.kfunction->arg_types;
+         a2 = t2->u.kfunction->arg_types;
+         while (*a1 != NULL && *a2 != NULL)
+           {
+             if (! debug_type_samep (info, *a1, *a2))
+               break;
+             ++a1;
+             ++a2;
+           }
+         ret = *a1 == NULL && *a2 == NULL;
+       }
+      break;
+
+    case DEBUG_KIND_REFERENCE:
+      ret = debug_type_samep (info, t1->u.kreference, t2->u.kreference);
+      break;
+
+    case DEBUG_KIND_RANGE:
+      ret = (t1->u.krange->lower == t2->u.krange->lower
+            && t1->u.krange->upper == t2->u.krange->upper
+            && debug_type_samep (info, t1->u.krange->type,
+                                 t2->u.krange->type));
+
+    case DEBUG_KIND_ARRAY:
+      ret = (t1->u.karray->lower == t2->u.karray->lower
+            && t1->u.karray->upper == t2->u.karray->upper
+            && t1->u.karray->stringp == t2->u.karray->stringp
+            && debug_type_samep (info, t1->u.karray->element_type,
+                                 t2->u.karray->element_type));
+      break;
+
+    case DEBUG_KIND_SET:
+      ret = (t1->u.kset->bitstringp == t2->u.kset->bitstringp
+            && debug_type_samep (info, t1->u.kset->type, t2->u.kset->type));
+      break;
+
+    case DEBUG_KIND_OFFSET:
+      ret = (debug_type_samep (info, t1->u.koffset->base_type,
+                              t2->u.koffset->base_type)
+            && debug_type_samep (info, t1->u.koffset->target_type,
+                                 t2->u.koffset->target_type));
+      break;
+
+    case DEBUG_KIND_METHOD:
+      if (t1->u.kmethod->varargs != t2->u.kmethod->varargs
+         || ! debug_type_samep (info, t1->u.kmethod->return_type,
+                                t2->u.kmethod->return_type)
+         || ! debug_type_samep (info, t1->u.kmethod->domain_type,
+                                t2->u.kmethod->domain_type)
+         || ((t1->u.kmethod->arg_types == NULL)
+             != (t2->u.kmethod->arg_types == NULL)))
+       ret = false;
+      else if (t1->u.kmethod->arg_types == NULL)
+       ret = true;
+      else
+       {
+         struct debug_type **a1, **a2;
+
+         a1 = t1->u.kmethod->arg_types;
+         a2 = t2->u.kmethod->arg_types;
+         while (*a1 != NULL && *a2 != NULL)
+           {
+             if (! debug_type_samep (info, *a1, *a2))
+               break;
+             ++a1;
+             ++a2;
+           }
+         ret = *a1 == NULL && *a2 == NULL;
+       }
+      break;
+
+    case DEBUG_KIND_CONST:
+      ret = debug_type_samep (info, t1->u.kconst, t2->u.kconst);
+      break;
+
+    case DEBUG_KIND_VOLATILE:
+      ret = debug_type_samep (info, t1->u.kvolatile, t2->u.kvolatile);
+      break;
+
+    case DEBUG_KIND_NAMED:
+    case DEBUG_KIND_TAGGED:
+      ret = (strcmp (t1->u.knamed->name->name, t2->u.knamed->name->name) == 0
+            && debug_type_samep (info, t1->u.knamed->type,
+                                 t2->u.knamed->type));
+      break;
+    }
+
+  info->compare_list = top.next;
+
+  return ret;
+}
+
+/* See if two classes are the same.  This is a subroutine of
+   debug_type_samep.  */
+
+static boolean
+debug_class_type_samep (info, t1, t2)
+     struct debug_handle *info;
+     struct debug_type *t1;
+     struct debug_type *t2;
+{
+  struct debug_class_type *c1, *c2;
+
+  c1 = t1->u.kclass;
+  c2 = t2->u.kclass;
+
+  if ((c1->fields == NULL) != (c2->fields == NULL)
+      || (c1->baseclasses == NULL) != (c2->baseclasses == NULL)
+      || (c1->methods == NULL) != (c2->methods == NULL)
+      || (c1->vptrbase == NULL) != (c2->vptrbase == NULL))
+    return false;
+
+  if (c1->fields != NULL)
+    {
+      struct debug_field **pf1, **pf2;
+
+      for (pf1 = c1->fields, pf2 = c2->fields;
+          *pf1 != NULL && *pf2 != NULL;
+          pf1++, pf2++)
+       {
+         struct debug_field *f1, *f2;
+
+         f1 = *pf1;
+         f2 = *pf2;
+         if (f1->name[0] != f2->name[0]
+             || f1->visibility != f2->visibility
+             || f1->static_member != f2->static_member)
+           return false;
+         if (f1->static_member)
+           {
+             if (strcmp (f1->u.s.physname, f2->u.s.physname) != 0)
+               return false;
+           }
+         else
+           {
+             if (f1->u.f.bitpos != f2->u.f.bitpos
+                 || f1->u.f.bitsize != f2->u.f.bitsize)
+               return false;
+           }
+         /* We do the checks which require function calls last.  We
+             don't require that the types of fields have the same
+             names, since that sometimes fails in the presence of
+             typedefs and we really don't care.  */
+         if (strcmp (f1->name, f2->name) != 0
+             || ! debug_type_samep (info,
+                                    debug_get_real_type ((PTR) info,
+                                                         f1->type, NULL),
+                                    debug_get_real_type ((PTR) info,
+                                                         f2->type, NULL)))
+           return false;
+       }
+      if (*pf1 != NULL || *pf2 != NULL)
+       return false;
+    }
+
+  if (c1->vptrbase != NULL)
+    {
+      if (! debug_type_samep (info, c1->vptrbase, c2->vptrbase))
+       return false;
+    }
+
+  if (c1->baseclasses != NULL)
+    {
+      struct debug_baseclass **pb1, **pb2;
+
+      for (pb1 = c1->baseclasses, pb2 = c2->baseclasses;
+          *pb1 != NULL && *pb2 != NULL;
+          ++pb1, ++pb2)
+       {
+         struct debug_baseclass *b1, *b2;
+
+         b1 = *pb1;
+         b2 = *pb2;
+         if (b1->bitpos != b2->bitpos
+             || b1->virtual != b2->virtual
+             || b1->visibility != b2->visibility
+             || ! debug_type_samep (info, b1->type, b2->type))
+           return false;
+       }
+      if (*pb1 != NULL || *pb2 != NULL)
+       return false;
+    }
+
+  if (c1->methods != NULL)
+    {
+      struct debug_method **pm1, **pm2;
+
+      for (pm1 = c1->methods, pm2 = c2->methods;
+          *pm1 != NULL && *pm2 != NULL;
+          ++pm1, ++pm2)
+       {
+         struct debug_method *m1, *m2;
+
+         m1 = *pm1;
+         m2 = *pm2;
+         if (m1->name[0] != m2->name[0]
+             || strcmp (m1->name, m2->name) != 0
+             || (m1->variants == NULL) != (m2->variants == NULL))
+           return false;
+         if (m1->variants == NULL)
+           {
+             struct debug_method_variant **pv1, **pv2;
+
+             for (pv1 = m1->variants, pv2 = m2->variants;
+                  *pv1 != NULL && *pv2 != NULL;
+                  ++pv1, ++pv2)
+               {
+                 struct debug_method_variant *v1, *v2;
+
+                 v1 = *pv1;
+                 v2 = *pv2;
+                 if (v1->physname[0] != v2->physname[0]
+                     || v1->visibility != v2->visibility
+                     || v1->constp != v2->constp
+                     || v1->volatilep != v2->volatilep
+                     || v1->voffset != v2->voffset
+                     || (v1->context == NULL) != (v2->context == NULL)
+                     || strcmp (v1->physname, v2->physname) != 0
+                     || ! debug_type_samep (info, v1->type, v2->type))
+                   return false;
+                 if (v1->context != NULL)
+                   {
+                     if (! debug_type_samep (info, v1->context,
+                                             v2->context))
+                       return false;
+                   }
+               }
+             if (*pv1 != NULL || *pv2 != NULL)
+               return false;
+           }
+       }
+      if (*pm1 != NULL || *pm2 != NULL)
+       return false;
+    }
+
+  return true;
+}
diff --git a/binutils/debug.h b/binutils/debug.h
new file mode 100644 (file)
index 0000000..1b890b2
--- /dev/null
@@ -0,0 +1,798 @@
+/* debug.h -- Describe generic debugging information.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+/* This header file describes a generic debugging information format.
+   We may eventually have readers which convert different formats into
+   this generic format, and writers which write it out.  The initial
+   impetus for this was writing a convertor from stabs to HP IEEE-695
+   debugging format.  */
+
+/* Different kinds of types.  */
+
+enum debug_type_kind
+{
+  /* Not used.  */
+  DEBUG_KIND_ILLEGAL,
+  /* Indirect via a pointer.  */
+  DEBUG_KIND_INDIRECT,
+  /* Void.  */
+  DEBUG_KIND_VOID,
+  /* Integer.  */
+  DEBUG_KIND_INT,
+  /* Floating point.  */
+  DEBUG_KIND_FLOAT,
+  /* Complex.  */
+  DEBUG_KIND_COMPLEX,
+  /* Boolean.  */
+  DEBUG_KIND_BOOL,
+  /* Struct.  */
+  DEBUG_KIND_STRUCT,
+  /* Union.  */
+  DEBUG_KIND_UNION,
+  /* Class.  */
+  DEBUG_KIND_CLASS,
+  /* Union class (can this really happen?).  */
+  DEBUG_KIND_UNION_CLASS,
+  /* Enumeration type.  */
+  DEBUG_KIND_ENUM,
+  /* Pointer.  */
+  DEBUG_KIND_POINTER,
+  /* Function.  */
+  DEBUG_KIND_FUNCTION,
+  /* Reference.  */
+  DEBUG_KIND_REFERENCE,
+  /* Range.  */
+  DEBUG_KIND_RANGE,
+  /* Array.  */
+  DEBUG_KIND_ARRAY,
+  /* Set.  */
+  DEBUG_KIND_SET,
+  /* Based pointer.  */
+  DEBUG_KIND_OFFSET,
+  /* Method.  */
+  DEBUG_KIND_METHOD,
+  /* Const qualified type.  */
+  DEBUG_KIND_CONST,
+  /* Volatile qualified type.  */
+  DEBUG_KIND_VOLATILE,
+  /* Named type.  */
+  DEBUG_KIND_NAMED,
+  /* Tagged type.  */
+  DEBUG_KIND_TAGGED
+};
+
+/* Different kinds of variables.  */
+
+enum debug_var_kind
+{
+  /* Not used.  */
+  DEBUG_VAR_ILLEGAL,
+  /* A global variable.  */
+  DEBUG_GLOBAL,
+  /* A static variable.  */
+  DEBUG_STATIC,
+  /* A local static variable.  */
+  DEBUG_LOCAL_STATIC,
+  /* A local variable.  */
+  DEBUG_LOCAL,
+  /* A register variable.  */
+  DEBUG_REGISTER
+};
+
+/* Different kinds of function parameters.  */
+
+enum debug_parm_kind
+{
+  /* Not used.  */
+  DEBUG_PARM_ILLEGAL,
+  /* A stack based parameter.  */
+  DEBUG_PARM_STACK,
+  /* A register parameter.  */
+  DEBUG_PARM_REG,
+  /* A stack based reference parameter.  */
+  DEBUG_PARM_REFERENCE,
+  /* A register reference parameter.  */
+  DEBUG_PARM_REF_REG
+};
+
+/* Different kinds of visibility.  */
+
+enum debug_visibility
+{
+  /* A public field (e.g., a field in a C struct).  */
+  DEBUG_VISIBILITY_PUBLIC,
+  /* A protected field.  */
+  DEBUG_VISIBILITY_PROTECTED,
+  /* A private field.  */
+  DEBUG_VISIBILITY_PRIVATE,
+  /* A field which should be ignored.  */
+  DEBUG_VISIBILITY_IGNORE
+};
+
+/* A type.  */
+
+typedef struct debug_type *debug_type;
+
+#define DEBUG_TYPE_NULL ((debug_type) NULL)
+
+/* A field in a struct or union.  */
+
+typedef struct debug_field *debug_field;
+
+#define DEBUG_FIELD_NULL ((debug_field) NULL)
+
+/* A base class for an object.  */
+
+typedef struct debug_baseclass *debug_baseclass;
+
+#define DEBUG_BASECLASS_NULL ((debug_baseclass) NULL)
+
+/* A method of an object.  */
+
+typedef struct debug_method *debug_method;
+
+#define DEBUG_METHOD_NULL ((debug_method) NULL)
+
+/* The arguments to a method function of an object.  These indicate
+   which method to run.  */
+
+typedef struct debug_method_variant *debug_method_variant;
+
+#define DEBUG_METHOD_VARIANT_NULL ((debug_method_variant) NULL)
+
+/* This structure is passed to debug_write.  It holds function
+   pointers that debug_write will call based on the accumulated
+   debugging information.  */
+
+struct debug_write_fns
+{
+  /* This is called at the start of each new compilation unit with the
+     name of the main file in the new unit.  */
+  boolean (*start_compilation_unit) PARAMS ((PTR, const char *));
+
+  /* This is called at the start of each source file within a
+     compilation unit, before outputting any global information for
+     that file.  The argument is the name of the file.  */
+  boolean (*start_source) PARAMS ((PTR, const char *));
+
+  /* Each writer must keep a stack of types.  */
+
+  /* Push an empty type onto the type stack.  This type can appear if
+     there is a reference to a type which is never defined.  */
+  boolean (*empty_type) PARAMS ((PTR));
+
+  /* Push a void type onto the type stack.  */
+  boolean (*void_type) PARAMS ((PTR));
+
+  /* Push an integer type onto the type stack, given the size and
+     whether it is unsigned.  */
+  boolean (*int_type) PARAMS ((PTR, unsigned int, boolean));
+
+  /* Push a floating type onto the type stack, given the size.  */
+  boolean (*float_type) PARAMS ((PTR, unsigned int));
+
+  /* Push a complex type onto the type stack, given the size.  */
+  boolean (*complex_type) PARAMS ((PTR, unsigned int));
+
+  /* Push a boolean type onto the type stack, given the size.  */
+  boolean (*bool_type) PARAMS ((PTR, unsigned int));
+
+  /* Push an enum type onto the type stack, given the tag, a NULL
+     terminated array of names and the associated values.  If there is
+     no tag, the tag argument will be NULL.  If this is an undefined
+     enum, the names and values arguments will be NULL.  */
+  boolean (*enum_type) PARAMS ((PTR, const char *, const char **,
+                               bfd_signed_vma *));
+
+  /* Pop the top type on the type stack, and push a pointer to that
+     type onto the type stack.  */
+  boolean (*pointer_type) PARAMS ((PTR));
+
+  /* Push a function type onto the type stack.  The second argument
+     indicates the number of argument types that have been pushed onto
+     the stack.  If the number of argument types is passed as -1, then
+     the argument types of the function are unknown, and no types have
+     been pushed onto the stack.  The third argument is true if the
+     function takes a variable number of arguments.  The return type
+     of the function is pushed onto the type stack below the argument
+     types, if any.  */
+  boolean (*function_type) PARAMS ((PTR, int, boolean));
+
+  /* Pop the top type on the type stack, and push a reference to that
+     type onto the type stack.  */
+  boolean (*reference_type) PARAMS ((PTR));
+
+  /* Pop the top type on the type stack, and push a range of that type
+     with the given lower and upper bounds onto the type stack.  */
+  boolean (*range_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+
+  /* Push an array type onto the type stack.  The top type on the type
+     stack is the range, and the next type on the type stack is the
+     element type.  These should be popped before the array type is
+     pushed.  The arguments are the lower bound, the upper bound, and
+     whether the array is a string.  */
+  boolean (*array_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma,
+                                boolean));
+
+  /* Pop the top type on the type stack, and push a set of that type
+     onto the type stack.  The argument indicates whether this set is
+     a bitstring.  */
+  boolean (*set_type) PARAMS ((PTR, boolean));
+
+  /* Push an offset type onto the type stack.  The top type on the
+     type stack is the target type, and the next type on the type
+     stack is the base type.  These should be popped before the offset
+     type is pushed.  */
+  boolean (*offset_type) PARAMS ((PTR));
+
+  /* Push a method type onto the type stack.  If the second argument
+     is true, the top type on the stack is the class to which the
+     method belongs; otherwise, the class must be determined by the
+     class to which the method is attached.  The third argument is the
+     number of argument types; these are pushed onto the type stack in
+     reverse order (the first type popped is the last argument to the
+     method).  A value of -1 for the third argument means that no
+     argument information is available.  The fourth argument is true
+     if the function takes a variable number of arguments.  The next
+     type on the type stack below the domain and the argument types is
+     the return type of the method.  All these types must be popped,
+     and then the method type must be pushed.  */
+  boolean (*method_type) PARAMS ((PTR, boolean, int, boolean));
+
+  /* Pop the top type off the type stack, and push a const qualified
+     version of that type onto the type stack.  */
+  boolean (*const_type) PARAMS ((PTR));
+
+  /* Pop the top type off the type stack, and push a volatile
+     qualified version of that type onto the type stack.  */
+  boolean (*volatile_type) PARAMS ((PTR));
+
+  /* Start building a struct.  This is followed by calls to the
+     struct_field function, and finished by a call to the
+     end_struct_type function.  The second argument is the tag; this
+     will be NULL if there isn't one.  If the second argument is NULL,
+     the third argument is a constant identifying this struct for use
+     with tag_type.  The fourth argument is true for a struct, false
+     for a union.  The fifth argument is the size.  If this is an
+     undefined struct or union, the size will be 0 and struct_field
+     will not be called before end_struct_type is called.  */
+  boolean (*start_struct_type) PARAMS ((PTR, const char *, unsigned int,
+                                       boolean, unsigned int));
+
+  /* Add a field to the struct type currently being built.  The type
+     of the field should be popped off the type stack.  The arguments
+     are the name, the bit position, the bit size (may be zero if the
+     field is not packed), and the visibility.  */
+  boolean (*struct_field) PARAMS ((PTR, const char *, bfd_vma, bfd_vma,
+                                  enum debug_visibility));
+
+  /* Finish building a struct, and push it onto the type stack.  */
+  boolean (*end_struct_type) PARAMS ((PTR));
+
+  /* Start building a class.  This is followed by calls to several
+     functions: struct_field, class_static_member, class_baseclass,
+     class_start_method, class_method_variant,
+     class_static_method_variant, and class_end_method.  The class is
+     finished by a call to end_class_type.  The first five arguments
+     are the same as for start_struct_type.  The sixth argument is
+     true if there is a virtual function table; if there is, the
+     seventh argument is true if the virtual function table can be
+     found in the type itself, and is false if the type of the object
+     holding the virtual function table should be popped from the type
+     stack.  */
+  boolean (*start_class_type) PARAMS ((PTR, const char *, unsigned int,
+                                      boolean, unsigned int, boolean,
+                                      boolean));
+
+  /* Add a static member to the class currently being built.  The
+     arguments are the field name, the physical name, and the
+     visibility.  The type must be popped off the type stack.  */
+  boolean (*class_static_member) PARAMS ((PTR, const char *, const char *,
+                                         enum debug_visibility));
+  
+  /* Add a baseclass to the class currently being built.  The type of
+     the baseclass must be popped off the type stack.  The arguments
+     are the bit position, whether the class is virtual, and the
+     visibility.  */
+  boolean (*class_baseclass) PARAMS ((PTR, bfd_vma, boolean,
+                                     enum debug_visibility));
+
+  /* Start adding a method to the class currently being built.  This
+     is followed by calls to class_method_variant and
+     class_static_method_variant to describe different variants of the
+     method which take different arguments.  The method is finished
+     with a call to class_end_method.  The argument is the method
+     name.  */
+  boolean (*class_start_method) PARAMS ((PTR, const char *));
+
+  /* Describe a variant to the class method currently being built.
+     The type of the variant must be popped off the type stack.  The
+     second argument is the physical name of the function.  The
+     following arguments are the visibility, whether the variant is
+     const, whether the variant is volatile, the offset in the virtual
+     function table, and whether the context is on the type stack
+     (below the variant type).  */
+  boolean (*class_method_variant) PARAMS ((PTR, const char *,
+                                          enum debug_visibility,
+                                          boolean, boolean,
+                                          bfd_vma, boolean));
+
+  /* Describe a static variant to the class method currently being
+     built.  The arguments are the same as for class_method_variant,
+     except that the last two arguments are omitted.  The type of the
+     variant must be popped off the type stack.  */
+  boolean (*class_static_method_variant) PARAMS ((PTR, const char *,
+                                                 enum debug_visibility,
+                                                 boolean, boolean));
+
+  /* Finish describing a class method.  */
+  boolean (*class_end_method) PARAMS ((PTR));
+
+  /* Finish describing a class, and push it onto the type stack.  */
+  boolean (*end_class_type) PARAMS ((PTR));
+
+  /* Push a type on the stack which was given a name by an earlier
+     call to typdef.  */
+  boolean (*typedef_type) PARAMS ((PTR, const char *));
+
+  /* Push a tagged type on the stack which was defined earlier.  If
+     the second argument is not NULL, the type was defined by a call
+     to tag.  If the second argument is NULL, the type was defined by
+     a call to start_struct_type or start_class_type with a tag of
+     NULL and the number of the third argument.  Either way, the
+     fourth argument is the tag kind.  Note that this may be called
+     for a struct (class) being defined, in between the call to
+     start_struct_type (start_class_type) and the call to
+     end_struct_type (end_class_type).  */
+  boolean (*tag_type) PARAMS ((PTR, const char *, unsigned int,
+                              enum debug_type_kind));
+
+  /* Pop the type stack, and typedef it to the given name.  */
+  boolean (*typdef) PARAMS ((PTR, const char *));
+
+  /* Pop the type stack, and declare it as a tagged struct or union or
+     enum or whatever.  The tag passed down here is redundant, since
+     was also passed when enum_type, start_struct_type, or
+     start_class_type was called.  */
+  boolean (*tag) PARAMS ((PTR, const char *));
+
+  /* This is called to record a named integer constant.  */
+  boolean (*int_constant) PARAMS ((PTR, const char *, bfd_vma));
+
+  /* This is called to record a named floating point constant.  */
+  boolean (*float_constant) PARAMS ((PTR, const char *, double));
+
+  /* This is called to record a typed integer constant.  The type is
+     popped off the type stack.  */
+  boolean (*typed_constant) PARAMS ((PTR, const char *, bfd_vma));
+
+  /* This is called to record a variable.  The type is popped off the
+     type stack.  */
+  boolean (*variable) PARAMS ((PTR, const char *, enum debug_var_kind,
+                              bfd_vma));
+
+  /* Start writing out a function.  The return type must be popped off
+     the stack.  The boolean is true if the function is global.  This
+     is followed by calls to function_parameter, followed by block
+     information.  */
+  boolean (*start_function) PARAMS ((PTR, const char *, boolean));
+
+  /* Record a function parameter for the current function.  The type
+     must be popped off the stack.  */
+  boolean (*function_parameter) PARAMS ((PTR, const char *,
+                                        enum debug_parm_kind, bfd_vma));
+
+  /* Start writing out a block.  There is at least one top level block
+     per function.  Blocks may be nested.  The argument is the
+     starting address of the block.  */
+  boolean (*start_block) PARAMS ((PTR, bfd_vma));
+
+  /* Finish writing out a block.  The argument is the ending address
+     of the block.  */
+  boolean (*end_block) PARAMS ((PTR, bfd_vma));
+
+  /* Finish writing out a function.  */
+  boolean (*end_function) PARAMS ((PTR));
+
+  /* Record line number information for the current compilation unit.  */
+  boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+};
+
+/* Exported functions.  */
+
+/* The first argument to most of these functions is a handle.  This
+   handle is returned by the debug_init function.  The purpose of the
+   handle is to permit the debugging routines to not use static
+   variables, and hence to be reentrant.  This would be useful for a
+   program which wanted to handle two executables simultaneously.  */
+
+/* Return a debugging handle.  */
+
+extern PTR debug_init PARAMS ((void));
+
+/* Set the source filename.  This implicitly starts a new compilation
+   unit.  */
+
+extern boolean debug_set_filename PARAMS ((PTR, const char *));
+
+/* Change source files to the given file name.  This is used for
+   include files in a single compilation unit.  */
+
+extern boolean debug_start_source PARAMS ((PTR, const char *));
+
+/* Record a function definition.  This implicitly starts a function
+   block.  The debug_type argument is the type of the return value.
+   The boolean indicates whether the function is globally visible.
+   The bfd_vma is the address of the start of the function.  Currently
+   the parameter types are specified by calls to
+   debug_record_parameter.  */
+
+extern boolean debug_record_function
+  PARAMS ((PTR, const char *, debug_type, boolean, bfd_vma));
+
+/* Record a parameter for the current function.  */
+
+extern boolean debug_record_parameter
+  PARAMS ((PTR, const char *, debug_type, enum debug_parm_kind, bfd_vma));
+
+/* End a function definition.  The argument is the address where the
+   function ends.  */
+
+extern boolean debug_end_function PARAMS ((PTR, bfd_vma));
+
+/* Start a block in a function.  All local information will be
+   recorded in this block, until the matching call to debug_end_block.
+   debug_start_block and debug_end_block may be nested.  The argument
+   is the address at which this block starts.  */
+
+extern boolean debug_start_block PARAMS ((PTR, bfd_vma));
+
+/* Finish a block in a function.  This matches the call to
+   debug_start_block.  The argument is the address at which this block
+   ends.  */
+
+extern boolean debug_end_block PARAMS ((PTR, bfd_vma));
+
+/* Associate a line number in the current source file with a given
+   address.  */
+
+extern boolean debug_record_line PARAMS ((PTR, unsigned long, bfd_vma));
+
+/* Start a named common block.  This is a block of variables that may
+   move in memory.  */
+
+extern boolean debug_start_common_block PARAMS ((PTR, const char *));
+
+/* End a named common block.  */
+
+extern boolean debug_end_common_block PARAMS ((PTR, const char *));
+
+/* Record a named integer constant.  */
+
+extern boolean debug_record_int_const PARAMS ((PTR, const char *, bfd_vma));
+
+/* Record a named floating point constant.  */
+
+extern boolean debug_record_float_const PARAMS ((PTR, const char *, double));
+
+/* Record a typed constant with an integral value.  */
+
+extern boolean debug_record_typed_const
+  PARAMS ((PTR, const char *, debug_type, bfd_vma));
+
+/* Record a label.  */
+
+extern boolean debug_record_label
+  PARAMS ((PTR, const char *, debug_type, bfd_vma));
+
+/* Record a variable.  */
+
+extern boolean debug_record_variable
+  PARAMS ((PTR, const char *, debug_type, enum debug_var_kind, bfd_vma));
+
+/* Make an indirect type.  The first argument is a pointer to the
+   location where the real type will be placed.  The second argument
+   is the type tag, if there is one; this may be NULL; the only
+   purpose of this argument is so that debug_get_type_name can return
+   something useful.  This function may be used when a type is
+   referenced before it is defined.  */
+
+extern debug_type debug_make_indirect_type
+  PARAMS ((PTR, debug_type *, const char *));
+
+/* Make a void type.  */
+
+extern debug_type debug_make_void_type PARAMS ((PTR));
+
+/* Make an integer type of a given size.  The boolean argument is true
+   if the integer is unsigned.  */
+
+extern debug_type debug_make_int_type PARAMS ((PTR, unsigned int, boolean));
+
+/* Make a floating point type of a given size.  FIXME: On some
+   platforms, like an Alpha, you probably need to be able to specify
+   the format.  */
+
+extern debug_type debug_make_float_type PARAMS ((PTR, unsigned int));
+
+/* Make a boolean type of a given size.  */
+
+extern debug_type debug_make_bool_type PARAMS ((PTR, unsigned int));
+
+/* Make a complex type of a given size.  */
+
+extern debug_type debug_make_complex_type PARAMS ((PTR, unsigned int));
+
+/* Make a structure type.  The second argument is true for a struct,
+   false for a union.  The third argument is the size of the struct.
+   The fourth argument is a NULL terminated array of fields.  */
+
+extern debug_type debug_make_struct_type
+  PARAMS ((PTR, boolean, bfd_vma, debug_field *));
+
+/* Make an object type.  The first three arguments after the handle
+   are the same as for debug_make_struct_type.  The next arguments are
+   a NULL terminated array of base classes, a NULL terminated array of
+   methods, the type of the object holding the virtual function table
+   if it is not this object, and a boolean which is true if this
+   object has its own virtual function table.  */
+
+extern debug_type debug_make_object_type
+  PARAMS ((PTR, boolean, bfd_vma, debug_field *, debug_baseclass *,
+          debug_method *, debug_type, boolean));
+
+/* Make an enumeration type.  The arguments are a null terminated
+   array of strings, and an array of corresponding values.  */
+
+extern debug_type debug_make_enum_type
+  PARAMS ((PTR, const char **, bfd_signed_vma *));
+
+/* Make a pointer to a given type.  */
+
+extern debug_type debug_make_pointer_type
+  PARAMS ((PTR, debug_type));
+
+/* Make a function type.  The second argument is the return type.  The
+   third argument is a NULL terminated array of argument types.  The
+   fourth argument is true if the function takes a variable number of
+   arguments.  If the third argument is NULL, then the argument types
+   are unknown.  */
+
+extern debug_type debug_make_function_type
+  PARAMS ((PTR, debug_type, debug_type *, boolean));
+
+/* Make a reference to a given type.  */
+
+extern debug_type debug_make_reference_type PARAMS ((PTR, debug_type));
+
+/* Make a range of a given type from a lower to an upper bound.  */
+
+extern debug_type debug_make_range_type
+  PARAMS ((PTR, debug_type, bfd_signed_vma, bfd_signed_vma));
+
+/* Make an array type.  The second argument is the type of an element
+   of the array.  The third argument is the type of a range of the
+   array.  The fourth and fifth argument are the lower and upper
+   bounds, respectively (if the bounds are not known, lower should be
+   0 and upper should be -1).  The sixth argument is true if this
+   array is actually a string, as in C.  */
+
+extern debug_type debug_make_array_type
+  PARAMS ((PTR, debug_type, debug_type, bfd_signed_vma, bfd_signed_vma,
+          boolean));
+
+/* Make a set of a given type.  For example, a Pascal set type.  The
+   boolean argument is true if this set is actually a bitstring, as in
+   CHILL.  */
+
+extern debug_type debug_make_set_type PARAMS ((PTR, debug_type, boolean));
+
+/* Make a type for a pointer which is relative to an object.  The
+   second argument is the type of the object to which the pointer is
+   relative.  The third argument is the type that the pointer points
+   to.  */
+
+extern debug_type debug_make_offset_type
+  PARAMS ((PTR, debug_type, debug_type));
+
+/* Make a type for a method function.  The second argument is the
+   return type.  The third argument is the domain.  The fourth
+   argument is a NULL terminated array of argument types.  The fifth
+   argument is true if the function takes a variable number of
+   arguments, in which case the array of argument types indicates the
+   types of the first arguments.  The domain and the argument array
+   may be NULL, in which case this is a stub method and that
+   information is not available.  Stabs debugging uses this, and gets
+   the argument types from the mangled name.  */
+
+extern debug_type debug_make_method_type
+  PARAMS ((PTR, debug_type, debug_type, debug_type *, boolean));
+
+/* Make a const qualified version of a given type.  */
+
+extern debug_type debug_make_const_type PARAMS ((PTR, debug_type));
+
+/* Make a volatile qualified version of a given type.  */
+
+extern debug_type debug_make_volatile_type PARAMS ((PTR, debug_type));
+
+/* Make an undefined tagged type.  For example, a struct which has
+   been mentioned, but not defined.  */
+
+extern debug_type debug_make_undefined_tagged_type
+  PARAMS ((PTR, const char *, enum debug_type_kind));
+
+/* Make a base class for an object.  The second argument is the base
+   class type.  The third argument is the bit position of this base
+   class in the object.  The fourth argument is whether this is a
+   virtual class.  The fifth argument is the visibility of the base
+   class.  */
+
+extern debug_baseclass debug_make_baseclass
+  PARAMS ((PTR, debug_type, bfd_vma, boolean, enum debug_visibility));
+
+/* Make a field for a struct.  The second argument is the name.  The
+   third argument is the type of the field.  The fourth argument is
+   the bit position of the field.  The fifth argument is the size of
+   the field (it may be zero).  The sixth argument is the visibility
+   of the field.  */
+
+extern debug_field debug_make_field
+  PARAMS ((PTR, const char *, debug_type, bfd_vma, bfd_vma,
+          enum debug_visibility));
+
+/* Make a static member of an object.  The second argument is the
+   name.  The third argument is the type of the member.  The fourth
+   argument is the physical name of the member (i.e., the name as a
+   global variable).  The fifth argument is the visibility of the
+   member.  */
+
+extern debug_field debug_make_static_member
+  PARAMS ((PTR, const char *, debug_type, const char *,
+          enum debug_visibility));
+
+/* Make a method.  The second argument is the name, and the third
+   argument is a NULL terminated array of method variants.  Each
+   method variant is a method with this name but with different
+   argument types.  */
+
+extern debug_method debug_make_method
+  PARAMS ((PTR, const char *, debug_method_variant *));
+
+/* Make a method variant.  The second argument is the physical name of
+   the function.  The third argument is the type of the function,
+   probably constructed by debug_make_method_type.  The fourth
+   argument is the visibility.  The fifth argument is whether this is
+   a const function.  The sixth argument is whether this is a volatile
+   function.  The seventh argument is the index in the virtual
+   function table, if any.  The eighth argument is the virtual
+   function context.  */
+
+extern debug_method_variant debug_make_method_variant
+  PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean,
+          boolean, bfd_vma, debug_type));
+
+/* Make a static method argument.  The arguments are the same as for
+   debug_make_method_variant, except that the last two are omitted
+   since a static method can not also be virtual.  */
+
+extern debug_method_variant debug_make_static_method_variant
+  PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean,
+          boolean));
+
+/* Name a type.  This returns a new type with an attached name.  */
+
+extern debug_type debug_name_type PARAMS ((PTR, const char *, debug_type));
+
+/* Give a tag to a type, such as a struct or union.  This returns a
+   new type with an attached tag.  */
+
+extern debug_type debug_tag_type PARAMS ((PTR, const char *, debug_type));
+
+/* Record the size of a given type.  */
+
+extern boolean debug_record_type_size PARAMS ((PTR, debug_type, unsigned int));
+
+/* Find a named type.  */
+
+extern debug_type debug_find_named_type PARAMS ((PTR, const char *));
+
+/* Find a tagged type.  */
+
+extern debug_type debug_find_tagged_type
+  PARAMS ((PTR, const char *, enum debug_type_kind));
+
+/* Get the kind of a type.  */
+
+extern enum debug_type_kind debug_get_type_kind PARAMS ((PTR, debug_type));
+
+/* Get the name of a type.  */
+
+extern const char *debug_get_type_name PARAMS ((PTR, debug_type));
+
+/* Get the size of a type.  */
+
+extern bfd_vma debug_get_type_size PARAMS ((PTR, debug_type));
+
+/* Get the return type of a function or method type.  */
+
+extern debug_type debug_get_return_type PARAMS ((PTR, debug_type));
+
+/* Get the NULL terminated array of parameter types for a function or
+   method type (actually, parameter types are not currently stored for
+   function types).  This may be used to determine whether a method
+   type is a stub method or not.  The last argument points to a
+   boolean which is set to true if the function takes a variable
+   number of arguments.  */
+
+extern const debug_type *debug_get_parameter_types PARAMS ((PTR,
+                                                           debug_type,
+                                                           boolean *));
+
+/* Get the target type of a pointer or reference or const or volatile
+   type.  */
+
+extern debug_type debug_get_target_type PARAMS ((PTR, debug_type));
+
+/* Get the NULL terminated array of fields for a struct, union, or
+   class.  */
+
+extern const debug_field *debug_get_fields PARAMS ((PTR, debug_type));
+
+/* Get the type of a field.  */
+
+extern debug_type debug_get_field_type PARAMS ((PTR, debug_field));
+
+/* Get the name of a field.  */
+
+extern const char *debug_get_field_name PARAMS ((PTR, debug_field));
+
+/* Get the bit position of a field within the containing structure.
+   If the field is a static member, this will return (bfd_vma) -1.  */
+
+extern bfd_vma debug_get_field_bitpos PARAMS ((PTR, debug_field));
+
+/* Get the bit size of a field.  If the field is a static member, this
+   will return (bfd_vma) -1.  */
+
+extern bfd_vma debug_get_field_bitsize PARAMS ((PTR, debug_field));
+
+/* Get the visibility of a field.  */
+
+extern enum debug_visibility debug_get_field_visibility
+  PARAMS ((PTR, debug_field));
+
+/* Get the physical name of a field, if it is a static member.  If the
+   field is not a static member, this will return NULL.  */
+
+extern const char *debug_get_field_physname PARAMS ((PTR, debug_field));
+
+/* Write out the recorded debugging information.  This takes a set of
+   function pointers which are called to do the actual writing.  The
+   first PTR is the debugging handle.  The second PTR is a handle
+   which is passed to the functions.  */
+
+extern boolean debug_write PARAMS ((PTR, const struct debug_write_fns *, PTR));
+
+#endif /* DEBUG_H */
diff --git a/binutils/deflex.l b/binutils/deflex.l
new file mode 100644 (file)
index 0000000..e7fa362
--- /dev/null
@@ -0,0 +1,86 @@
+%{/* deflex.l - Lexer for .def files */
+
+/*   Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+/* Contributed by Steve Chamberlain
+                 sac@cygnus.com
+
+*/
+#define DONTDECLARE_MALLOC
+#include "libiberty.h"
+#include "defparse.h"
+#include "dlltool.h"
+
+int linenumber;
+
+%}
+%%
+"NAME"                 { return NAME;}
+"LIBRARY"      { return LIBRARY;}
+"DESCRIPTION"  { return DESCRIPTION;}
+"STACKSIZE"    { return STACKSIZE;}
+"HEAPSIZE"     { return HEAPSIZE;}
+"CODE"                 { return CODE;}
+"DATA"         { return DATA;}
+"SECTIONS"     { return SECTIONS;}
+"EXPORTS"      { return EXPORTS;}
+"IMPORTS"      { return IMPORTS;}
+"VERSION"      { return VERSIONK;}
+"BASE"         { return BASE;}
+"CONSTANT"     { return CONSTANT; }
+"NONAME"       { return NONAME; }
+"READ"         { return READ;}
+"WRITE"                { return WRITE;}
+"EXECUTE"      { return EXECUTE;}
+"SHARED"       { return SHARED;}
+
+[0-9][x0-9A-Fa-f]* { yylval.number = strtol (yytext,0,0); 
+               return NUMBER; }
+
+[A-Za-z$:\-\_?][A-Za-z0-9/$:\-\_@?]+ {         
+               yylval.id =  xstrdup (yytext);
+               return ID;
+               }
+
+"\""[^\"]*"\"" {
+               yylval.id = xstrdup (yytext+1);
+               yylval.id[yyleng-2] = 0;
+               return ID;
+               }
+
+"\'"[^\']*"\'" {
+               yylval.id = xstrdup (yytext+1);
+               yylval.id[yyleng-2] = 0;
+               return ID;
+               }
+"*".*          { }
+";".*          { }
+" "            { }
+"\t"           { }
+"\n"           { linenumber ++ ;}
+"="            { return '=';}
+"."            { return '.';}
+"@"            { return '@';}
+","            { return ',';}
+%%
+#ifndef yywrap
+/* Needed for lex, though not flex. */
+int yywrap() { return 1; }
+#endif
diff --git a/binutils/defparse.y b/binutils/defparse.y
new file mode 100644 (file)
index 0000000..1cb6360
--- /dev/null
@@ -0,0 +1,157 @@
+%{ /* defparse.y - parser for .def files */
+
+/*   Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "dlltool.h"
+%}
+
+%union {
+  char *id;
+  int number;
+};
+
+%token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATA
+%token SECTIONS, EXPORTS, IMPORTS, VERSIONK, BASE, CONSTANT
+%token READ WRITE EXECUTE SHARED NONAME
+%token <id> ID
+%token <number> NUMBER
+%type  <number> opt_base opt_ordinal opt_NONAME opt_CONSTANT opt_DATA
+%type  <number> attr attr_list opt_number
+%type  <id> opt_name opt_equal_name 
+
+%%
+
+start: start command
+       | command
+       ;
+
+command: 
+               NAME opt_name opt_base { def_name ($2, $3); }
+       |       LIBRARY opt_name opt_base { def_library ($2, $3); }
+       |       EXPORTS explist 
+       |       DESCRIPTION ID { def_description ($2);}
+       |       STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);}
+       |       HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);}
+       |       CODE attr_list { def_code ($2);}
+       |       DATA attr_list  { def_data ($2);}
+       |       SECTIONS seclist
+       |       IMPORTS implist
+       |       VERSIONK NUMBER { def_version ($2,0);}
+       |       VERSIONK NUMBER '.' NUMBER { def_version ($2,$4);}
+       ;
+
+
+explist:
+               /* EMPTY */
+       |       expline
+       |       explist expline
+       ;
+
+expline:
+               ID opt_equal_name opt_ordinal opt_NONAME opt_CONSTANT opt_DATA
+                       { def_exports ($1, $2, $3, $4, $5, $6);}
+       ;
+implist:       
+               implist impline
+       |       impline
+       ;
+
+impline:
+               ID '=' ID '.' ID '.' ID     { def_import ($1,$3,$5,$7, 0); }
+       |       ID '=' ID '.' ID '.' NUMBER { def_import ($1,$3,$5, 0,$7); }
+       |       ID '=' ID '.' ID            { def_import ($1,$3, 0,$5, 0); }
+       |       ID '=' ID '.' NUMBER        { def_import ($1,$3, 0, 0,$5); }
+       |       ID '.' ID '.' ID            { def_import ( 0,$1,$3,$5, 0); }
+       |       ID '.' ID '.' NUMBER        { def_import ( 0,$1,$3, 0,$5); }
+       |       ID '.' ID                   { def_import ( 0,$1, 0,$3, 0); }
+       |       ID '.' NUMBER               { def_import ( 0,$1, 0, 0,$3); }
+;
+
+seclist:
+               seclist secline
+       |       secline
+       ;
+
+secline:
+       ID attr_list { def_section ($1,$2);}
+       ;
+
+attr_list:
+       attr_list opt_comma attr
+       | attr
+       ;
+
+opt_comma:
+       ','
+       | 
+       ;
+opt_number: ',' NUMBER { $$=$2;}
+       |          { $$=-1;}
+       ;
+       
+attr:
+               READ { $$ = 1;}
+       |       WRITE { $$ = 2;}        
+       |       EXECUTE { $$=4;}
+       |       SHARED { $$=8;}
+       ;
+
+opt_CONSTANT:
+               CONSTANT {$$=1;}
+       |                {$$=0;}
+       ;
+
+opt_NONAME:
+               NONAME {$$=1;}
+       |                {$$=0;}
+       ;
+
+opt_DATA:
+               DATA { $$ = 1; }
+       |            { $$ = 0; }
+       ;
+
+opt_name: ID           { $$ =$1; }
+       | ID '.' ID     
+         { 
+           char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1);
+           sprintf (name, "%s.%s", $1, $3);
+           $$ = name;
+         }
+       |               { $$=""; }
+       ;
+
+opt_ordinal: 
+         '@' NUMBER     { $$=$2;}
+       |                { $$=-1;}
+       ;
+
+opt_equal_name:
+          '=' ID       { $$ = $2; }
+        |              { $$ =  0; }                     
+       ;
+
+opt_base: BASE '=' NUMBER      { $$= $3;}
+       |       { $$=-1;}
+       ;
+
+       
+
diff --git a/binutils/dep-in.sed b/binutils/dep-in.sed
new file mode 100644 (file)
index 0000000..f61921a
--- /dev/null
@@ -0,0 +1,17 @@
+:loop
+/\\$/N
+/\\$/b loop
+
+s!@INCDIR@!$(INCDIR)!g
+s!@BFDDIR@!$(BFDDIR)!g
+s!@SRCDIR@/!!g
+s!@OBJDIR@/!!g
+
+s/\\\n */ /g
+
+s/ *$//
+s/  */ /g
+/:$/d
+
+s/\(.\{50\}[^ ]*\) /\1 \\\
+  /g
diff --git a/binutils/dlltool.c b/binutils/dlltool.c
new file mode 100644 (file)
index 0000000..ed5cf5e
--- /dev/null
@@ -0,0 +1,3199 @@
+/* dlltool.c -- tool to generate stuff for PE style DLLs
+   Copyright (C) 1995, 96, 97, 98, 1999 Free Software Foundation, Inc.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+
+/*
+   This program allows you to build the files necessary to create
+   DLLs to run on a system which understands PE format image files.
+   (eg, Windows NT)
+
+   See "Peering Inside the PE: A Tour of the Win32 Portable Executable
+   File Format", MSJ 1994, Volume 9 for more information.
+   Also see "Microsoft Portable Executable and Common Object File Format,
+   Specification 4.1" for more information.
+
+   A DLL contains an export table which contains the information
+   which the runtime loader needs to tie up references from a
+   referencing program.
+
+   The export table is generated by this program by reading
+   in a .DEF file or scanning the .a and .o files which will be in the
+   DLL.  A .o file can contain information in special  ".drectve" sections
+   with export information.
+
+   A DEF file contains any number of the following commands:
+
+
+   NAME <name> [ , <base> ]
+   The result is going to be <name>.EXE
+
+   LIBRARY <name> [ , <base> ]
+   The result is going to be <name>.DLL
+
+   EXPORTS  ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) *
+   Declares name1 as an exported symbol from the
+   DLL, with optional ordinal number <integer>
+
+   IMPORTS  (  (   <internal-name> =   <module-name> . <integer> )
+             | ( [ <internal-name> = ] <module-name> . <external-name> )) *
+   Declares that <external-name> or the exported function whoes ordinal number
+   is <integer> is to be imported from the file <module-name>.  If
+   <internal-name> is specified then this is the name that the imported
+   function will be refered to in the body of the DLL.
+
+   DESCRIPTION <string>
+   Puts <string> into output .exp file in the .rdata section
+
+   [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
+   Generates --stack|--heap <number-reserve>,<number-commit>
+   in the output .drectve section.  The linker will
+   see this and act upon it.
+
+   [CODE|DATA] <attr>+
+   SECTIONS ( <sectionname> <attr>+ )*
+   <attr> = READ | WRITE | EXECUTE | SHARED
+   Generates --attr <sectionname> <attr> in the output
+   .drectve section.  The linker will see this and act
+   upon it.
+
+
+   A -export:<name> in a .drectve section in an input .o or .a
+   file to this program is equivalent to a EXPORTS <name>
+   in a .DEF file.
+
+
+
+   The program generates output files with the prefix supplied
+   on the command line, or in the def file, or taken from the first
+   supplied argument.
+
+   The .exp.s file contains the information necessary to export
+   the routines in the DLL.  The .lib.s file contains the information
+   necessary to use the DLL's routines from a referencing program.
+
+
+
+   Example:
+
+ file1.c:
+   asm (".section .drectve");
+   asm (".ascii \"-export:adef\"");
+
+   void adef (char * s)
+   {
+     printf ("hello from the dll %s\n", s);
+   }
+
+   void bdef (char * s)
+   {
+     printf ("hello from the dll and the other entry point %s\n", s);
+   }
+
+ file2.c:
+   asm (".section .drectve");
+   asm (".ascii \"-export:cdef\"");
+   asm (".ascii \"-export:ddef\"");
+   
+   void cdef (char * s)
+   {
+     printf ("hello from the dll %s\n", s);
+   }
+
+   void ddef (char * s)
+   {
+     printf ("hello from the dll and the other entry point %s\n", s);
+   }
+
+   printf()
+   {
+     return 9;
+   }
+
+ main.c
+
+   void main()
+   {
+     cdef();
+   }
+
+ thedll.def
+
+   LIBRARY thedll
+   HEAPSIZE 0x40000, 0x2000
+   EXPORTS bdef @ 20
+           cdef @ 30 NONAME
+
+   SECTIONS donkey READ WRITE
+   aardvark EXECUTE
+
+ # compile up the parts of the dll
+
+   gcc -c file1.c
+   gcc -c file2.c
+
+ # put them in a library (you don't have to, you
+ # could name all the .os on the dlltool line)
+
+   ar  qcv thedll.in file1.o file2.o
+   ranlib thedll.in
+
+ # run this tool over the library and the def file
+   ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
+
+ # build the dll with the library with file1.o, file2.o and the export table
+   ld -o thedll.dll thedll.o thedll.in
+
+ # build the mainline
+   gcc -c themain.c
+
+ # link the executable with the import library
+   ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
+
+ */
+
+/* .idata section description
+
+   The .idata section is the import table.  It is a collection of several
+   subsections used to keep the pieces for each dll together: .idata$[234567].
+   IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
+
+   .idata$2 = Import Directory Table
+   = array of IMAGE_IMPORT_DESCRIPTOR's.
+
+       DWORD   Import Lookup Table;  - pointer to .idata$4
+       DWORD   TimeDateStamp;        - currently always 0
+       DWORD   ForwarderChain;       - currently always 0
+       DWORD   Name;                 - pointer to dll's name
+       PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
+
+   .idata$3 = null terminating entry for .idata$2.
+
+   .idata$4 = Import Lookup Table
+   = array of array of pointers to hint name table.
+   There is one for each dll being imported from, and each dll's set is
+   terminated by a trailing NULL.
+
+   .idata$5 = Import Address Table
+   = array of array of pointers to hint name table.
+   There is one for each dll being imported from, and each dll's set is
+   terminated by a trailing NULL.
+   Initially, this table is identical to the Import Lookup Table.  However,
+   at load time, the loader overwrites the entries with the address of the
+   function.
+
+   .idata$6 = Hint Name Table
+   = Array of { short, asciz } entries, one for each imported function.
+   The `short' is the function's ordinal number.
+
+   .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
+*/
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# ifdef _AIX
+ #pragma alloca
+#endif
+#endif
+
+#define show_allnames 0
+
+#define PAGE_SIZE 4096
+#define PAGE_MASK (-PAGE_SIZE)
+#include "bfd.h"
+#include "libiberty.h"
+#include "bucomm.h"
+#include "getopt.h"
+#include "demangle.h"
+#include "dlltool.h"
+
+#include <ctype.h>
+#include <time.h>
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef DLLTOOL_ARM
+#include "coff/arm.h"
+#include "coff/internal.h"
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#else /* ! HAVE_SYS_WAIT_H */
+#if ! defined (_WIN32) || defined (__CYGWIN32__)
+#ifndef WIFEXITED
+#define WIFEXITED(w)   (((w)&0377) == 0)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(w)    ((w) & 0177)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (((w) >> 8) & 0377)
+#endif
+#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
+#ifndef WIFEXITED
+#define WIFEXITED(w)   (((w) & 0xff) == 0)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(w)    ((w) & 0x7f)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
+#endif
+#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
+#endif /* ! HAVE_SYS_WAIT_H */
+
+/* ifunc and ihead data structures: ttk@cygnus.com 1997
+
+   When IMPORT declarations are encountered in a .def file the
+   function import information is stored in a structure referenced by
+   the global variable IMPORT_LIST.  The structure is a linked list
+   containing the names of the dll files each function is imported
+   from and a linked list of functions being imported from that dll
+   file.  This roughly parallels the structure of the .idata section
+   in the PE object file.
+
+   The contents of .def file are interpreted from within the
+   process_def_file function.  Every time an IMPORT declaration is
+   encountered, it is broken up into its component parts and passed to
+   def_import.  IMPORT_LIST is initialized to NULL in function main.  */
+
+typedef struct ifunct
+{
+  char          *name;   /* name of function being imported */
+  int            ord;    /* two-byte ordinal value associated with function */
+  struct ifunct *next;
+} ifunctype;
+
+typedef struct iheadt
+{
+  char          *dllname;  /* name of dll file imported from */
+  long           nfuncs;   /* number of functions in list */
+  struct ifunct *funchead; /* first function in list */
+  struct ifunct *functail; /* last  function in list */
+  struct iheadt *next;     /* next dll file in list */
+} iheadtype;
+
+/* Structure containing all import information as defined in .def file
+   (qv "ihead structure").  */
+
+static iheadtype *import_list = NULL;
+
+static char *as_name = "as";
+static char * as_flags = "";
+
+static int no_idata4;
+static int no_idata5;
+static char *exp_name;
+static char *imp_name;
+static char *head_label;
+static char *imp_name_lab;
+static char *dll_name;
+
+static int add_indirect = 0;
+static int add_underscore = 0;
+static int dontdeltemps = 0;
+
+#ifdef DLLTOOL_ARM
+static int interwork = 0;
+#endif 
+
+/* True if we should export all symbols.  Otherwise, we only export
+   symbols listed in .drectve sections or in the def file.  */
+static boolean export_all_symbols;
+
+/* True if we should exclude the symbols in DEFAULT_EXCLUDES when
+   exporting all symbols.  */
+static boolean do_default_excludes;
+
+/* Default symbols to exclude when exporting all the symbols.  */
+static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
+
+static char *def_file;
+
+extern char * program_name;
+
+static int machine;
+static int killat;
+static int add_stdcall_alias;
+static int verbose;
+static FILE *output_def;
+static FILE *base_file;
+
+#ifdef DLLTOOL_BEOS
+static const char *mname = "beos";
+#endif
+
+#ifdef DLLTOOL_ARM
+static const char *mname = "arm";
+#endif
+
+#ifdef DLLTOOL_I386
+static const char *mname = "i386";
+#endif
+
+#ifdef DLLTOOL_PPC
+static const char *mname = "ppc";
+#endif
+
+#define PATHMAX 250            /* What's the right name for this ? */
+
+#define TMP_ASM                "dc.s"
+#define TMP_HEAD_S     "dh.s"
+#define TMP_HEAD_O     "dh.o"
+#define TMP_TAIL_S     "dt.s"
+#define TMP_TAIL_O     "dt.o"
+#define TMP_STUB       "ds"
+
+/* This bit of assemly does jmp * ....
+s set how_jtab_roff to mark where the 32bit abs branch should go */
+static const unsigned char i386_jtab[] =
+{
+  0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
+};
+
+static const unsigned char arm_jtab[] =
+{
+  0x00, 0xc0, 0x9f, 0xe5,
+  0x00, 0xf0, 0x9c, 0xe5,
+  0,    0,    0,    0
+};
+
+static const unsigned char thumb_jtab[] =
+{
+  0xc0, 0xb4,
+  0x02, 0x4e,
+  0x36, 0x68,
+  0x01, 0x96,
+  0x40, 0xbd,
+  0xc0, 0x46,
+  0,    0,    0,    0
+};
+
+/* This is the glue sequence for PowerPC PE. There is a  */
+/* tocrel16-tocdefn reloc against the first instruction. */
+/* We also need a IMGLUE reloc against the glue function */
+/* to restore the toc saved by the third instruction in  */
+/* the glue. */
+static const unsigned char ppc_jtab[] =
+{
+  0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2)               */
+                          /*   Reloc TOCREL16 __imp_xxx  */
+  0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11)              */
+  0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1)                */
+  0xA6, 0x03, 0x89, 0x7D, /* mtctr r12                   */
+  0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11)               */
+  0x20, 0x04, 0x80, 0x4E  /* bctr                        */
+};
+
+#ifdef DLLTOOL_PPC
+/* the glue instruction, picks up the toc from the stw in */
+/* the above code: "lwz r2,4(r1)"                         */
+static bfd_vma ppc_glue_insn = 0x80410004;
+#endif
+
+/* The outfile array must be big enough to contain a fully
+   qualified path name, plus an arbitary series of command
+   line switches.  We hope that PATH_MAX times two will be
+   enough.  */
+static char outfile [PATHMAX * 2];
+
+struct mac
+  {
+    const char *type;
+    const char *how_byte;
+    const char *how_short;
+    const char *how_long;
+    const char *how_asciz;
+    const char *how_comment;
+    const char *how_jump;
+    const char *how_global;
+    const char *how_space;
+    const char *how_align_short;
+    const char *how_align_long;
+    const char *how_bfd_target;
+    enum bfd_architecture how_bfd_arch;
+    const unsigned char *how_jtab;
+    int how_jtab_size; /* size of the jtab entry */
+    int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
+  };
+
+static const struct mac
+mtable[] =
+{
+  {
+#define MARM 0
+    "arm", ".byte", ".short", ".long", ".asciz", "@",
+    "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
+    ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
+    arm_jtab, sizeof (arm_jtab), 8
+  }
+  ,
+  {
+#define M386 1
+    "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
+   i386_jtab, sizeof (i386_jtab), 2
+  }
+  ,
+  {
+#define MPPC 2
+    "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
+   ppc_jtab, sizeof (ppc_jtab), 0
+  }
+  ,
+  {
+#define MTHUMB 3
+    "thumb", ".byte", ".short", ".long", ".asciz", "@",
+    "push\t{r6, r7}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tstr\tr6, [sp, #4]\n\tpop\t{r6, pc}\n\tnop",
+    ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
+    thumb_jtab, sizeof (thumb_jtab), 12
+  }
+  ,
+{    0}
+};
+
+typedef struct dlist
+{
+  char *text;
+  struct dlist *next;
+}
+dlist_type;
+
+typedef struct export
+  {
+    const char *name;
+    const char *internal_name;
+    int ordinal;
+    int constant;
+    int noname;
+    int data;
+    int hint;
+    struct export *next;
+  }
+export_type;
+
+/* A list of symbols which we should not export.  */
+struct string_list
+{
+  struct string_list *next;
+  char *string;
+};
+
+static struct string_list *excludes;
+
+static const char *rvaafter PARAMS ((int));
+static const char *rvabefore PARAMS ((int));
+static const char *asm_prefix PARAMS ((int));
+static void append_import PARAMS ((const char *, const char *, int));
+static void run PARAMS ((const char *, char *));
+static void scan_drectve_symbols PARAMS ((bfd *));
+static void scan_filtered_symbols PARAMS ((bfd *, PTR, long, unsigned int));
+static void add_excludes PARAMS ((const char *));
+static boolean match_exclude PARAMS ((const char *));
+static void set_default_excludes PARAMS ((void));
+static long filter_symbols PARAMS ((bfd *, PTR, long, unsigned int));
+static void scan_all_symbols PARAMS ((bfd *));
+static void scan_open_obj_file PARAMS ((bfd *));
+static void scan_obj_file PARAMS ((const char *));
+static void dump_def_info PARAMS ((FILE *));
+static int sfunc PARAMS ((const void *, const void *));
+static void flush_page PARAMS ((FILE *, long *, int, int));
+static void gen_def_file PARAMS ((void));
+static void generate_idata_ofile PARAMS ((FILE *));
+static void gen_exp_file PARAMS ((void));
+static const char *xlate PARAMS ((const char *));
+#if 0
+static void dump_iat PARAMS ((FILE *, export_type *));
+#endif
+static char *make_label PARAMS ((const char *, const char *));
+static bfd *make_one_lib_file PARAMS ((export_type *, int));
+static bfd *make_head PARAMS ((void));
+static bfd *make_tail PARAMS ((void));
+static void gen_lib_file PARAMS ((void));
+static int pfunc PARAMS ((const void *, const void *));
+static int nfunc PARAMS ((const void *, const void *));
+static void remove_null_names PARAMS ((export_type **));
+static void dtab PARAMS ((export_type **));
+static void process_duplicates PARAMS ((export_type **));
+static void fill_ordinals PARAMS ((export_type **));
+static int alphafunc PARAMS ((const void *, const void *));
+static void mangle_defs PARAMS ((void));
+static void usage PARAMS ((FILE *, int));
+static void display PARAMS ((const char *, va_list));
+static void inform PARAMS ((const char *, ...));
+static void warn PARAMS ((const char *, ...));
+
+static void
+display (message, args)
+     const char * message;
+     va_list      args;
+{
+  if (program_name != NULL)
+    fprintf (stderr, "%s: ", program_name);
+
+  vfprintf (stderr, message, args);
+
+  if (message [strlen (message) - 1] != '\n')
+    fputc ('\n', stderr);
+}  
+
+
+static void
+#ifdef __STDC__
+inform (const char * message, ...)
+#else
+inform (message, va_alist)
+     const char * message;
+     va_dcl
+#endif
+{
+  va_list args;
+  
+  if (!verbose)
+    return;
+
+#ifdef __STDC__
+  va_start (args, message);
+#else
+  va_start (args);
+#endif
+
+  display (message, args);
+  
+  va_end (args);
+}
+
+static void
+#ifdef __STDC__
+warn (const char * message, ...)
+#else
+warn (message, va_alist)
+     const char * message;
+     va_dcl
+#endif
+{
+  va_list args;
+  
+#ifdef __STDC__
+  va_start (args, message);
+#else
+  va_start (args);
+#endif
+  
+  display (message, args);
+
+  va_end (args);
+}
+
+static const char *
+rvaafter (machine)
+     int machine;
+{
+  switch (machine)
+    {
+    case MARM:
+    case M386:
+    case MPPC:
+    case MTHUMB:
+      break;
+    default:
+      /* xgettext:c-format */
+      fatal (_("Internal error: Unknown machine type: %d\n"), machine);
+      break;
+    }
+  return "";
+}
+
+static const char *
+rvabefore (machine)
+     int machine;
+{
+  switch (machine)
+    {
+    case MARM:
+    case M386:
+    case MPPC:
+    case MTHUMB:
+      return ".rva\t";
+    default:
+      /* xgettext:c-format */
+      fatal (_("Internal error: Unknown machine type: %d\n"), machine);
+      break;
+    }
+  return "";
+}
+
+static const char *
+asm_prefix (machine)
+     int machine;
+{
+  switch (machine)
+    {
+    case MARM:
+    case MPPC:
+    case MTHUMB:
+      break;
+    case M386:
+      return "_";
+    default:
+      /* xgettext:c-format */
+      fatal (_("Internal error: Unknown machine type: %d\n"), machine);
+      break;
+    }
+  return "";
+}
+
+#define ASM_BYTE       mtable[machine].how_byte
+#define ASM_SHORT      mtable[machine].how_short
+#define ASM_LONG       mtable[machine].how_long
+#define ASM_TEXT       mtable[machine].how_asciz
+#define ASM_C          mtable[machine].how_comment
+#define ASM_JUMP       mtable[machine].how_jump
+#define ASM_GLOBAL     mtable[machine].how_global
+#define ASM_SPACE      mtable[machine].how_space
+#define ASM_ALIGN_SHORT mtable[machine].how_align_short
+#define ASM_RVA_BEFORE         rvabefore(machine)
+#define ASM_RVA_AFTER          rvaafter(machine)
+#define ASM_PREFIX     asm_prefix(machine)
+#define ASM_ALIGN_LONG mtable[machine].how_align_long
+#define HOW_BFD_TARGET  0  /* always default*/
+#define HOW_BFD_ARCH   mtable[machine].how_bfd_arch
+#define HOW_JTAB       mtable[machine].how_jtab
+#define HOW_JTAB_SIZE      mtable[machine].how_jtab_size
+#define HOW_JTAB_ROFF      mtable[machine].how_jtab_roff
+static char **oav;
+
+void
+process_def_file (name)
+     const char *name;
+{
+  FILE *f = fopen (name, FOPEN_RT);
+  
+  if (!f)
+    /* xgettext:c-format */
+    fatal (_("Can't open def file: %s"), name);
+
+  yyin = f;
+
+  /* xgettext:c-format */
+  inform (_("Processing def file: %s"), name);
+  
+  yyparse ();
+
+  inform (_("Processed def file"));
+}
+
+/**********************************************************************/
+
+/* Communications with the parser */
+
+static const char *d_name;     /* Arg to NAME or LIBRARY */
+static int d_nfuncs;           /* Number of functions exported */
+static int d_named_nfuncs;     /* Number of named functions exported */
+static int d_low_ord;          /* Lowest ordinal index */
+static int d_high_ord;         /* Highest ordinal index */
+static export_type *d_exports; /*list of exported functions */
+static export_type **d_exports_lexically;      /* vector of exported functions in alpha order */
+static dlist_type *d_list;     /* Descriptions */
+static dlist_type *a_list;     /* Stuff to go in directives */
+
+static int d_is_dll;
+static int d_is_exe;
+
+int
+yyerror (err)
+     const char *err;
+{
+  /* xgettext:c-format */
+  warn (_("Syntax error in def file %s:%d\n"), def_file, linenumber);
+  
+  return 0;
+}
+
+void
+def_exports (name, internal_name, ordinal, noname, constant, data)
+     const char *name;
+     const char *internal_name;
+     int ordinal;
+     int noname;
+     int constant;
+     int data;
+{
+  struct export *p = (struct export *) xmalloc (sizeof (*p));
+
+  p->name = name;
+  p->internal_name = internal_name ? internal_name : name;
+  p->ordinal = ordinal;
+  p->constant = constant;
+  p->noname = noname;
+  p->data = data;
+  p->next = d_exports;
+  d_exports = p;
+  d_nfuncs++;
+}
+
+void
+def_name (name, base)
+     const char *name;
+     int base;
+{
+  /* xgettext:c-format */
+  inform (_("NAME: %s base: %x"), name, base);
+  
+  if (d_is_dll)
+    warn (_("Can't have LIBRARY and NAME\n"));
+  
+  d_name = name;
+  /* if --dllname not provided, use the one in the DEF file.
+     FIXME: Is this appropriate for executables? */
+  if (! dll_name)
+    dll_name = xstrdup (name);
+  d_is_exe = 1;
+}
+
+void
+def_library (name, base)
+     const char *name;
+     int base;
+{
+  /* xgettext:c-format */
+  inform (_("LIBRARY: %s base: %x"), name, base);
+  
+  if (d_is_exe)
+    warn (_("%s: Can't have LIBRARY and NAME\n"), program_name);
+  
+  d_name = name;
+  /* if --dllname not provided, use the one in the DEF file. */
+  if (! dll_name)
+    dll_name = xstrdup (name);
+  d_is_dll = 1;
+}
+
+void
+def_description (desc)
+     const char *desc;
+{
+  dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
+  d->text = xstrdup (desc);
+  d->next = d_list;
+  d_list = d;
+}
+
+void
+new_directive (dir)
+     char *dir;
+{
+  dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
+  d->text = xstrdup (dir);
+  d->next = a_list;
+  a_list = d;
+}
+
+void
+def_heapsize (reserve, commit)
+     int reserve;
+     int commit;
+{
+  char b[200];
+  if (commit > 0)
+    sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
+  else
+    sprintf (b, "-heap 0x%x ", reserve);
+  new_directive (xstrdup (b));
+}
+
+void
+def_stacksize (reserve, commit)
+     int reserve;
+     int commit;
+{
+  char b[200];
+  if (commit > 0)
+    sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
+  else
+    sprintf (b, "-stack 0x%x ", reserve);
+  new_directive (xstrdup (b));
+}
+
+/* append_import simply adds the given import definition to the global
+   import_list.  It is used by def_import.  */
+
+static void
+append_import (symbol_name, dll_name, func_ordinal)
+     const char *symbol_name;
+     const char *dll_name;
+     int func_ordinal;
+{
+  iheadtype **pq;
+  iheadtype *q;
+
+  for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
+    {
+      if (strcmp ((*pq)->dllname, dll_name) == 0)
+       {
+         q = *pq;
+         q->functail->next = xmalloc (sizeof (ifunctype));
+         q->functail = q->functail->next;
+         q->functail->ord  = func_ordinal;
+         q->functail->name = xstrdup (symbol_name);
+         q->functail->next = NULL;
+         q->nfuncs++;
+         return;
+       }
+    }
+
+  q = xmalloc (sizeof (iheadtype));
+  q->dllname = xstrdup (dll_name);
+  q->nfuncs = 1;
+  q->funchead = xmalloc (sizeof (ifunctype));
+  q->functail = q->funchead;
+  q->next = NULL;
+  q->functail->name = xstrdup (symbol_name);
+  q->functail->ord  = func_ordinal;
+  q->functail->next = NULL;
+
+  *pq = q;
+}
+
+/* def_import is called from within defparse.y when an IMPORT
+   declaration is encountered.  Depending on the form of the
+   declaration, the module name may or may not need ".dll" to be
+   appended to it, the name of the function may be stored in internal
+   or entry, and there may or may not be an ordinal value associated
+   with it.  */
+
+/* A note regarding the parse modes:
+   In defparse.y we have to accept import declarations which follow
+   any one of the following forms:
+     <func_name_in_app> = <dll_name>.<func_name_in_dll>
+     <func_name_in_app> = <dll_name>.<number>
+     <dll_name>.<func_name_in_dll>
+     <dll_name>.<number>
+   Furthermore, the dll's name may or may not end with ".dll", which
+   complicates the parsing a little.  Normally the dll's name is
+   passed to def_import() in the "module" parameter, but when it ends
+   with ".dll" it gets passed in "module" sans ".dll" and that needs
+   to be reappended.
+
+  def_import gets five parameters:
+  APP_NAME - the name of the function in the application, if
+             present, or NULL if not present.
+  MODULE   - the name of the dll, possibly sans extension (ie, '.dll').
+  DLLEXT   - the extension of the dll, if present, NULL if not present.
+  ENTRY    - the name of the function in the dll, if present, or NULL.
+  ORD_VAL  - the numerical tag of the function in the dll, if present,
+             or NULL.  Exactly one of <entry> or <ord_val> must be
+             present (i.e., not NULL).  */
+
+void
+def_import (app_name, module, dllext, entry, ord_val)
+     const char *app_name;
+     const char *module;
+     const char *dllext;
+     const char *entry;
+     int ord_val;
+{
+  const char *application_name;
+  char *buf;
+
+  if (entry != NULL)
+    application_name = entry;
+  else
+    {
+      if (app_name != NULL)
+       application_name = app_name;
+      else
+       application_name = "";
+    }
+  
+  if (dllext != NULL)
+    {
+      buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
+      sprintf (buf, "%s.%s", module, dllext);
+      module = buf;
+    }
+
+  append_import (application_name, module, ord_val);
+}
+
+void
+def_version (major, minor)
+     int major;
+     int minor;
+{
+  printf ("VERSION %d.%d\n", major, minor);
+}
+
+void
+def_section (name, attr)
+     const char *name;
+     int attr;
+{
+  char buf[200];
+  char atts[5];
+  char *d = atts;
+  if (attr & 1)
+    *d++ = 'R';
+
+  if (attr & 2)
+    *d++ = 'W';
+  if (attr & 4)
+    *d++ = 'X';
+  if (attr & 8)
+    *d++ = 'S';
+  *d++ = 0;
+  sprintf (buf, "-attr %s %s", name, atts);
+  new_directive (xstrdup (buf));
+}
+
+void
+def_code (attr)
+     int attr;
+{
+
+  def_section ("CODE", attr);
+}
+
+void
+def_data (attr)
+     int attr;
+{
+  def_section ("DATA", attr);
+}
+
+/**********************************************************************/
+
+static void
+run (what, args)
+     const char *what;
+     char *args;
+{
+  char *s;
+  int pid, wait_status;
+  int i;
+  const char **argv;
+  char *errmsg_fmt, *errmsg_arg;
+  char *temp_base = choose_temp_base ();
+
+  inform ("run: %s %s\n", what, args);
+
+  /* Count the args */
+  i = 0;
+  for (s = args; *s; s++)
+    if (*s == ' ')
+      i++;
+  i++;
+  argv = alloca (sizeof (char *) * (i + 3));
+  i = 0;
+  argv[i++] = what;
+  s = args;
+  while (1)
+    {
+      while (*s == ' ')
+       ++s;
+      argv[i++] = s;
+      while (*s != ' ' && *s != 0)
+       s++;
+      if (*s == 0)
+       break;
+      *s++ = 0;
+    }
+  argv[i++] = NULL;
+
+  pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
+                 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
+
+  if (pid == -1)
+    {
+      inform (strerror (errno));
+      
+      fatal (errmsg_fmt, errmsg_arg);
+    }
+
+  pid = pwait (pid, & wait_status, 0);
+  
+  if (pid == -1)
+    {
+      /* xgettext:c-format */
+      fatal (_("wait: %s"), strerror (errno));
+    }
+  else if (WIFSIGNALED (wait_status))
+    {
+      /* xgettext:c-format */
+      fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
+    }
+  else if (WIFEXITED (wait_status))
+    {
+      if (WEXITSTATUS (wait_status) != 0)
+       /* xgettext:c-format */
+       warn (_("%s exited with status %d\n"),
+             what, WEXITSTATUS (wait_status));
+    }
+  else
+    abort ();
+}
+
+/* Look for a list of symbols to export in the .drectve section of
+   ABFD.  Pass each one to def_exports.  */
+
+static void
+scan_drectve_symbols (abfd)
+     bfd *abfd;
+{
+  asection * s;
+  int        size;
+  char *     buf;
+  char *     p;
+  char *     e;
+  
+  /* Look for .drectve's */
+  s = bfd_get_section_by_name (abfd, ".drectve");
+  
+  if (s == NULL)
+    return;
+      
+  size = bfd_get_section_size_before_reloc (s);
+  buf  = xmalloc (size);
+
+  bfd_get_section_contents (abfd, s, buf, 0, size);
+      
+  /* xgettext:c-format */
+  inform (_("Sucking in info from .drective section in %s\n"),
+         bfd_get_filename (abfd));
+
+  /* Search for -export: strings */
+  p = buf;
+  e = buf + size;
+  while (p < e)
+    {
+      if (p[0] == '-'
+         && strncmp (p, "-export:", 8) == 0)
+       {
+         char * name;
+         char * c;
+         
+         p += 8;
+         name = p;
+         while (p < e && *p != ' ' && *p != '-')
+           p++;
+         c = xmalloc (p - name + 1);
+         memcpy (c, name, p - name);
+         c[p - name] = 0;
+
+         /* FIXME: The 5th arg is for the `constant' field.
+            What should it be?  Not that it matters since it's not
+            currently useful.  */
+         def_exports (c, 0, -1, 0, 0, 0);
+
+         if (add_stdcall_alias && strchr (c, '@'))
+           {
+             char *exported_name = xstrdup (c);
+             char *atsym = strchr (exported_name, '@');
+             *atsym = '\0';
+             def_exports (exported_name, xstrdup (c), -1, 0, 0, 0);
+           }
+       }
+      else
+       p++;
+    }
+  free (buf);
+}
+
+/* Look through the symbols in MINISYMS, and add each one to list of
+   symbols to export.  */
+
+static void
+scan_filtered_symbols (abfd, minisyms, symcount, size)
+     bfd *abfd;
+     PTR minisyms;
+     long symcount;
+     unsigned int size;
+{
+  asymbol *store;
+  bfd_byte *from, *fromend;
+
+  store = bfd_make_empty_symbol (abfd);
+  if (store == NULL)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  from = (bfd_byte *) minisyms;
+  fromend = from + symcount * size;
+  for (; from < fromend; from += size)
+    {
+      asymbol *sym;
+      const char *symbol_name;
+
+      sym = bfd_minisymbol_to_symbol (abfd, false, from, store);
+      if (sym == NULL)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      symbol_name = bfd_asymbol_name (sym);
+      if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
+       ++symbol_name;
+
+      def_exports (xstrdup (symbol_name) , 0, -1, 0, 0, 0);
+
+      if (add_stdcall_alias && strchr (symbol_name, '@'))
+        {
+         char *exported_name = xstrdup (symbol_name);
+         char *atsym = strchr (exported_name, '@');
+         *atsym = '\0';
+         def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0);
+       }
+    }
+}
+
+/* Add a list of symbols to exclude.  */
+
+static void
+add_excludes (new_excludes)
+     const char *new_excludes;
+{
+  char *local_copy;
+  char *exclude_string;
+
+  local_copy = xstrdup (new_excludes);
+
+  exclude_string = strtok (local_copy, ",:");
+  for (; exclude_string; exclude_string = strtok (NULL, ",:"))
+    {
+      struct string_list *new_exclude;
+      
+      new_exclude = ((struct string_list *)
+                    xmalloc (sizeof (struct string_list)));
+      new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
+      /* FIXME: Is it always right to add a leading underscore?  */
+      sprintf (new_exclude->string, "_%s", exclude_string);
+      new_exclude->next = excludes;
+      excludes = new_exclude;
+
+      /* xgettext:c-format */
+      inform (_("Excluding symbol: %s\n"), exclude_string);
+    }
+
+  free (local_copy);
+}
+
+/* See if STRING is on the list of symbols to exclude.  */
+
+static boolean
+match_exclude (string)
+     const char *string;
+{
+  struct string_list *excl_item;
+
+  for (excl_item = excludes; excl_item; excl_item = excl_item->next)
+    if (strcmp (string, excl_item->string) == 0)
+      return true;
+  return false;
+}
+
+/* Add the default list of symbols to exclude.  */
+
+static void
+set_default_excludes (void)
+{
+  add_excludes (default_excludes);
+}
+
+/* Choose which symbols to export.  */
+
+static long
+filter_symbols (abfd, minisyms, symcount, size)
+     bfd *abfd;
+     PTR minisyms;
+     long symcount;
+     unsigned int size;
+{
+  bfd_byte *from, *fromend, *to;
+  asymbol *store;
+
+  store = bfd_make_empty_symbol (abfd);
+  if (store == NULL)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  from = (bfd_byte *) minisyms;
+  fromend = from + symcount * size;
+  to = (bfd_byte *) minisyms;
+
+  for (; from < fromend; from += size)
+    {
+      int keep = 0;
+      asymbol *sym;
+
+      sym = bfd_minisymbol_to_symbol (abfd, false, (const PTR) from, store);
+      if (sym == NULL)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      /* Check for external and defined only symbols.  */
+      keep = (((sym->flags & BSF_GLOBAL) != 0
+              || (sym->flags & BSF_WEAK) != 0
+              || bfd_is_com_section (sym->section))
+             && ! bfd_is_und_section (sym->section));
+      
+      keep = keep && ! match_exclude (sym->name);
+
+      if (keep)
+       {
+         memcpy (to, from, size);
+         to += size;
+       }
+    }
+
+  return (to - (bfd_byte *) minisyms) / size;
+}
+
+/* Export all symbols in ABFD, except for ones we were told not to
+   export.  */
+
+static void
+scan_all_symbols (abfd)
+     bfd *abfd;
+{
+  long symcount;
+  PTR minisyms;
+  unsigned int size;
+
+  /* Ignore bfds with an import descriptor table.  We assume that any
+     such BFD contains symbols which are exported from another DLL,
+     and we don't want to reexport them from here.  */
+  if (bfd_get_section_by_name (abfd, ".idata$4"))
+    return;
+
+  if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
+    {
+      /* xgettext:c-format */
+      warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
+      return;
+    }
+
+  symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size);
+  if (symcount < 0)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  if (symcount == 0)
+    {
+      /* xgettext:c-format */
+      warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
+      return;
+    }
+
+  /* Discard the symbols we don't want to export.  It's OK to do this
+     in place; we'll free the storage anyway.  */
+
+  symcount = filter_symbols (abfd, minisyms, symcount, size);
+  scan_filtered_symbols (abfd, minisyms, symcount, size);
+
+  free (minisyms);
+}
+
+/* Look at the object file to decide which symbols to export.  */
+
+static void
+scan_open_obj_file (abfd)
+     bfd *abfd;
+{
+  if (export_all_symbols)
+    scan_all_symbols (abfd);
+  else
+    scan_drectve_symbols (abfd);
+  /* FIXME: we ought to read in and block out the base relocations */
+
+  /* xgettext:c-format */
+  inform (_("%s: Done reading %s\n"), bfd_get_filename (abfd));
+}
+
+static void
+scan_obj_file (filename)
+     const char *filename;
+{
+  bfd * f = bfd_openr (filename, 0);
+
+  if (!f)
+    /* xgettext:c-format */
+    fatal (_("Unable to open object file: %s"), filename);
+
+  /* xgettext:c-format */
+  inform (_("Scanning object file %s"), filename);
+  
+  if (bfd_check_format (f, bfd_archive))
+    {
+      bfd *arfile = bfd_openr_next_archived_file (f, 0);
+      while (arfile)
+       {
+         if (bfd_check_format (arfile, bfd_object))
+           scan_open_obj_file (arfile);
+         bfd_close (arfile);
+         arfile = bfd_openr_next_archived_file (f, arfile);
+       }
+    }
+  else if (bfd_check_format (f, bfd_object))
+    {
+      scan_open_obj_file (f);
+    }
+
+  bfd_close (f);
+}
+
+/**********************************************************************/
+
+static void
+dump_def_info (f)
+     FILE *f;
+{
+  int i;
+  export_type *exp;
+  fprintf (f, "%s ", ASM_C);
+  for (i = 0; oav[i]; i++)
+    fprintf (f, "%s ", oav[i]);
+  fprintf (f, "\n");
+  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
+    {
+      fprintf (f, "%s  %d = %s %s @ %d %s%s%s\n",
+              ASM_C,
+              i,
+              exp->name,
+              exp->internal_name,
+              exp->ordinal,
+              exp->noname ? "NONAME " : "",
+              exp->constant ? "CONSTANT" : "",
+              exp->data ? "DATA" : "");
+    }
+}
+
+/* Generate the .exp file */
+
+static int
+sfunc (a, b)
+     const void *a;
+     const void *b;
+{
+  return *(const long *) a - *(const long *) b;
+}
+
+static void
+flush_page (f, need, page_addr, on_page)
+     FILE *f;
+     long *need;
+     int page_addr;
+     int on_page;
+{
+  int i;
+
+  /* Flush this page */
+  fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
+          ASM_LONG,
+          page_addr,
+          ASM_C);
+  fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
+          ASM_LONG,
+          (on_page * 2) + (on_page & 1) * 2 + 8,
+          ASM_C);
+  for (i = 0; i < on_page; i++)
+    {
+      fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
+    }
+  /* And padding */
+  if (on_page & 1)
+    fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
+}
+
+static void
+gen_def_file ()
+{
+  int i;
+  export_type *exp;
+
+  inform (_("Adding exports to output file"));
+  
+  fprintf (output_def, ";");
+  for (i = 0; oav[i]; i++)
+    fprintf (output_def, " %s", oav[i]);
+
+  fprintf (output_def, "\nEXPORTS\n");
+
+  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
+    {
+      char *quote = strchr (exp->name, '.') ? "\"" : "";
+      char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
+
+      if (strcmp (exp->name, exp->internal_name) == 0)
+        {
+
+         fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
+                  quote,
+                  exp->name,
+                  quote,
+                  exp->ordinal,
+                  exp->noname ? " NONAME" : "",
+                  exp->data ? " DATA" : "",
+                  res ? res : "");
+       }
+      else 
+        {
+          char *quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
+         /* char *alias =  */
+         fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s ; %s\n",
+                  quote,
+                  exp->name,
+                  quote,
+                  quote1,
+                  exp->internal_name,
+                  quote1,
+                  exp->ordinal,
+                  exp->noname ? " NONAME" : "",
+                  exp->data ? " DATA" : "",
+                  res ? res : "");
+       }
+      if (res)
+        free (res);
+    }
+  
+  inform (_("Added exports to output file"));
+}
+
+/* generate_idata_ofile generates the portable assembly source code
+   for the idata sections.  It appends the source code to the end of
+   the file.  */
+
+static void
+generate_idata_ofile (filvar)
+     FILE *filvar;
+{
+  iheadtype *headptr;
+  ifunctype *funcptr;
+  int        headindex;
+  int        funcindex;
+  int       nheads;
+
+  if (import_list == NULL)
+    return;
+
+  fprintf (filvar, "%s Import data sections\n", ASM_C);
+  fprintf (filvar, "\n\t.section\t.idata$2\n");
+  fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL);
+  fprintf (filvar, "doi_idata:\n");
+
+  nheads = 0;
+  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
+    {
+      fprintf (filvar, "\t%slistone%d%s\t%s %s\n",
+              ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER,
+              ASM_C, headptr->dllname);
+      fprintf (filvar, "\t%s\t0\n", ASM_LONG);
+      fprintf (filvar, "\t%s\t0\n", ASM_LONG);
+      fprintf (filvar, "\t%sdllname%d%s\n",
+              ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
+      fprintf (filvar, "\t%slisttwo%d%s\n\n",
+              ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER);
+      nheads++;
+    }
+
+  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */
+  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */
+  fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section        */
+  fprintf (filvar, "\t%s\t0\n", ASM_LONG);
+  fprintf (filvar, "\t%s\t0\n", ASM_LONG);
+
+  fprintf (filvar, "\n\t.section\t.idata$4\n");
+  headindex = 0;
+  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
+    {
+      fprintf (filvar, "listone%d:\n", headindex);
+      for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
+       fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
+                ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
+      fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+      headindex++;
+    }
+
+  fprintf (filvar, "\n\t.section\t.idata$5\n");
+  headindex = 0;
+  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
+    {
+      fprintf (filvar, "listtwo%d:\n", headindex);
+      for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
+       fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
+                ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
+      fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+      headindex++;
+    }
+
+  fprintf (filvar, "\n\t.section\t.idata$6\n");
+  headindex = 0;
+  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
+    {
+      funcindex = 0;
+      for (funcptr = headptr->funchead; funcptr != NULL;
+          funcptr = funcptr->next)
+       {
+         fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex);
+         fprintf (filvar,"\t%s\t%d\n", ASM_SHORT,
+                  ((funcptr->ord) & 0xFFFF));
+         fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name);
+         fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
+         funcindex++;
+       }
+      headindex++;
+    }
+
+  fprintf (filvar, "\n\t.section\t.idata$7\n");
+  headindex = 0;
+  for (headptr = import_list; headptr != NULL; headptr = headptr->next)
+    {
+      fprintf (filvar,"dllname%d:\n", headindex);
+      fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname);
+      fprintf (filvar,"\t%s\t0\n", ASM_BYTE);
+      headindex++;
+    }
+}
+
+static void
+gen_exp_file ()
+{
+  FILE *f;
+  int i;
+  export_type *exp;
+  dlist_type *dl;
+
+  /* xgettext:c-format */
+  inform (_("Generating export file: %s\n"), exp_name);
+  
+  f = fopen (TMP_ASM, FOPEN_WT);
+  if (!f)
+    /* xgettext:c-format */
+    fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM);
+  
+  /* xgettext:c-format */
+  inform (_("Opened temporary file: %s"), TMP_ASM);
+
+  dump_def_info (f);
+  
+  if (d_exports)
+    {
+      fprintf (f, "\t.section  .edata\n\n");
+      fprintf (f, "\t%s        0       %s Allways 0\n", ASM_LONG, ASM_C);
+      fprintf (f, "\t%s        0x%lx   %s Time and date\n", ASM_LONG, (long) time(0),
+              ASM_C);
+      fprintf (f, "\t%s        0       %s Major and Minor version\n", ASM_LONG, ASM_C);
+      fprintf (f, "\t%sname%s  %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
+      fprintf (f, "\t%s        %d      %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
+
+
+      fprintf (f, "\t%s        %d      %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
+      fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
+             ASM_C,
+             d_named_nfuncs, d_low_ord, d_high_ord);
+      fprintf (f, "\t%s        %d      %s Number of names\n", ASM_LONG,
+              show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
+      fprintf (f, "\t%safuncs%s  %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
+
+      fprintf (f, "\t%sanames%s        %s Address of Name Pointer Table\n",
+              ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
+
+      fprintf (f, "\t%sanords%s        %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
+
+      fprintf (f, "name:       %s      \"%s\"\n", ASM_TEXT, dll_name);
+
+
+      fprintf(f,"%s Export address Table\n", ASM_C);
+      fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
+      fprintf (f, "afuncs:\n");
+      i = d_low_ord;
+
+      for (exp = d_exports; exp; exp = exp->next)
+       {
+         if (exp->ordinal != i)
+           {
+#if 0
+             fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
+                      ASM_SPACE,
+                      (exp->ordinal - i) * 4,
+                      ASM_C,
+                      i, exp->ordinal - 1);
+             i = exp->ordinal;
+#endif
+             while (i < exp->ordinal)
+               {
+                 fprintf(f,"\t%s\t0\n", ASM_LONG);
+                 i++;
+               }
+           }
+         fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
+                  ASM_PREFIX,
+                  exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
+         i++;
+       }
+
+      fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
+      fprintf (f, "anames:\n");
+
+      for (i = 0; (exp = d_exports_lexically[i]); i++)
+       {
+         if (!exp->noname || show_allnames)
+           fprintf (f, "\t%sn%d%s\n",
+                    ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
+       }
+
+      fprintf (f,"%s Export Oridinal Table\n", ASM_C);
+      fprintf (f, "anords:\n");
+      for (i = 0; (exp = d_exports_lexically[i]); i++)
+       {
+         if (!exp->noname || show_allnames)
+           fprintf (f, "\t%s   %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
+       }
+
+      fprintf(f,"%s Export Name Table\n", ASM_C);
+      for (i = 0; (exp = d_exports_lexically[i]); i++)
+       if (!exp->noname || show_allnames)
+         fprintf (f, "n%d:     %s      \"%s\"\n",
+                  exp->ordinal, ASM_TEXT, exp->name);
+
+      if (a_list)
+       {
+         fprintf (f, "\t.section .drectve\n");
+         for (dl = a_list; dl; dl = dl->next)
+           {
+             fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
+           }
+       }
+      if (d_list)
+       {
+         fprintf (f, "\t.section .rdata\n");
+         for (dl = d_list; dl; dl = dl->next)
+           {
+             char *p;
+             int l;
+             /* We dont output as ascii 'cause there can
+                be quote characters in the string */
+
+             l = 0;
+             for (p = dl->text; *p; p++)
+               {
+                 if (l == 0)
+                   fprintf (f, "\t%s\t", ASM_BYTE);
+                 else
+                   fprintf (f, ",");
+                 fprintf (f, "%d", *p);
+                 if (p[1] == 0)
+                   {
+                     fprintf (f, ",0\n");
+                     break;
+                   }
+                 if (++l == 10)
+                   {
+                     fprintf (f, "\n");
+                     l = 0;
+                   }
+               }
+           }
+       }
+    }
+
+
+  /* Add to the output file a way of getting to the exported names
+     without using the import library. */
+  if (add_indirect)
+    {
+      fprintf (f, "\t.section\t.rdata\n");
+      for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
+       if (!exp->noname || show_allnames)
+         {
+           /* We use a single underscore for MS compatibility, and a
+               double underscore for backward compatibility with old
+               cygwin releases.  */
+           fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
+           fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
+           fprintf (f, "__imp_%s:\n", exp->name);
+           fprintf (f, "_imp__%s:\n", exp->name);
+           fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
+         }
+    }
+
+  /* Dump the reloc section if a base file is provided */
+  if (base_file)
+    {
+      int addr;
+      long need[PAGE_SIZE];
+      long page_addr;
+      int numbytes;
+      int num_entries;
+      long *copy;
+      int j;
+      int on_page;
+      fprintf (f, "\t.section\t.init\n");
+      fprintf (f, "lab:\n");
+
+      fseek (base_file, 0, SEEK_END);
+      numbytes = ftell (base_file);
+      fseek (base_file, 0, SEEK_SET);
+      copy = xmalloc (numbytes);
+      fread (copy, 1, numbytes, base_file);
+      num_entries = numbytes / sizeof (long);
+
+
+      fprintf (f, "\t.section\t.reloc\n");
+      if (num_entries)
+       {
+         int src;
+         int dst = 0;
+         int last = -1;
+         int totsize = 0;
+
+         qsort (copy, num_entries, sizeof (long), sfunc);
+         /* Delete duplcates */
+         for (src = 0; src < num_entries; src++)
+           {
+             if (last != copy[src])
+               last = copy[dst++] = copy[src];
+           }
+         num_entries = dst;
+         addr = copy[0];
+         page_addr = addr & PAGE_MASK;         /* work out the page addr */
+         on_page = 0;
+         for (j = 0; j < num_entries; j++)
+           {
+             totsize += 2;
+             addr = copy[j];
+             if ((addr & PAGE_MASK) != page_addr)
+               {
+                 totsize += 8 + (on_page & 1)*2;
+                 flush_page (f, need, page_addr, on_page);
+                 on_page = 0;
+                 page_addr = addr & PAGE_MASK;
+               }
+             need[on_page++] = addr;
+           }
+
+         /* Pad the section to an even 32-byte boundary.  This will make
+            the BeOS loader much happier, and shouldn't matter for other
+            OSes. */
+         while ((totsize + 8 + (on_page & 1)*2) % 32 != 0)
+           {
+             /* 0x0000 is an absolute relocation that should be ignored.  */
+             need[on_page++] = 0x0000;
+             totsize += 2;
+           }
+
+         flush_page (f, need, page_addr, on_page);
+
+         /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
+       }
+    }
+
+  generate_idata_ofile (f);
+
+  fclose (f);
+
+  /* assemble the file */
+  sprintf (outfile, "%s -o %s %s", as_flags, exp_name, TMP_ASM);
+
+#ifdef DLLTOOL_ARM
+  if (interwork)
+    strcat (outfile, " -mthumb-interwork");
+#endif
+  
+  run (as_name, outfile);
+  
+  if (dontdeltemps == 0)
+    unlink (TMP_ASM);
+  
+  inform (_("Generated exports file"));
+}
+
+static const char *
+xlate (name)
+     const char *name;
+{
+  if (add_underscore)
+    {
+      char *copy = xmalloc (strlen (name) + 2);
+      copy[0] = '_';
+      strcpy (copy + 1, name);
+      name = copy;
+    }
+
+  if (killat)
+    {
+      char *p;
+      p = strchr (name, '@');
+      if (p)
+       *p = 0;
+    }
+  return name;
+}
+
+/**********************************************************************/
+
+#if 0
+
+static void
+dump_iat (f, exp)
+     FILE *f;
+     export_type *exp;
+{
+  if (exp->noname && !show_allnames )
+    {
+      fprintf (f, "\t%s\t0x%08x\n",
+              ASM_LONG,
+              exp->ordinal | 0x80000000); /* hint or orindal ?? */
+    }
+  else
+    {
+      fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
+              exp->ordinal,
+              ASM_RVA_AFTER);
+    }
+}
+
+#endif
+
+typedef struct
+{
+  int id;
+  const char *name;
+  int flags;
+  int align;
+  asection *sec;
+  asymbol *sym;
+  asymbol **sympp;
+  int size;
+  unsigned   char *data;
+} sinfo;
+
+#ifndef DLLTOOL_PPC
+
+#define TEXT 0
+#define DATA 1
+#define BSS 2
+#define IDATA7 3
+#define IDATA5 4
+#define IDATA4 5
+#define IDATA6 6
+
+#define NSECS 7
+
+static sinfo secdata[NSECS] =
+{
+  { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 2},
+  { DATA,   ".data",    SEC_DATA,                    2},
+  { BSS,    ".bss",     0,                           2},
+  { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
+  { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
+  { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
+  { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1}
+};
+
+#else
+
+/* Sections numbered to make the order the same as other PowerPC NT    */
+/* compilers. This also keeps funny alignment thingies from happening. */
+#define TEXT   0
+#define PDATA  1
+#define RDATA  2
+#define IDATA5 3
+#define IDATA4 4
+#define IDATA6 5
+#define IDATA7 6
+#define DATA   7
+#define BSS    8
+
+#define NSECS 9
+
+static sinfo secdata[NSECS] =
+{
+  { TEXT,   ".text",    SEC_CODE | SEC_HAS_CONTENTS, 3},
+  { PDATA,  ".pdata",   SEC_HAS_CONTENTS,            2},
+  { RDATA,  ".reldata", SEC_HAS_CONTENTS,            2},
+  { IDATA5, ".idata$5", SEC_HAS_CONTENTS,            2},
+  { IDATA4, ".idata$4", SEC_HAS_CONTENTS,            2},
+  { IDATA6, ".idata$6", SEC_HAS_CONTENTS,            1},
+  { IDATA7, ".idata$7", SEC_HAS_CONTENTS,            2},
+  { DATA,   ".data",    SEC_DATA,                    2},
+  { BSS,    ".bss",     0,                           2}
+};
+
+#endif
+
+/*
+This is what we're trying to make.  We generate the imp symbols with
+both single and double underscores, for compatibility.
+
+       .text
+       .global _GetFileVersionInfoSizeW@8
+       .global __imp_GetFileVersionInfoSizeW@8
+_GetFileVersionInfoSizeW@8:
+       jmp *   __imp_GetFileVersionInfoSizeW@8
+       .section        .idata$7        # To force loading of head
+       .long   __version_a_head
+# Import Address Table
+       .section        .idata$5
+__imp_GetFileVersionInfoSizeW@8:
+       .rva    ID2
+
+# Import Lookup Table
+       .section        .idata$4
+       .rva    ID2
+# Hint/Name table
+       .section        .idata$6
+ID2:   .short  2
+       .asciz  "GetFileVersionInfoSizeW"
+
+
+For the PowerPC, here's the variation on the above scheme:
+
+# Rather than a simple "jmp *", the code to get to the dll function
+# looks like:
+         .text
+         lwz   r11,[tocv]__imp_function_name(r2)
+#                 RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
+         lwz   r12,0(r11)
+        stw    r2,4(r1)
+        mtctr  r12
+        lwz    r2,4(r11)
+        bctr
+*/
+
+static char *
+make_label (prefix, name)
+     const char *prefix;
+     const char *name;
+{
+  int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
+  char *copy = xmalloc (len +1 );
+  strcpy (copy, ASM_PREFIX);
+  strcat (copy, prefix);
+  strcat (copy, name);
+  return copy;
+}
+
+static bfd *
+make_one_lib_file (exp, i)
+     export_type *exp;
+     int i;
+{
+#if 0
+    {
+      FILE *f;
+      char *prefix="d";
+      sprintf (outfile, "%ss%05d.s", prefix, i);
+      f = fopen (outfile, FOPEN_WT);
+      fprintf (f, "\t.text\n");
+      fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
+      fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
+      fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name);
+      fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
+              exp->name, ASM_JUMP, exp->name);
+
+      fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
+      fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
+
+
+      fprintf (f,"%s Import Address Table\n", ASM_C);
+
+      fprintf (f, "\t.section  .idata$5\n");
+      fprintf (f, "__imp_%s:\n", exp->name);
+      fprintf (f, "_imp__%s:\n", exp->name);
+
+      dump_iat (f, exp);
+
+      fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
+      fprintf (f, "\t.section  .idata$4\n");
+
+      dump_iat (f, exp);
+
+      if(!exp->noname || show_allnames)
+       {
+         fprintf (f, "%s Hint/Name table\n", ASM_C);
+         fprintf (f, "\t.section       .idata$6\n");
+         fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
+         fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
+       }
+
+      fclose (f);
+
+      sprintf (outfile, "%s -o %ss%05d.o %ss%d.s",
+              as_flags, prefix, i, prefix, i);
+
+#ifdef DLLTOOL_ARM
+      if (interwork)
+       strcat (outfile, " -mthumb-interwork");
+#endif
+  
+      run (as_name, outfile);
+    }
+#else /* if 0 */
+    {
+      bfd *      abfd;
+      asymbol *  exp_label;
+      asymbol *  iname;
+      asymbol *  iname2;
+      asymbol *  iname_lab;
+      asymbol ** iname_lab_pp;
+      asymbol ** iname_pp;
+#ifdef DLLTOOL_PPC
+      asymbol ** fn_pp;
+      asymbol ** toc_pp;
+#define EXTRA   2
+#endif
+#ifndef EXTRA
+#define EXTRA    0
+#endif
+      asymbol *  ptrs[NSECS + 4 + EXTRA + 1];
+
+      char *     outname = xmalloc (10);
+      int        oidx = 0;
+
+      
+      sprintf (outname, "%s%05d.o", TMP_STUB, i);
+      
+      abfd = bfd_openw (outname, HOW_BFD_TARGET);
+      
+      if (!abfd)
+       /* xgettext:c-format */
+       fatal (_("bfd_open failed open stub file: %s"), outname);
+
+      /* xgettext:c-format */
+      inform (_("Creating stub file: %s"), outname);
+      
+      bfd_set_format (abfd, bfd_object);
+      bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
+
+#ifdef DLLTOOL_ARM
+      if (interwork)
+       bfd_set_private_flags (abfd, F_INTERWORK);
+#endif
+      
+      /* First make symbols for the sections */
+      for (i = 0; i < NSECS; i++)
+       {
+         sinfo *si = secdata + i;
+         if (si->id != i)
+           abort();
+         si->sec = bfd_make_section_old_way (abfd, si->name);
+         bfd_set_section_flags (abfd,
+                                si->sec,
+                                si->flags);
+
+         bfd_set_section_alignment(abfd, si->sec, si->align);
+         si->sec->output_section = si->sec;
+         si->sym = bfd_make_empty_symbol(abfd);
+         si->sym->name = si->sec->name;
+         si->sym->section = si->sec;
+         si->sym->flags = BSF_LOCAL;
+         si->sym->value = 0;
+         ptrs[oidx] = si->sym;
+         si->sympp = ptrs + oidx;
+         si->size = 0;
+         si->data = NULL;
+
+         oidx++;
+       }
+
+      if (! exp->data)
+       {
+         exp_label = bfd_make_empty_symbol (abfd);
+         exp_label->name = make_label ("", exp->name);
+
+         /* On PowerPC, the function name points to a descriptor in
+            the rdata section, the first element of which is a
+            pointer to the code (..function_name), and the second
+            points to the .toc */
+#ifdef DLLTOOL_PPC
+         if (machine == MPPC)
+           exp_label->section = secdata[RDATA].sec;
+         else
+#endif
+           exp_label->section = secdata[TEXT].sec;
+
+         exp_label->flags = BSF_GLOBAL;
+         exp_label->value = 0;
+
+#ifdef DLLTOOL_ARM
+         if (machine == MTHUMB)
+           bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
+#endif
+         ptrs[oidx++] = exp_label;
+       }
+
+      /* Generate imp symbols with one underscore for Microsoft
+         compatibility, and with two underscores for backward
+         compatibility with old versions of cygwin.  */
+      iname = bfd_make_empty_symbol(abfd);
+      iname->name = make_label ("__imp_", exp->name);
+      iname->section = secdata[IDATA5].sec;
+      iname->flags = BSF_GLOBAL;
+      iname->value = 0;
+
+      iname2 = bfd_make_empty_symbol(abfd);
+      iname2->name = make_label ("_imp__", exp->name);
+      iname2->section = secdata[IDATA5].sec;
+      iname2->flags = BSF_GLOBAL;
+      iname2->value = 0;
+
+      iname_lab = bfd_make_empty_symbol(abfd);
+
+      iname_lab->name = head_label;
+      iname_lab->section = (asection *)&bfd_und_section;
+      iname_lab->flags = 0;
+      iname_lab->value = 0;
+
+
+      iname_pp = ptrs + oidx;
+      ptrs[oidx++] = iname;
+      ptrs[oidx++] = iname2;
+
+      iname_lab_pp = ptrs + oidx;
+      ptrs[oidx++] = iname_lab;
+
+#ifdef DLLTOOL_PPC
+      /* The symbol refering to the code (.text) */
+      {
+       asymbol *function_name;
+
+       function_name = bfd_make_empty_symbol(abfd);
+       function_name->name = make_label ("..", exp->name);
+       function_name->section = secdata[TEXT].sec;
+       function_name->flags = BSF_GLOBAL;
+       function_name->value = 0;
+
+       fn_pp = ptrs + oidx;
+       ptrs[oidx++] = function_name;
+      }
+
+      /* The .toc symbol */
+      {
+       asymbol *toc_symbol;    /* The .toc symbol */
+
+       toc_symbol = bfd_make_empty_symbol (abfd);
+       toc_symbol->name = make_label (".", "toc");
+       toc_symbol->section = (asection *)&bfd_und_section;
+       toc_symbol->flags = BSF_GLOBAL;
+       toc_symbol->value = 0;
+
+       toc_pp = ptrs + oidx;
+       ptrs[oidx++] = toc_symbol;
+      }
+#endif
+      
+      ptrs[oidx] = 0;
+
+      for (i = 0; i < NSECS; i++)
+       {
+         sinfo *si = secdata + i;
+         asection *sec = si->sec;
+         arelent *rel;
+         arelent **rpp;
+
+         switch (i)
+           {
+           case TEXT:
+             if (! exp->data)
+               {
+                 si->size = HOW_JTAB_SIZE;
+                 si->data = xmalloc (HOW_JTAB_SIZE);
+                 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
+
+                 /* add the reloc into idata$5 */
+                 rel = xmalloc (sizeof (arelent));
+                 
+                 rpp = xmalloc (sizeof (arelent *) * 2);
+                 rpp[0] = rel;
+                 rpp[1] = 0;
+                 
+                 rel->address = HOW_JTAB_ROFF;
+                 rel->addend = 0;
+
+                 if (machine == MPPC)
+                   {
+                     rel->howto = bfd_reloc_type_lookup (abfd,
+                                                         BFD_RELOC_16_GOTOFF);
+                     rel->sym_ptr_ptr = iname_pp;
+                   }
+                 else
+                   {
+                     rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+                     rel->sym_ptr_ptr = secdata[IDATA5].sympp;
+                   }
+                 sec->orelocation = rpp;
+                 sec->reloc_count = 1;
+               }
+             break;
+           case IDATA4:
+           case IDATA5:
+             /* An idata$4 or idata$5 is one word long, and has an
+                rva to idata$6 */
+
+             si->data = xmalloc (4);
+             si->size = 4;
+
+             if (exp->noname)
+               {
+                 si->data[0] = exp->ordinal ;
+                 si->data[1] = exp->ordinal >> 8;
+                 si->data[2] = exp->ordinal >> 16;
+                 si->data[3] = 0x80;
+               }
+             else
+               {
+                 sec->reloc_count = 1;
+                 memset (si->data, 0, si->size);
+                 rel = xmalloc (sizeof (arelent));
+                 rpp = xmalloc (sizeof (arelent *) * 2);
+                 rpp[0] = rel;
+                 rpp[1] = 0;
+                 rel->address = 0;
+                 rel->addend = 0;
+                 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
+                 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
+                 sec->orelocation = rpp;
+               }
+
+             break;
+
+           case IDATA6:
+             if (!exp->noname)
+               {
+                 /* This used to add 1 to exp->hint.  I don't know
+                     why it did that, and it does not match what I see
+                     in programs compiled with the MS tools.  */
+                 int idx = exp->hint;
+                 si->size = strlen (xlate (exp->name)) + 3;
+                 si->data = xmalloc (si->size);
+                 si->data[0] = idx & 0xff;
+                 si->data[1] = idx >> 8;
+                 strcpy (si->data + 2, xlate (exp->name));
+               }
+             break;
+           case IDATA7:
+             si->size = 4;
+             si->data =xmalloc(4);
+             memset (si->data, 0, si->size);
+             rel = xmalloc (sizeof (arelent));
+             rpp = xmalloc (sizeof (arelent *) * 2);
+             rpp[0] = rel;
+             rel->address = 0;
+             rel->addend = 0;
+             rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
+             rel->sym_ptr_ptr = iname_lab_pp;
+             sec->orelocation = rpp;
+             sec->reloc_count = 1;
+             break;
+
+#ifdef DLLTOOL_PPC
+           case PDATA:
+             {
+               /* The .pdata section is 5 words long. */
+               /* Think of it as:                     */
+               /* struct                              */
+               /* {                                   */
+               /*   bfd_vma BeginAddress,     [0x00]  */
+               /*           EndAddress,       [0x04]  */
+               /*           ExceptionHandler, [0x08]  */
+               /*           HandlerData,      [0x0c]  */
+               /*           PrologEndAddress; [0x10]  */
+               /* };                                  */
+
+               /* So this pdata section setups up this as a glue linkage to
+                  a dll routine. There are a number of house keeping things
+                  we need to do:
+
+                  1. In the name of glue trickery, the ADDR32 relocs for 0,
+                     4, and 0x10 are set to point to the same place:
+                     "..function_name".
+                  2. There is one more reloc needed in the pdata section.
+                     The actual glue instruction to restore the toc on
+                     return is saved as the offset in an IMGLUE reloc.
+                     So we need a total of four relocs for this section.
+
+                  3. Lastly, the HandlerData field is set to 0x03, to indicate
+                     that this is a glue routine.
+               */
+               arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
+
+               /* alignment must be set to 2**2 or you get extra stuff */
+               bfd_set_section_alignment(abfd, sec, 2);
+
+               si->size = 4 * 5;
+               si->data =xmalloc(4 * 5);
+               memset (si->data, 0, si->size);
+               rpp = xmalloc (sizeof (arelent *) * 5);
+               rpp[0] = imglue  = xmalloc (sizeof (arelent));
+               rpp[1] = ba_rel  = xmalloc (sizeof (arelent));
+               rpp[2] = ea_rel  = xmalloc (sizeof (arelent));
+               rpp[3] = pea_rel = xmalloc (sizeof (arelent));
+               rpp[4] = 0;
+
+               /* stick the toc reload instruction in the glue reloc */
+               bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
+
+               imglue->addend = 0;
+               imglue->howto = bfd_reloc_type_lookup (abfd,
+                                                      BFD_RELOC_32_GOTOFF);
+               imglue->sym_ptr_ptr = fn_pp;
+
+               ba_rel->address = 0;
+               ba_rel->addend = 0;
+               ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+               ba_rel->sym_ptr_ptr = fn_pp;
+
+               bfd_put_32(abfd, 0x18, si->data + 0x04);
+               ea_rel->address = 4;
+               ea_rel->addend = 0;
+               ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+               ea_rel->sym_ptr_ptr = fn_pp;
+
+               /* mark it as glue */
+               bfd_put_32(abfd, 0x03, si->data + 0x0c);
+
+               /* mark the prolog end address */
+               bfd_put_32(abfd, 0x0D, si->data + 0x10);
+               pea_rel->address = 0x10;
+               pea_rel->addend = 0;
+               pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+               pea_rel->sym_ptr_ptr = fn_pp;
+
+               sec->orelocation = rpp;
+               sec->reloc_count = 4;
+               break;
+             }
+           case RDATA:
+             /* Each external function in a PowerPC PE file has a two word
+                descriptor consisting of:
+                1. The address of the code.
+                2. The address of the appropriate .toc
+                We use relocs to build this.
+             */
+
+             si->size = 8;
+             si->data = xmalloc (8);
+             memset (si->data, 0, si->size);
+
+             rpp = xmalloc (sizeof (arelent *) * 3);
+             rpp[0] = rel = xmalloc (sizeof (arelent));
+             rpp[1] = xmalloc (sizeof (arelent));
+             rpp[2] = 0;
+
+             rel->address = 0;
+             rel->addend = 0;
+             rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+             rel->sym_ptr_ptr = fn_pp;
+
+             rel = rpp[1];
+
+             rel->address = 4;
+             rel->addend = 0;
+             rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+             rel->sym_ptr_ptr = toc_pp;
+
+             sec->orelocation = rpp;
+             sec->reloc_count = 2;
+             break;
+#endif /* DLLTOOL_PPC */
+           }
+       }
+
+      {
+       bfd_vma vma = 0;
+       /* Size up all the sections */
+       for (i = 0; i < NSECS; i++)
+         {
+           sinfo *si = secdata + i;
+
+           bfd_set_section_size (abfd, si->sec, si->size);
+           bfd_set_section_vma (abfd, si->sec, vma);
+
+/*         vma += si->size;*/
+         }
+      }
+      /* Write them out */
+      for (i = 0; i < NSECS; i++)
+       {
+         sinfo *si = secdata + i;
+
+         if (i == IDATA5 && no_idata5)
+           continue;
+
+         if (i == IDATA4 && no_idata4)
+           continue;
+
+         bfd_set_section_contents (abfd, si->sec,
+                                   si->data, 0,
+                                   si->size);
+       }
+
+      bfd_set_symtab (abfd, ptrs, oidx);
+      bfd_close (abfd);
+      abfd = bfd_openr (outname, HOW_BFD_TARGET);
+      return abfd;
+    }
+#endif
+}
+
+static bfd *
+make_head ()
+{
+  FILE *  f = fopen (TMP_HEAD_S, FOPEN_WT);
+
+  fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
+  fprintf (f, "\t.section      .idata$2\n");
+
+  fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
+
+  fprintf (f, "%s:\n", head_label);
+
+  fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
+          ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
+
+  fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
+  fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
+  fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
+  fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
+  fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
+          ASM_RVA_BEFORE,
+          imp_name_lab,
+          ASM_RVA_AFTER,
+          ASM_C);
+  fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
+          ASM_RVA_BEFORE,
+          ASM_RVA_AFTER, ASM_C);
+
+  fprintf (f, "%sStuff for compatibility\n", ASM_C);
+
+  if (!no_idata5)
+    {
+      fprintf (f, "\t.section\t.idata$5\n");
+      fprintf (f, "\t%s\t0\n", ASM_LONG);
+      fprintf (f, "fthunk:\n");
+    }
+  if (!no_idata4)
+    {
+      fprintf (f, "\t.section\t.idata$4\n");
+
+      fprintf (f, "\t%s\t0\n", ASM_LONG);
+      fprintf (f, "\t.section  .idata$4\n");
+      fprintf (f, "hname:\n");
+    }
+  fclose (f);
+
+  sprintf (outfile, "%s -o %s %s", as_flags, TMP_HEAD_O, TMP_HEAD_S);
+  
+#ifdef DLLTOOL_ARM
+  if (interwork)
+    strcat (outfile, " -mthumb-interwork");
+#endif
+  
+  run (as_name, outfile);
+
+  return  bfd_openr (TMP_HEAD_O, HOW_BFD_TARGET);
+}
+
+static bfd *
+make_tail ()
+{
+  FILE *  f = fopen (TMP_TAIL_S, FOPEN_WT);
+
+  if (!no_idata4)
+    {
+      fprintf (f, "\t.section  .idata$4\n");
+      fprintf (f, "\t%s\t0\n", ASM_LONG);
+    }
+  if (!no_idata5)
+    {
+      fprintf (f, "\t.section  .idata$5\n");
+      fprintf (f, "\t%s\t0\n", ASM_LONG);
+    }
+
+#ifdef DLLTOOL_PPC
+  /* Normally, we need to see a null descriptor built in idata$3 to
+     act as the terminator for the list. The ideal way, I suppose,
+     would be to mark this section as a comdat type 2 section, so
+     only one would appear in the final .exe (if our linker supported
+     comdat, that is) or cause it to be inserted by something else (say
+     crt0)
+  */
+
+  fprintf (f, "\t.section      .idata$3\n");
+  fprintf (f, "\t%s\t0\n", ASM_LONG);
+  fprintf (f, "\t%s\t0\n", ASM_LONG);
+  fprintf (f, "\t%s\t0\n", ASM_LONG);
+  fprintf (f, "\t%s\t0\n", ASM_LONG);
+  fprintf (f, "\t%s\t0\n", ASM_LONG);
+#endif
+
+#ifdef DLLTOOL_PPC
+  /* Other PowerPC NT compilers use idata$6 for the dllname, so I
+     do too. Original, huh? */
+  fprintf (f, "\t.section      .idata$6\n");
+#else
+  fprintf (f, "\t.section      .idata$7\n");
+#endif
+
+  fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
+  fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
+          imp_name_lab, ASM_TEXT, dll_name);
+
+  fclose (f);
+
+  sprintf (outfile, "%s -o %s %s", as_flags, TMP_TAIL_O, TMP_TAIL_S);
+  
+#ifdef DLLTOOL_ARM
+  if (interwork)
+    strcat (outfile, " -mthumb-interwork");
+#endif
+  
+  run (as_name, outfile);
+  
+  return  bfd_openr (TMP_TAIL_O, HOW_BFD_TARGET);
+}
+
+static void
+gen_lib_file ()
+{
+  int i;
+  export_type *exp;
+  bfd *ar_head;
+  bfd *ar_tail;
+  bfd *outarch;
+  bfd * head  = 0;
+
+  unlink (imp_name);
+
+  outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
+
+  if (!outarch)
+    /* xgettext:c-format */
+    fatal (_("Can't open .lib file: %s"), imp_name);
+
+  /* xgettext:c-format */
+  inform (_("Creating library file: %s\n"), imp_name);
+  
+  bfd_set_format (outarch, bfd_archive);
+  outarch->has_armap = 1;
+
+  /* Work out a reasonable size of things to put onto one line. */
+
+  ar_head = make_head ();
+  ar_tail = make_tail();
+
+  if (ar_head == NULL || ar_tail == NULL)
+    return;
+  
+  for (i = 0; (exp = d_exports_lexically[i]); i++)
+    {
+      bfd *n = make_one_lib_file (exp, i);
+      n->next = head;
+      head = n;
+    }
+
+  /* Now stick them all into the archive */
+
+  ar_head->next = head;
+  ar_tail->next = ar_head;
+  head = ar_tail;
+
+  if (! bfd_set_archive_head (outarch, head))
+    bfd_fatal ("bfd_set_archive_head");
+  
+  if (! bfd_close (outarch))
+    bfd_fatal (imp_name);
+
+  while (head != NULL)
+    {
+      bfd *n = head->next;
+      bfd_close (head);
+      head = n;
+    }
+
+  /* Delete all the temp files */
+
+  if (dontdeltemps == 0)
+    {
+      unlink (TMP_HEAD_O);
+      unlink (TMP_HEAD_S);
+      unlink (TMP_TAIL_O);
+      unlink (TMP_TAIL_S);
+    }
+
+  if (dontdeltemps < 2)
+    {
+      for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
+       {
+         sprintf (outfile, "%s%05d.o", TMP_STUB, i);
+         if (unlink (outfile) < 0)
+           /* xgettext:c-format */
+           warn (_("cannot delete %s: %s\n"), outfile, strerror (errno));
+       }
+    }
+  
+  inform (_("Created lib file"));
+}
+
+/**********************************************************************/
+
+/* Run through the information gathered from the .o files and the
+   .def file and work out the best stuff */
+static int
+pfunc (a, b)
+     const void *a;
+     const void *b;
+{
+  export_type *ap = *(export_type **) a;
+  export_type *bp = *(export_type **) b;
+  if (ap->ordinal == bp->ordinal)
+    return 0;
+
+  /* unset ordinals go to the bottom */
+  if (ap->ordinal == -1)
+    return 1;
+  if (bp->ordinal == -1)
+    return -1;
+  return (ap->ordinal - bp->ordinal);
+}
+
+static int
+nfunc (a, b)
+     const void *a;
+     const void *b;
+{
+  export_type *ap = *(export_type **) a;
+  export_type *bp = *(export_type **) b;
+
+  return (strcmp (ap->name, bp->name));
+}
+
+static void
+remove_null_names (ptr)
+     export_type **ptr;
+{
+  int src;
+  int dst;
+  for (dst = src = 0; src < d_nfuncs; src++)
+    {
+      if (ptr[src])
+       {
+         ptr[dst] = ptr[src];
+         dst++;
+       }
+    }
+  d_nfuncs = dst;
+}
+
+static void
+dtab (ptr)
+     export_type **ptr;
+{
+#ifdef SACDEBUG
+  int i;
+  for (i = 0; i < d_nfuncs; i++)
+    {
+      if (ptr[i])
+       {
+         printf ("%d %s @ %d %s%s%s\n",
+                 i, ptr[i]->name, ptr[i]->ordinal,
+                 ptr[i]->noname ? "NONAME " : "",
+                 ptr[i]->constant ? "CONSTANT" : "",
+                 ptr[i]->data ? "DATA" : "");
+       }
+      else
+       printf ("empty\n");
+    }
+#endif
+}
+
+static void
+process_duplicates (d_export_vec)
+     export_type **d_export_vec;
+{
+  int more = 1;
+  int i;
+  while (more)
+    {
+
+      more = 0;
+      /* Remove duplicates */
+      qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
+
+      dtab (d_export_vec);
+      for (i = 0; i < d_nfuncs - 1; i++)
+       {
+         if (strcmp (d_export_vec[i]->name,
+                     d_export_vec[i + 1]->name) == 0)
+           {
+
+             export_type *a = d_export_vec[i];
+             export_type *b = d_export_vec[i + 1];
+
+             more = 1;
+             
+             /* xgettext:c-format */
+             inform (_("Warning, ignoring duplicate EXPORT %s %d,%d\n"),
+                     a->name, a->ordinal, b->ordinal);
+             
+             if (a->ordinal != -1
+                 && b->ordinal != -1)
+               /* xgettext:c-format */
+               fatal (_("Error, duplicate EXPORT with oridinals: %s"),
+                     a->name);
+
+             /* Merge attributes */
+             b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
+             b->constant |= a->constant;
+             b->noname |= a->noname;
+             b->data |= a->data;
+             d_export_vec[i] = 0;
+           }
+
+         dtab (d_export_vec);
+         remove_null_names (d_export_vec);
+         dtab (d_export_vec);
+       }
+    }
+
+
+  /* Count the names */
+  for (i = 0; i < d_nfuncs; i++)
+    {
+      if (!d_export_vec[i]->noname)
+       d_named_nfuncs++;
+    }
+}
+
+static void
+fill_ordinals (d_export_vec)
+     export_type **d_export_vec;
+{
+  int lowest = -1;
+  int i;
+  char *ptr;
+  int size = 65536;
+
+  qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
+
+  /* fill in the unset ordinals with ones from our range */
+
+  ptr = (char *) xmalloc (size);
+
+  memset (ptr, 0, size);
+
+  /* Mark in our large vector all the numbers that are taken */
+  for (i = 0; i < d_nfuncs; i++)
+    {
+      if (d_export_vec[i]->ordinal != -1)
+       {
+         ptr[d_export_vec[i]->ordinal] = 1;
+         if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
+           {
+             lowest = d_export_vec[i]->ordinal;
+           }
+       }
+    }
+
+  /* Start at 1 for compatibility with MS toolchain.  */
+  if (lowest == -1)
+    lowest = 1;
+
+  /* Now fill in ordinals where the user wants us to choose. */
+  for (i = 0; i < d_nfuncs; i++)
+    {
+      if (d_export_vec[i]->ordinal == -1)
+       {
+         register int j;
+
+         /* First try within or after any user supplied range. */
+         for (j = lowest; j < size; j++)
+           if (ptr[j] == 0)
+             {
+               ptr[j] = 1;
+               d_export_vec[i]->ordinal = j;
+               goto done;
+             }
+
+         /* Then try before the range. */
+         for (j = lowest; j >0; j--)
+           if (ptr[j] == 0)
+             {
+               ptr[j] = 1;
+               d_export_vec[i]->ordinal = j;
+               goto done;
+             }
+       done:;
+       }
+    }
+
+  free (ptr);
+
+  /* And resort */
+
+  qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
+
+  /* Work out the lowest and highest ordinal numbers.  */
+  if (d_nfuncs)
+    {
+      if (d_export_vec[0])
+       d_low_ord = d_export_vec[0]->ordinal;
+      if (d_export_vec[d_nfuncs-1])
+       d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
+    }
+}
+
+static int
+alphafunc (av,bv)
+     const void *av;
+     const void *bv;
+{
+  const export_type **a = (const export_type **) av;
+  const export_type **b = (const export_type **) bv;
+
+  return strcmp ((*a)->name, (*b)->name);
+}
+
+static void
+mangle_defs ()
+{
+  /* First work out the minimum ordinal chosen */
+
+  export_type *exp;
+
+  int i;
+  int hint = 0;
+  export_type **d_export_vec
+  = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
+
+  inform (_("Processing definitions"));
+  
+  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
+    {
+      d_export_vec[i] = exp;
+    }
+
+  process_duplicates (d_export_vec);
+  fill_ordinals (d_export_vec);
+
+  /* Put back the list in the new order */
+  d_exports = 0;
+  for (i = d_nfuncs - 1; i >= 0; i--)
+    {
+      d_export_vec[i]->next = d_exports;
+      d_exports = d_export_vec[i];
+    }
+
+  /* Build list in alpha order */
+  d_exports_lexically = (export_type **)
+    xmalloc (sizeof (export_type *) * (d_nfuncs + 1));
+
+  for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
+    {
+      d_exports_lexically[i] = exp;
+    }
+  d_exports_lexically[i] = 0;
+
+  qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
+
+  /* Fill exp entries with their hint values */
+
+  for (i = 0; i < d_nfuncs; i++)
+    {
+      if (!d_exports_lexically[i]->noname || show_allnames)
+       d_exports_lexically[i]->hint = hint++;
+    }
+  
+  inform (_("Processed definitions"));
+}
+
+/**********************************************************************/
+
+static void
+usage (file, status)
+     FILE *file;
+     int status;
+{
+  /* xgetext:c-format */
+  fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
+  /* xgetext:c-format */
+  fprintf (file, _("   -m --machine <machine>    Create {arm, i386, ppc, thumb} DLL. [default: %s]\n"), mname);
+  fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
+  fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
+  fprintf (file, _("   -a --add-indirect         Add dll indirects to export file.\n"));
+  fprintf (file, _("   -D --dllname <name>       Name of input dll to put into interface lib.\n"));
+  fprintf (file, _("   -d --input-def <deffile>  Name of .def file to be read in.\n"));
+  fprintf (file, _("   -z --output-def <deffile> Name of .def file to be created.\n"));
+  fprintf (file, _("   --export-all-symbols      Export all symbols to .def\n"));
+  fprintf (file, _("   --no-export-all-symbols   Only export listed symbols\n"));
+  fprintf (file, _("   --exclude-symbols <list>  Don't export <list>\n"));
+  fprintf (file, _("   --no-default-excludes     Clear default exclude symbols\n"));
+  fprintf (file, _("   -b --base-file <basefile> Read linker generated base file.\n"));
+  fprintf (file, _("   -x --no-idata4            Don't generate idata$4 section.\n"));
+  fprintf (file, _("   -c --no-idata5            Don't generate idata$5 section.\n"));
+  fprintf (file, _("   -U --add-underscore       Add underscores to symbols in interface library.\n"));
+  fprintf (file, _("   -k --kill-at              Kill @<n> from exported names.\n"));
+  fprintf (file, _("   -A --add-stdcall-alias    Add aliases without @<n>.\n"));
+  fprintf (file, _("   -S --as <name>            Use <name> for assembler.\n"));
+  fprintf (file, _("   -f --as-flags <flags>     Pass <flags> to the assembler.\n"));
+#ifdef DLLTOOL_ARM
+  fprintf (file, _("   -i --interwork            Support ARM/Thumb interworking.\n"));
+#endif
+  fprintf (file, _("   -n --no-delete            Keep temp files (repeat for extra preservation).\n"));
+  fprintf (file, _("   -v --verbose              Be verbose.\n"));
+  fprintf (file, _("   -V --version              Display the program version.\n"));
+  fprintf (file, _("   -h --help                 Display this information.\n"));
+  
+  exit (status);
+}
+
+#define OPTION_EXPORT_ALL_SYMS         150
+#define OPTION_NO_EXPORT_ALL_SYMS      (OPTION_EXPORT_ALL_SYMS + 1)
+#define OPTION_EXCLUDE_SYMS            (OPTION_NO_EXPORT_ALL_SYMS + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES     (OPTION_EXCLUDE_SYMS + 1)
+#define OPTION_NO_IDATA4               'x'
+#define OPTION_NO_IDATA5               'c'
+
+static const struct option long_options[] =
+{
+  {"no-delete", no_argument, NULL, 'n'},
+  {"dllname", required_argument, NULL, 'D'},
+  {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
+  {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
+  {"output-exp", required_argument, NULL, 'e'},
+  {"output-def", required_argument, NULL, 'z'},
+  {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
+  {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
+  {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
+  {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
+  {"output-lib", required_argument, NULL, 'l'},
+  {"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */
+  {"input-def", required_argument, NULL, 'd'},
+  {"add-underscore", no_argument, NULL, 'U'},
+  {"kill-at", no_argument, NULL, 'k'},
+  {"add-stdcall-alias", no_argument, NULL, 'A'},
+  {"verbose", no_argument, NULL, 'v'},
+  {"version", no_argument, NULL, 'V'},
+  {"help", no_argument, NULL, 'h'},
+  {"machine", required_argument, NULL, 'm'},
+  {"add-indirect", no_argument, NULL, 'a'},
+  {"base-file", required_argument, NULL, 'b'},
+  {"as", required_argument, NULL, 'S'},
+  {"as-flags", required_argument, NULL, 'f'},
+#ifdef DLLTOOL_ARM
+  {"interwork", no_argument, NULL, 'i'},
+#endif
+  {0}
+};
+
+int
+main (ac, av)
+     int ac;
+     char **av;
+{
+  int c;
+  int i;
+  char *firstarg = 0;
+  program_name = av[0];
+  oav = av;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  while ((c = getopt_long (ac, av, "xcz:S:aD:l:e:nkAvVb:Uh?m:d:f:i",
+                          long_options, 0))
+        != EOF)
+    {
+      switch (c)
+       {
+       case OPTION_NO_IDATA4:
+         no_idata4 = 1;
+         break;
+       case OPTION_NO_IDATA5:
+         no_idata5 = 1;
+         break;
+       case OPTION_EXPORT_ALL_SYMS:
+         export_all_symbols = true;
+         break;
+       case OPTION_NO_EXPORT_ALL_SYMS:
+         export_all_symbols = false;
+         break;
+       case OPTION_EXCLUDE_SYMS:
+         add_excludes (optarg);
+         break;
+       case OPTION_NO_DEFAULT_EXCLUDES:
+         do_default_excludes = false;
+         break;
+       case 'S':
+         as_name = optarg;
+         break;
+       case 'f':
+         as_flags = optarg;
+         break;
+
+         /* ignored for compatibility */
+       case 'u':
+         break;
+       case 'a':
+         add_indirect = 1;
+         break;
+       case 'z':
+         output_def = fopen (optarg, FOPEN_WT);
+         break;
+       case 'D':
+         dll_name = optarg;
+         break;
+       case 'l':
+         imp_name = optarg;
+         break;
+       case 'e':
+         exp_name = optarg;
+         break;
+       case 'h':
+         usage (stdout, 0);
+         break;
+       case 'm':
+         mname = optarg;
+         break;
+       case 'v':
+         verbose = 1;
+         break;
+       case 'V':
+         print_version (program_name);
+         break;
+#ifdef DLLTOOL_ARM
+       case 'i':
+         interwork = 1;
+         break;
+#endif
+       case 'y':
+#if 0
+         /* We don't currently define YYDEBUG when building
+             defparse.y.  */
+         yydebug = 1;
+#endif
+         break;
+       case 'U':
+         add_underscore = 1;
+         break;
+       case 'k':
+         killat = 1;
+         break;
+       case 'A':
+         add_stdcall_alias = 1;
+         break;
+       case 'd':
+         def_file = optarg;
+         break;
+       case 'n':
+         dontdeltemps++;
+         break;
+       case 'b':
+         base_file = fopen (optarg, FOPEN_RB);
+         
+         if (!base_file)
+           /* xgettext:c-format */
+           fatal (_("Unable to open base-file: %s"), optarg);
+
+         break;
+       default:
+         usage (stderr, 1);
+         break;
+       }
+    }
+
+  for (i = 0; mtable[i].type; i++)
+    {
+      if (strcmp (mtable[i].type, mname) == 0)
+       break;
+    }
+
+  if (!mtable[i].type)
+    /* xgettext:c-format */
+    fatal (_("Machine '%s' not supported"), mname);
+
+  machine = i;
+
+#ifdef DLLTOOL_ARM
+  /* Always enable interworking for Thumb targets.  */
+  if (machine == MTHUMB && (! interwork))
+    interwork = 1;
+#endif
+  
+  if (!dll_name && exp_name)
+    {
+      int len = strlen (exp_name) + 5;
+      dll_name = xmalloc (len);
+      strcpy (dll_name, exp_name);
+      strcat (dll_name, ".dll");
+    }
+
+  /* Don't use the default exclude list if we're reading only the
+     symbols in the .drectve section.  The default excludes are meant
+     to avoid exporting DLL entry point and Cygwin32 impure_ptr.  */
+  if (! export_all_symbols)
+    do_default_excludes = false;
+  
+  if (do_default_excludes)
+    set_default_excludes ();
+
+  if (def_file)
+    process_def_file (def_file);
+
+  while (optind < ac)
+    {
+      if (!firstarg)
+       firstarg = av[optind];
+      scan_obj_file (av[optind]);
+      optind++;
+    }
+
+  mangle_defs ();
+
+  if (exp_name)
+    gen_exp_file ();
+  
+  if (imp_name)
+    {
+      /* Make imp_name safe for use as a label. */
+      char *p;
+
+      imp_name_lab = xstrdup (imp_name);
+      for (p = imp_name_lab; *p; p++)
+       {
+         if (!isalpha ((unsigned char) *p) && !isdigit ((unsigned char) *p))
+           *p = '_';
+       }
+      head_label = make_label("_head_", imp_name_lab);
+      gen_lib_file ();
+    }
+  
+  if (output_def)
+    gen_def_file ();
+
+  return 0;
+}
diff --git a/binutils/dlltool.h b/binutils/dlltool.h
new file mode 100644 (file)
index 0000000..b4167c8
--- /dev/null
@@ -0,0 +1,42 @@
+/* dlltool.h -- header file for dlltool
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#include "ansidecl.h"
+#include <stdio.h>
+
+extern void def_code PARAMS ((int));
+extern void def_data PARAMS ((int));
+extern void def_description PARAMS ((const char *));
+extern void def_exports
+  PARAMS ((const char *, const char *, int, int, int, int));
+extern void def_heapsize PARAMS ((int, int));
+extern void def_import
+  PARAMS ((const char *, const char *, const char *, const char *, int));
+extern void def_library PARAMS ((const char *, int));
+extern void def_name PARAMS ((const char *, int));
+extern void def_section PARAMS ((const char *, int));
+extern void def_stacksize PARAMS ((int, int));
+extern void def_version PARAMS ((int, int));
+extern int yyparse PARAMS ((void));
+extern int yyerror PARAMS ((const char *));
+extern int yydebug;
+extern int yylex PARAMS ((void));
+extern FILE *yyin;
+extern int linenumber;
diff --git a/binutils/dllwrap.c b/binutils/dllwrap.c
new file mode 100644 (file)
index 0000000..574611b
--- /dev/null
@@ -0,0 +1,1050 @@
+/* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+   Contributed by Mumit Khan (khan@xraylith.wisc.edu).
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# ifdef _AIX
+ #pragma alloca
+#endif
+#endif
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "bfd.h"
+#include "libiberty.h"
+#include "bucomm.h"
+#include "getopt.h"
+#include "dyn-string.h"
+
+#include <ctype.h>
+#include <time.h>
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#else /* ! HAVE_SYS_WAIT_H */
+#if ! defined (_WIN32) || defined (__CYGWIN32__)
+#ifndef WIFEXITED
+#define WIFEXITED(w)   (((w)&0377) == 0)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(w)    ((w) & 0177)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (((w) >> 8) & 0377)
+#endif
+#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
+#ifndef WIFEXITED
+#define WIFEXITED(w)   (((w) & 0xff) == 0)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(w)    ((w) & 0x7f)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
+#endif
+#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
+#endif /* ! HAVE_SYS_WAIT_H */
+
+static char *program_version = "0.2.4";
+static char *driver_name = "gcc";
+static char *cygwin_driver_flags = 
+  "-Wl,--dll -nostartfiles";
+static char *mingw32_driver_flags = "-mdll";
+static char *generic_driver_flags = "-Wl,--dll";
+
+static char *entry_point;
+
+static char *dlltool_name = "dlltool";
+
+static char *target = TARGET;
+
+typedef enum {
+  UNKNOWN_TARGET, 
+  CYGWIN_TARGET, 
+  MINGW32_TARGET
+} 
+target_type;
+
+static target_type which_target = UNKNOWN_TARGET;
+
+static int dontdeltemps = 0;
+static int dry_run = 0;
+
+static char *program_name;
+
+static int verbose = 0;
+
+static char *dll_file_name;
+static char *dll_name;
+static char *base_file_name;
+static char *exp_file_name;
+static char *def_file_name;
+static int delete_base_file = 1;
+static int delete_exp_file = 1;
+static int delete_def_file = 1;
+
+static int run PARAMS ((const char *, char *));
+static void usage PARAMS ((FILE *, int));
+static void delete_temp_files PARAMS ((void));
+static void cleanup_and_exit PARAMS ((int status));
+
+/**********************************************************************/
+
+static void
+delete_temp_files ()
+{
+  if (delete_base_file && base_file_name)
+    {
+      if (verbose)
+       fprintf (stderr, "%s temporary base file %s\n",
+                dontdeltemps ? "Keeping" : "Deleting",
+                base_file_name);
+      if (! dontdeltemps)
+        {
+          unlink (base_file_name);
+         free (base_file_name);
+       }
+    }
+  
+  if (delete_exp_file && exp_file_name)
+    {
+      if (verbose)
+       fprintf (stderr, "%s temporary exp file %s\n",
+                dontdeltemps ? "Keeping" : "Deleting",
+                exp_file_name);
+      if (! dontdeltemps)
+        {
+          unlink (exp_file_name);
+          free (exp_file_name);
+       }
+    }
+  if (delete_def_file && def_file_name)
+    {
+      if (verbose)
+       fprintf (stderr, "%s temporary def file %s\n",
+                dontdeltemps ? "Keeping" : "Deleting",
+                def_file_name);
+      if (! dontdeltemps)
+        {
+          unlink (def_file_name);
+          free (def_file_name);
+       }
+    }
+}
+
+static void 
+cleanup_and_exit (int status)
+{
+  delete_temp_files ();
+  exit (status);
+}
+  
+static int
+run (what, args)
+     const char *what;
+     char *args;
+{
+  char *s;
+  int pid, wait_status, retcode;
+  int i;
+  const char **argv;
+  char *errmsg_fmt, *errmsg_arg;
+  char *temp_base = choose_temp_base ();
+  int in_quote;
+  char sep;
+
+  if (verbose || dry_run)
+    fprintf (stderr, "%s %s\n", what, args);
+
+  /* Count the args */
+  i = 0;
+  for (s = args; *s; s++)
+    if (*s == ' ')
+      i++;
+  i++;
+  argv = alloca (sizeof (char *) * (i + 3));
+  i = 0;
+  argv[i++] = what;
+  s = args;
+  while (1)
+    {
+      while (*s == ' ' && *s != 0)
+       s++;
+      if (*s == 0)
+       break;
+      in_quote = (*s == '\'' || *s == '"');
+      sep = (in_quote) ? *s++ : ' ';
+      argv[i++] = s;
+      while (*s != sep && *s != 0)
+       s++;
+      if (*s == 0)
+       break;
+      *s++ = 0;
+      if (in_quote)
+        s++;
+    }
+  argv[i++] = NULL;
+
+  if (dry_run)
+    return 0;
+
+  pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
+                 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
+
+  if (pid == -1)
+    {
+      int errno_val = errno;
+
+      fprintf (stderr, "%s: ", program_name);
+      fprintf (stderr, errmsg_fmt, errmsg_arg);
+      fprintf (stderr, ": %s\n", strerror (errno_val));
+      return 1;
+    }
+
+  retcode = 0;
+  pid = pwait (pid, &wait_status, 0);
+  if (pid == -1)
+    {
+      fprintf (stderr, "%s: wait: %s\n", program_name, strerror (errno));
+      retcode = 1;
+    }
+  else if (WIFSIGNALED (wait_status))
+    {
+      fprintf (stderr, "%s: subprocess got fatal signal %d\n",
+              program_name, WTERMSIG (wait_status));
+      retcode = 1;
+    }
+  else if (WIFEXITED (wait_status))
+    {
+      if (WEXITSTATUS (wait_status) != 0)
+       {
+         fprintf (stderr, "%s: %s exited with status %d\n",
+                  program_name, what, WEXITSTATUS (wait_status));
+         retcode = 1;
+       }
+    }
+  else
+    retcode = 1;
+  
+  return retcode;
+}
+
+static char *
+mybasename (name)
+     const char *name;
+{
+  const char *base = name;
+
+  while (*name)
+    {
+      if (*name == '/' || *name == '\\')
+       {
+         base = name + 1;
+       }
+      ++name;
+    }
+  return (char *) base;
+}
+
+static int 
+strhash (const char *str)
+{
+  const unsigned char *s;
+  unsigned long hash;
+  unsigned int c;
+  unsigned int len;
+
+  hash = 0;
+  len = 0;
+  s = (const unsigned char *) str;
+  while ((c = *s++) != '\0')
+    {
+      hash += c + (c << 17);
+      hash ^= hash >> 2;
+      ++len;
+    }
+  hash += len + (len << 17);
+  hash ^= hash >> 2;
+
+  return hash;
+}
+
+/**********************************************************************/
+
+void
+print_version (name)
+     const char *name;
+{
+  /* This output is intended to follow the GNU standards document.  */
+  /* xgettext:c-format */
+  printf ("GNU %s %s\n", name, program_version);
+  printf ("Copyright 1998 Free Software Foundation, Inc.\n");
+  printf ("\
+This program is free software; you may redistribute it under the terms of\n\
+the GNU General Public License.  This program has absolutely no warranty.\n");
+  exit (0);
+}
+
+static void
+usage (file, status)
+     FILE *file;
+     int status;
+{
+  fprintf (file, "Usage %s <options> <object-files>\n", program_name);
+  fprintf (file, "  Generic options:\n");
+  fprintf (file, "   --quiet, -q            Work quietly\n");
+  fprintf (file, "   --verbose, -v          Verbose\n");
+  fprintf (file, "   --version              Print dllwrap version\n");
+  fprintf (file, "   --implib <outname>     Synonym for --output-lib\n");
+  fprintf (file, "  Options for %s:\n", program_name);
+  fprintf (file, "   --driver-name <driver> Defaults to \"gcc\"\n");
+  fprintf (file, "   --driver-flags <flags> Override default ld flags\n");
+  fprintf (file, "   --dlltool-name <dlltool> Defaults to \"dlltool\"\n");
+  fprintf (file, "   --entry <entry>        Specify alternate DLL entry point\n");
+  fprintf (file, "   --image-base <base>    Specify image base address\n");
+  fprintf (file, "   --target <machine>     i386-cygwin32 or i386-mingw32\n");
+  fprintf (file, "   --dry-run              Show what needs to be run\n");
+  fprintf (file, "  Options passed to DLLTOOL:\n");
+  fprintf (file, "   --machine <machine>\n");
+  fprintf (file, "   --output-exp <outname> Generate export file.\n");
+  fprintf (file, "   --output-lib <outname> Generate input library.\n");
+  fprintf (file, "   --add-indirect         Add dll indirects to export file.\n");
+  fprintf (file, "   --dllname <name>       Name of input dll to put into output lib.\n");
+  fprintf (file, "   --def <deffile>        Name input .def file\n");
+  fprintf (file, "   --output-def <deffile> Name output .def file\n");
+  fprintf (file, "   --export-all-symbols     Export all symbols to .def\n");
+  fprintf (file, "   --no-export-all-symbols  Only export .drectve symbols\n");
+  fprintf (file, "   --exclude-symbols <list> Exclude <list> from .def\n");
+  fprintf (file, "   --no-default-excludes    Zap default exclude symbols\n");
+  fprintf (file, "   --base-file <basefile> Read linker generated base file\n");
+  fprintf (file, "   --no-idata4           Don't generate idata$4 section\n");
+  fprintf (file, "   --no-idata5           Don't generate idata$5 section\n");
+  fprintf (file, "   -U                     Add underscores to .lib\n");
+  fprintf (file, "   -k                     Kill @<n> from exported names\n");
+  fprintf (file, "   --add-stdcall-alias    Add aliases without @<n>\n");
+  fprintf (file, "   --as <name>            Use <name> for assembler\n");
+  fprintf (file, "   --nodelete             Keep temp files.\n");
+  fprintf (file, "  Rest are passed unmodified to the language driver\n");
+  fprintf (file, "\n\n");
+  exit (status);
+}
+
+#define OPTION_START           149
+
+/* GENERIC options. */
+#define OPTION_QUIET           (OPTION_START + 1)
+#define OPTION_VERBOSE         (OPTION_QUIET + 1)
+#define OPTION_VERSION         (OPTION_VERBOSE + 1)
+
+/* DLLWRAP options. */
+#define OPTION_DRY_RUN         (OPTION_VERSION + 1)
+#define OPTION_DRIVER_NAME     (OPTION_DRY_RUN + 1)
+#define OPTION_DRIVER_FLAGS    (OPTION_DRIVER_NAME + 1)
+#define OPTION_DLLTOOL_NAME    (OPTION_DRIVER_FLAGS + 1)
+#define OPTION_ENTRY           (OPTION_DLLTOOL_NAME + 1)
+#define OPTION_IMAGE_BASE      (OPTION_ENTRY + 1)
+#define OPTION_TARGET          (OPTION_IMAGE_BASE + 1)
+
+/* DLLTOOL options. */
+#define OPTION_NODELETE                (OPTION_TARGET + 1)
+#define OPTION_DLLNAME         (OPTION_NODELETE + 1)
+#define OPTION_NO_IDATA4       (OPTION_DLLNAME + 1)
+#define OPTION_NO_IDATA5       (OPTION_NO_IDATA4 + 1)
+#define OPTION_OUTPUT_EXP      (OPTION_NO_IDATA5 + 1)
+#define OPTION_OUTPUT_DEF      (OPTION_OUTPUT_EXP + 1)
+#define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1)
+#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
+#define OPTION_EXCLUDE_SYMS    (OPTION_NO_EXPORT_ALL_SYMS + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
+#define OPTION_OUTPUT_LIB      (OPTION_NO_DEFAULT_EXCLUDES + 1)
+#define OPTION_DEF             (OPTION_OUTPUT_LIB + 1)
+#define OPTION_ADD_UNDERSCORE  (OPTION_DEF + 1)
+#define OPTION_KILLAT          (OPTION_ADD_UNDERSCORE + 1)
+#define OPTION_HELP            (OPTION_KILLAT + 1)
+#define OPTION_MACHINE         (OPTION_HELP + 1)
+#define OPTION_ADD_INDIRECT    (OPTION_MACHINE + 1)
+#define OPTION_BASE_FILE       (OPTION_ADD_INDIRECT + 1)
+#define OPTION_AS              (OPTION_BASE_FILE + 1)
+
+static const struct option long_options[] =
+{
+  /* generic options. */
+  {"quiet", no_argument, NULL, 'q'},
+  {"verbose", no_argument, NULL, 'v'},
+  {"version", no_argument, NULL, OPTION_VERSION},
+  {"implib", required_argument, NULL, OPTION_OUTPUT_LIB},
+
+  /* dllwrap options. */
+  {"dry-run", no_argument, NULL, OPTION_DRY_RUN},
+  {"driver-name", required_argument, NULL, OPTION_DRIVER_NAME},
+  {"driver-flags", required_argument, NULL, OPTION_DRIVER_FLAGS},
+  {"dlltool-name", required_argument, NULL, OPTION_DLLTOOL_NAME},
+  {"entry", required_argument, NULL, 'e'},
+  {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
+  {"target", required_argument, NULL, OPTION_TARGET},
+
+  /* dlltool options. */
+  {"no-delete", no_argument, NULL, 'n'},
+  {"dllname", required_argument, NULL, OPTION_DLLNAME},
+  {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
+  {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
+  {"output-exp", required_argument, NULL, OPTION_OUTPUT_EXP},
+  {"output-def", required_argument, NULL, OPTION_OUTPUT_DEF},
+  {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
+  {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
+  {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
+  {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
+  {"output-lib", required_argument, NULL, OPTION_OUTPUT_LIB},
+  {"def", required_argument, NULL, OPTION_DEF},
+  {"add-underscore", no_argument, NULL, 'U'},
+  {"killat", no_argument, NULL, 'k'},
+  {"add-stdcall-alias", no_argument, NULL, 'A'},
+  {"help", no_argument, NULL, 'h'},
+  {"machine", required_argument, NULL, OPTION_MACHINE},
+  {"add-indirect", no_argument, NULL, OPTION_ADD_INDIRECT},
+  {"base-file", required_argument, NULL, OPTION_BASE_FILE},
+  {"as", required_argument, NULL, OPTION_AS},
+  {0}
+};
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int i;
+
+  char **saved_argv = 0;
+  int cmdline_len = 0;
+
+  int export_all = 0;
+
+  int *dlltool_arg_indices;
+  int *driver_arg_indices;
+
+  char *driver_flags = 0;
+  char *output_lib_file_name = 0;
+
+  dyn_string_t dlltool_cmdline;
+  dyn_string_t driver_cmdline;
+
+  int def_file_seen = 0;
+
+  char *image_base_str = 0;
+
+  program_name = argv[0];
+
+  saved_argv = (char **) xmalloc (argc * sizeof (char*));
+  dlltool_arg_indices = (int *) xmalloc (argc * sizeof (int));
+  driver_arg_indices = (int *) xmalloc (argc * sizeof (int));
+  for (i = 0; i < argc; ++i) 
+    {
+      size_t len = strlen (argv[i]);
+      char *arg = (char *) xmalloc (len + 1);
+      strcpy (arg, argv[i]);
+      cmdline_len += len;
+      saved_argv[i] = arg;
+      dlltool_arg_indices[i] = 0;
+      driver_arg_indices[i] = 1;
+    }
+  cmdline_len++;
+
+  /* We recognize dllwrap and dlltool options, and everything else is
+     passed onto the language driver (eg., to GCC). We collect options
+     to dlltool and driver in dlltool_args and driver_args. */
+   
+  opterr = 0;
+  while ((c = getopt_long_only (argc, argv, "nkAqve:Uho:l:L:I:", 
+                                long_options, (int *) 0)) != EOF)
+    {
+      int dlltool_arg;
+      int driver_arg;
+      int single_word_option_value_pair;
+
+      dlltool_arg = 0;
+      driver_arg = 1;
+      single_word_option_value_pair = 0;
+
+      if (c != '?')
+        {
+         /* We recognize this option, so it has to be either dllwrap or
+            dlltool option. Do not pass to driver unless it's one of the
+            generic options that are passed to all the tools (such as -v)
+            which are dealt with later. */
+         driver_arg = 0;
+       }
+
+      /* deal with generic and dllwrap options first. */
+      switch (c)
+       {
+       case 'h':
+         usage (stdout, 0);
+         break;
+       case 'q':
+         verbose = 0;
+         break;
+       case 'v':
+         verbose = 1;
+         break;
+       case OPTION_VERSION:
+         print_version (program_name);
+         break;
+       case 'e':
+         entry_point = optarg;
+         break;
+       case OPTION_IMAGE_BASE:
+         image_base_str = optarg;
+         break;
+       case OPTION_DEF:
+         def_file_name = optarg;
+         def_file_seen = 1;
+         delete_def_file = 0;
+         break;
+       case 'n':
+         dontdeltemps = 1;
+         dlltool_arg = 1;
+         break;
+       case 'o':
+         dll_file_name = optarg;
+         break;
+       case 'I':
+       case 'l':
+       case 'L':
+         driver_arg = 1;
+         break;
+       case OPTION_DLLNAME:
+         dll_name = optarg;
+         break;
+       case OPTION_DRY_RUN:
+         dry_run = 1;
+         break;
+       case OPTION_DRIVER_NAME:
+         driver_name = optarg;
+         break;
+       case OPTION_DRIVER_FLAGS:
+         driver_flags = optarg;
+         break;
+       case OPTION_DLLTOOL_NAME:
+         dlltool_name = optarg;
+         break;
+       case OPTION_TARGET:
+         target = optarg;
+         break;
+       case OPTION_BASE_FILE:
+         base_file_name = optarg;
+         delete_base_file = 0;
+         break;
+       case OPTION_OUTPUT_EXP:
+         exp_file_name = optarg;
+         delete_exp_file = 0;
+         break;
+       case OPTION_EXPORT_ALL_SYMS:
+         export_all = 1;
+         break;
+       case OPTION_OUTPUT_LIB:
+         output_lib_file_name = optarg;
+         break;
+       case '?':
+         break;
+       default:
+         dlltool_arg = 1;
+         break;
+       }
+      
+      /* Handle passing through --option=value case. */
+      if (optarg 
+          && saved_argv[optind-1][0] == '-' 
+          && saved_argv[optind-1][1] == '-' 
+         && strchr (saved_argv[optind-1], '='))
+       single_word_option_value_pair = 1;
+
+      if (dlltool_arg)
+        {
+         dlltool_arg_indices[optind-1] = 1;
+         if (optarg && ! single_word_option_value_pair)
+           {
+             dlltool_arg_indices[optind-2] = 1;
+           } 
+       }
+
+      if (! driver_arg)
+        {
+         driver_arg_indices[optind-1] = 0;
+         if (optarg && ! single_word_option_value_pair)
+           {
+             driver_arg_indices[optind-2] = 0;
+           } 
+       }
+    }
+  
+  /* sanity checks. */
+  if (! dll_name && ! dll_file_name)
+    {
+      fprintf (stderr,
+               "%s: Must provide at least one of -o or --dllname options\n",
+               program_name);
+      exit (1);
+    }
+  else if (! dll_name)
+    {
+      dll_name = xstrdup (mybasename (dll_file_name));
+    }
+  else if (! dll_file_name)
+    {
+      dll_file_name = xstrdup (dll_name);
+    }
+  
+  if (! def_file_seen)
+    {
+      char *fileprefix = choose_temp_base ();
+      def_file_name = (char *) xmalloc (strlen (fileprefix) + 5);
+      sprintf (def_file_name, "%s.def", 
+               (dontdeltemps) ? mybasename (fileprefix) : fileprefix);
+      delete_def_file = 1;
+      free (fileprefix);
+      delete_def_file = 1;
+      fprintf (stderr, "Warning: no export definition file provided\n");
+      fprintf (stderr, 
+               "dllwrap will create one, but may not be what you want\n");
+    }
+  
+  /* set the target platform. */
+  if (strstr (target, "cygwin32"))
+    which_target = CYGWIN_TARGET;
+  else if (strstr (target, "mingw32"))
+    which_target = MINGW32_TARGET;
+  else 
+    which_target = UNKNOWN_TARGET;
+
+  /* re-create the command lines as a string, taking care to quote stuff. */
+  dlltool_cmdline = dyn_string_new (cmdline_len);
+  if (verbose)
+    {
+      dyn_string_append (dlltool_cmdline, " -v");
+    }
+  dyn_string_append (dlltool_cmdline, " --dllname ");
+  dyn_string_append (dlltool_cmdline, dll_name);
+
+  for (i = 1; i < argc; ++i)
+    {
+      if (dlltool_arg_indices[i])
+        {
+         char *arg = saved_argv[i];
+          int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
+         dyn_string_append (dlltool_cmdline, 
+                            (quote) ? " \"" : " ");
+         dyn_string_append (dlltool_cmdline, arg);
+         dyn_string_append (dlltool_cmdline, 
+                            (quote) ? "\"" : "");
+       }
+    }
+
+  driver_cmdline = dyn_string_new (cmdline_len);
+  if (! driver_flags || strlen (driver_flags) == 0)
+    {
+      switch (which_target)
+        {
+       case CYGWIN_TARGET:
+          driver_flags = cygwin_driver_flags;
+         break;
+       
+       case MINGW32_TARGET:
+          driver_flags = mingw32_driver_flags;
+         break;
+       
+       default:
+          driver_flags = generic_driver_flags;
+         break;
+       }
+    }
+  dyn_string_append (driver_cmdline, driver_flags);
+  dyn_string_append (driver_cmdline, " -o ");
+  dyn_string_append (driver_cmdline, dll_file_name);
+
+  if (! entry_point || strlen (entry_point) == 0)
+    {
+      switch (which_target)
+        {
+       case CYGWIN_TARGET:
+         entry_point = "__cygwin_dll_entry@12";
+         break;
+       
+       case MINGW32_TARGET:
+         entry_point = "_DllMainCRTStartup@12";
+         break;
+       
+       default:
+          entry_point = "_DllMain@12";
+         break;
+       }
+    }
+  dyn_string_append (driver_cmdline, " -Wl,-e,");
+  dyn_string_append (driver_cmdline, entry_point);
+  dyn_string_append (dlltool_cmdline, " --exclude-symbol=");
+  dyn_string_append (dlltool_cmdline, 
+                     (entry_point[0] == '_') ? entry_point+1 : entry_point);
+
+  if (! image_base_str || strlen (image_base_str) == 0)
+    {
+      char *tmpbuf = (char *) xmalloc (sizeof ("0x12345678") + 1);
+      unsigned long hash = strhash (dll_file_name);
+      sprintf (tmpbuf, "0x%.8lX", 0x60000000|((hash<<16)&0xFFC0000));
+      image_base_str = tmpbuf;
+    }
+
+  dyn_string_append (driver_cmdline, " -Wl,--image-base,");
+  dyn_string_append (driver_cmdline, image_base_str);
+
+  if (verbose)
+    {
+      dyn_string_append (driver_cmdline, " -v");
+    }
+
+  for (i = 1; i < argc; ++i)
+    {
+      if (driver_arg_indices[i])
+        {
+         char *arg = saved_argv[i];
+          int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
+         dyn_string_append (driver_cmdline, 
+                            (quote) ? " \"" : " ");
+         dyn_string_append (driver_cmdline, arg);
+         dyn_string_append (driver_cmdline, 
+                            (quote) ? "\"" : "");
+       }
+    }
+  
+  /*
+   * Step pre-1. If no --def <EXPORT_DEF> is specified, then create it
+   * and then pass it on.
+   */
+  
+  if (! def_file_seen) 
+    {
+      int i;
+      dyn_string_t step_pre1;
+
+      step_pre1 = dyn_string_new (1024);
+
+      dyn_string_append (step_pre1, dlltool_cmdline->s);
+      if (export_all)
+       {
+          dyn_string_append (step_pre1, " --export-all --exclude-symbol=");
+          dyn_string_append (step_pre1, 
+         "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12");
+       }
+      dyn_string_append (step_pre1, " --output-def ");
+      dyn_string_append (step_pre1, def_file_name);
+
+      for (i = 1; i < argc; ++i)
+       {
+         if (driver_arg_indices[i])
+           {
+             char *arg = saved_argv[i];
+             size_t len = strlen (arg);
+             if (len >= 2 && arg[len-2] == '.' 
+                 && (arg[len-1] == 'o' || arg[len-1] == 'a'))
+               {
+                 int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
+                 dyn_string_append (step_pre1,
+                                    (quote) ? " \"" : " ");
+                 dyn_string_append (step_pre1, arg);
+                 dyn_string_append (step_pre1,
+                                    (quote) ? "\"" : "");
+               }
+           }
+       }
+
+      if (run (dlltool_name, step_pre1->s))
+       cleanup_and_exit (1);
+      
+      dyn_string_delete (step_pre1);
+    }
+
+  dyn_string_append (dlltool_cmdline, " --def ");
+  dyn_string_append (dlltool_cmdline, def_file_name);
+
+  if (verbose)
+    {
+      fprintf (stderr, "DLLTOOL name    : %s\n", dlltool_name);
+      fprintf (stderr, "DLLTOOL options : %s\n", dlltool_cmdline->s);
+      fprintf (stderr, "DRIVER name     : %s\n", driver_name);
+      fprintf (stderr, "DRIVER options  : %s\n", driver_cmdline->s);
+    }
+  /*
+   * Step 1. Call GCC/LD to create base relocation file. If using GCC, the
+   * driver command line will look like the following:
+   *    
+   *    % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
+   *
+   * If the user does not specify a base name, create temporary one that
+   * is deleted at exit.
+   *
+   */
+  
+  if (! base_file_name)
+    {
+      char *fileprefix = choose_temp_base ();
+      base_file_name = (char *) xmalloc (strlen (fileprefix) + 6);
+      sprintf (base_file_name, "%s.base", 
+               (dontdeltemps) ? mybasename (fileprefix) : fileprefix);
+      delete_base_file = 1;
+      free (fileprefix);
+    }
+  
+  {
+    int quote;
+
+    dyn_string_t step1 = dyn_string_new (driver_cmdline->length 
+                                         + strlen (base_file_name)
+                                        + 20);
+    dyn_string_append (step1, "-Wl,--base-file,");
+    quote = (strchr (base_file_name, ' ') 
+             || strchr (base_file_name, '\t'));
+    dyn_string_append (step1, 
+                      (quote) ? "\"" : "");
+    dyn_string_append (step1, base_file_name);
+    dyn_string_append (step1, 
+                      (quote) ? "\"" : "");
+    if (driver_cmdline->length)
+      {
+        dyn_string_append (step1, " ");
+        dyn_string_append (step1, driver_cmdline->s);
+      }
+
+    if (run (driver_name, step1->s))
+      cleanup_and_exit (1);
+    
+    dyn_string_delete (step1);
+  }
+
+
+
+  /*
+   * Step 2. generate the exp file by running dlltool. 
+   * dlltool command line will look like the following:
+   *    
+   *    % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
+   *
+   * If the user does not specify a base name, create temporary one that
+   * is deleted at exit.
+   *
+   */
+  
+  if (! exp_file_name)
+    {
+      char *p = strrchr (dll_name, '.');
+      size_t prefix_len = (p) ? p - dll_name : strlen (dll_name);
+      exp_file_name = (char *) xmalloc (prefix_len + 4 + 1);
+      strncpy (exp_file_name, dll_name, prefix_len);
+      exp_file_name[prefix_len] = '\0';
+      strcat (exp_file_name, ".exp");
+      delete_exp_file = 1;
+    }
+  
+  {
+    int quote;
+    dyn_string_t step2 = dyn_string_new (dlltool_cmdline->length 
+                                         + strlen (base_file_name)
+                                         + strlen (exp_file_name)
+                                        + 20);
+
+    dyn_string_append (step2, "--base-file ");
+    quote = (strchr (base_file_name, ' ') 
+             || strchr (base_file_name, '\t'));
+    dyn_string_append (step2, 
+                      (quote) ? "\"" : "");
+    dyn_string_append (step2, base_file_name);
+    dyn_string_append (step2, 
+                      (quote) ? "\" " : " ");
+
+    dyn_string_append (step2, "--output-exp ");
+    quote = (strchr (exp_file_name, ' ') 
+             || strchr (exp_file_name, '\t'));
+    dyn_string_append (step2, 
+                      (quote) ? "\"" : "");
+    dyn_string_append (step2, exp_file_name);
+    dyn_string_append (step2, 
+                      (quote) ? "\"" : "");
+
+    if (dlltool_cmdline->length)
+      {
+        dyn_string_append (step2, " ");
+        dyn_string_append (step2, dlltool_cmdline->s);
+      }
+
+    if (run (dlltool_name, step2->s))
+      cleanup_and_exit (1);
+    
+    dyn_string_delete (step2);
+  }
+
+  /*
+   * Step 3. Call GCC/LD to again, adding the exp file this time.
+   * driver command line will look like the following:
+   *    
+   *    % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...]
+   */
+
+  {
+    int quote;
+
+    dyn_string_t step3 = dyn_string_new (driver_cmdline->length 
+                                         + strlen (exp_file_name)
+                                         + strlen (base_file_name)
+                                        + 20);
+    dyn_string_append (step3, "-Wl,--base-file,");
+    quote = (strchr (base_file_name, ' ') 
+             || strchr (base_file_name, '\t'));
+    dyn_string_append (step3, 
+                      (quote) ? "\"" : "");
+    dyn_string_append (step3, base_file_name);
+    dyn_string_append (step3, 
+                      (quote) ? "\" " : " ");
+
+    quote = (strchr (exp_file_name, ' ') 
+             || strchr (exp_file_name, '\t'));
+    dyn_string_append (step3, 
+                      (quote) ? "\"" : "");
+    dyn_string_append (step3, exp_file_name);
+    dyn_string_append (step3, 
+                      (quote) ? "\"" : "");
+
+    if (driver_cmdline->length)
+      {
+        dyn_string_append (step3, " ");
+        dyn_string_append (step3, driver_cmdline->s);
+      }
+
+    if (run (driver_name, step3->s))
+      cleanup_and_exit (1);
+    
+    dyn_string_delete (step3);
+  }
+
+
+  /*
+   * Step 4. Run DLLTOOL again using the same command line.
+   */
+
+  {
+    int quote;
+    dyn_string_t step4 = dyn_string_new (dlltool_cmdline->length 
+                                         + strlen (base_file_name)
+                                         + strlen (exp_file_name)
+                                        + 20);
+
+    dyn_string_append (step4, "--base-file ");
+    quote = (strchr (base_file_name, ' ') 
+             || strchr (base_file_name, '\t'));
+    dyn_string_append (step4, 
+                      (quote) ? "\"" : "");
+    dyn_string_append (step4, base_file_name);
+    dyn_string_append (step4, 
+                      (quote) ? "\" " : " ");
+
+    dyn_string_append (step4, "--output-exp ");
+    quote = (strchr (exp_file_name, ' ') 
+             || strchr (exp_file_name, '\t'));
+    dyn_string_append (step4, 
+                      (quote) ? "\"" : "");
+    dyn_string_append (step4, exp_file_name);
+    dyn_string_append (step4, 
+                      (quote) ? "\"" : "");
+
+    if (dlltool_cmdline->length)
+      {
+        dyn_string_append (step4, " ");
+        dyn_string_append (step4, dlltool_cmdline->s);
+      }
+
+    if (output_lib_file_name)
+      {
+        dyn_string_append (step4, " --output-lib ");
+        dyn_string_append (step4, output_lib_file_name);
+      }
+
+    if (run (dlltool_name, step4->s))
+      cleanup_and_exit (1);
+    
+    dyn_string_delete (step4);
+  }
+  
+
+  /*
+   * Step 5. Link it all together and be done with it.
+   * driver command line will look like the following:
+   *    
+   *    % gcc -Wl,--dll foo.exp [rest ...]
+   *
+   */
+
+  {
+    int quote;
+
+    dyn_string_t step5 = dyn_string_new (driver_cmdline->length 
+                                         + strlen (exp_file_name)
+                                        + 20);
+    quote = (strchr (exp_file_name, ' ') 
+             || strchr (exp_file_name, '\t'));
+    dyn_string_append (step5, 
+                      (quote) ? "\"" : "");
+    dyn_string_append (step5, exp_file_name);
+    dyn_string_append (step5, 
+                      (quote) ? "\"" : "");
+
+    if (driver_cmdline->length)
+      {
+        dyn_string_append (step5, " ");
+        dyn_string_append (step5, driver_cmdline->s);
+      }
+
+    if (run (driver_name, step5->s))
+      cleanup_and_exit (1);
+    
+    dyn_string_delete (step5);
+  }
+
+  cleanup_and_exit (0);
+
+  return 0;
+}
diff --git a/binutils/dyn-string.c b/binutils/dyn-string.c
new file mode 100644 (file)
index 0000000..a4a3043
--- /dev/null
@@ -0,0 +1,107 @@
+/* An abstract string datatype.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   Contributed by Mark Mitchell (mark@markmitchell.com).
+
+   This file is part of GNU CC.
+   
+   GNU CC 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 2, or (at your option)
+   any later version.
+
+   GNU CC 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 GNU CC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This file lives in at least two places: binutils and gcc.
+   Don't change one without the other.  */
+
+#include "config.h"
+#ifdef IN_GCC
+#include "system.h"
+#include "gansidecl.h"
+#else
+#include "ansidecl.h"
+#endif
+#include "dyn-string.h"
+
+extern char *xmalloc ();
+extern char *xrealloc ();
+
+/* Create a new dynamic string capable of holding at least SPACE
+   characters, including the terminating NUL.  If SPACE is 0, it
+   will be silently increased to 1.  */
+
+dyn_string_t 
+dyn_string_new (space)
+     int space;
+{
+  dyn_string_t result = (dyn_string_t) xmalloc (sizeof (struct dyn_string));
+  if (space == 0)
+    /* We need at least one byte in which to store the terminating
+       NUL.  */
+    space = 1;
+
+  result->allocated = space;
+  result->s = (char*) xmalloc (space);
+  result->length = 0;
+  result->s[0] = '\0';
+
+  return result;
+}
+
+/* Free the memory used by DS.  */
+
+void 
+dyn_string_delete (ds)
+     dyn_string_t ds;
+{
+  free (ds->s);
+  free (ds);
+}
+
+/* Append the NUL-terminated string S to DS, resizing DS if
+   necessary.  */
+
+dyn_string_t 
+dyn_string_append (ds, s)
+     dyn_string_t ds;
+     char *s;
+{
+  int len = strlen (s);
+  dyn_string_resize (ds, ds->length + len + 1 /* '\0' */);
+  strcpy (ds->s + ds->length, s);
+  ds->length += len;
+
+  return ds;
+}
+
+/* Increase the capacity of DS so that it can hold at least SPACE
+   characters, including the terminating NUL.  This function will not
+   (at present) reduce the capacity of DS.  */
+
+dyn_string_t 
+dyn_string_resize (ds, space)
+     dyn_string_t ds;
+     int space;
+{
+  int new_allocated = ds->allocated;
+
+  while (space > new_allocated)
+    new_allocated *= 2;
+    
+  if (new_allocated != ds->allocated)
+    {
+      /* We actually need more space.  */
+      ds->allocated = new_allocated;
+      ds->s = (char*) xrealloc (ds->s, ds->allocated);
+    }
+
+  return ds;
+}
diff --git a/binutils/dyn-string.h b/binutils/dyn-string.h
new file mode 100644 (file)
index 0000000..a22bbbf
--- /dev/null
@@ -0,0 +1,34 @@
+/* An abstract string datatype.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   Contributed by Mark Mitchell (mark@markmitchell.com).
+
+   This file is part of GNU CC.
+   
+   GNU CC 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 2, or (at your option)
+   any later version.
+
+   GNU CC 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 GNU CC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This file lives in at least two places: binutils and gcc.
+   Don't change one without the other.  */
+
+typedef struct dyn_string
+{
+  int allocated; /* The amount of space allocated for the string.  */
+  int length; /* The actual length of the string.  */
+  char *s; /* The string itself, NUL-terminated.  */
+}* dyn_string_t;
+
+extern dyn_string_t dyn_string_new      PARAMS((int));
+extern void dyn_string_delete           PARAMS((dyn_string_t));
+extern dyn_string_t dyn_string_append   PARAMS((dyn_string_t, char*));
+extern dyn_string_t dyn_string_resize   PARAMS((dyn_string_t, int));
diff --git a/binutils/filemode.c b/binutils/filemode.c
new file mode 100644 (file)
index 0000000..58b52ba
--- /dev/null
@@ -0,0 +1,266 @@
+/* filemode.c -- make a string describing file modes
+   Copyright (C) 1985, 90, 91, 94, 95, 1997 Free Software Foundation, Inc.
+
+   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 2, 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+\f
+#include "bfd.h"
+#include "bucomm.h"
+
+static char ftypelet PARAMS ((unsigned long));
+static void setst PARAMS ((unsigned long, char *));
+
+/* filemodestring - fill in string STR with an ls-style ASCII
+   representation of the st_mode field of file stats block STATP.
+   10 characters are stored in STR; no terminating null is added.
+   The characters stored in STR are:
+
+   0   File type.  'd' for directory, 'c' for character
+       special, 'b' for block special, 'm' for multiplex,
+       'l' for symbolic link, 's' for socket, 'p' for fifo,
+       '-' for any other file type
+
+   1   'r' if the owner may read, '-' otherwise.
+
+   2   'w' if the owner may write, '-' otherwise.
+
+   3   'x' if the owner may execute, 's' if the file is
+       set-user-id, '-' otherwise.
+       'S' if the file is set-user-id, but the execute
+       bit isn't set.
+
+   4   'r' if group members may read, '-' otherwise.
+
+   5   'w' if group members may write, '-' otherwise.
+
+   6   'x' if group members may execute, 's' if the file is
+       set-group-id, '-' otherwise.
+       'S' if it is set-group-id but not executable.
+
+   7   'r' if any user may read, '-' otherwise.
+
+   8   'w' if any user may write, '-' otherwise.
+
+   9   'x' if any user may execute, 't' if the file is "sticky"
+       (will be retained in swap space after execution), '-'
+       otherwise.
+       'T' if the file is sticky but not executable. */
+
+#if 0
+
+/* This is not used; only mode_string is used.  */
+
+void
+filemodestring (statp, str)
+     struct stat *statp;
+     char *str;
+{
+  mode_string ((unsigned long) statp->st_mode, str);
+}
+
+#endif
+
+/* Get definitions for the file permission bits.  */
+
+#ifndef S_IRWXU
+#define S_IRWXU 0700
+#endif
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 0200
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR 0100
+#endif
+
+#ifndef S_IRWXG
+#define S_IRWXG 0070
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 0040
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 0020
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010
+#endif
+
+#ifndef S_IRWXO
+#define S_IRWXO 0007
+#endif
+#ifndef S_IROTH
+#define S_IROTH 0004
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 0002
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001
+#endif
+
+/* Like filemodestring, but only the relevant part of the `struct stat'
+   is given as an argument. */
+
+void
+mode_string (mode, str)
+     unsigned long mode;
+     char *str;
+{
+  str[0] = ftypelet ((unsigned long) mode);
+  str[1] = (mode & S_IRUSR) != 0 ? 'r' : '-';
+  str[2] = (mode & S_IWUSR) != 0 ? 'w' : '-';
+  str[3] = (mode & S_IXUSR) != 0 ? 'x' : '-';
+  str[4] = (mode & S_IRGRP) != 0 ? 'r' : '-';
+  str[5] = (mode & S_IWGRP) != 0 ? 'w' : '-';
+  str[6] = (mode & S_IXGRP) != 0 ? 'x' : '-';
+  str[7] = (mode & S_IROTH) != 0 ? 'r' : '-';
+  str[8] = (mode & S_IWOTH) != 0 ? 'w' : '-';
+  str[9] = (mode & S_IXOTH) != 0 ? 'x' : '-';
+  setst ((unsigned long) mode, str);
+}
+
+/* Return a character indicating the type of file described by
+   file mode BITS:
+   'd' for directories
+   'b' for block special files
+   'c' for character special files
+   'm' for multiplexor files
+   'l' for symbolic links
+   's' for sockets
+   'p' for fifos
+   '-' for any other file type. */
+
+#ifndef S_ISDIR
+#ifdef S_IFDIR
+#define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR)
+#else /* ! defined (S_IFDIR) */
+#define S_ISDIR(i) (((i) & 0170000) == 040000)
+#endif /* ! defined (S_IFDIR) */
+#endif /* ! defined (S_ISDIR) */
+
+#ifndef S_ISBLK
+#ifdef S_IFBLK
+#define S_ISBLK(i) (((i) & S_IFMT) == S_IFBLK)
+#else /* ! defined (S_IFBLK) */
+#define S_ISBLK(i) 0
+#endif /* ! defined (S_IFBLK) */
+#endif /* ! defined (S_ISBLK) */
+
+#ifndef S_ISCHR
+#ifdef S_IFCHR
+#define S_ISCHR(i) (((i) & S_IFMT) == S_IFCHR)
+#else /* ! defined (S_IFCHR) */
+#define S_ISCHR(i) 0
+#endif /* ! defined (S_IFCHR) */
+#endif /* ! defined (S_ISCHR) */
+
+#ifndef S_ISFIFO
+#ifdef S_IFIFO
+#define S_ISFIFO(i) (((i) & S_IFMT) == S_IFIFO)
+#else /* ! defined (S_IFIFO) */
+#define S_ISFIFO(i) 0
+#endif /* ! defined (S_IFIFO) */
+#endif /* ! defined (S_ISFIFO) */
+
+#ifndef S_ISSOCK
+#ifdef S_IFSOCK
+#define S_ISSOCK(i) (((i) & S_IFMT) == S_IFSOCK)
+#else /* ! defined (S_IFSOCK) */
+#define S_ISSOCK(i) 0
+#endif /* ! defined (S_IFSOCK) */
+#endif /* ! defined (S_ISSOCK) */
+
+#ifndef S_ISLNK
+#ifdef S_IFLNK
+#define S_ISLNK(i) (((i) & S_IFMT) == S_IFLNK)
+#else /* ! defined (S_IFLNK) */
+#define S_ISLNK(i) 0
+#endif /* ! defined (S_IFLNK) */
+#endif /* ! defined (S_ISLNK) */
+
+static char
+ftypelet (bits)
+     unsigned long bits;
+{
+  if (S_ISDIR (bits))
+    return 'd';
+  if (S_ISLNK (bits))
+    return 'l';
+  if (S_ISBLK (bits))
+    return 'b';
+  if (S_ISCHR (bits))
+    return 'c';
+  if (S_ISSOCK (bits))
+    return 's';
+  if (S_ISFIFO (bits))
+    return 'p';
+
+#ifdef S_IFMT
+#ifdef S_IFMPC
+  if ((bits & S_IFMT) == S_IFMPC
+      || (bits & S_IFMT) == S_IFMPB)
+    return 'm';
+#endif
+#ifdef S_IFNWK
+  if ((bits & S_IFMT) == S_IFNWK)
+    return 'n';
+#endif
+#endif
+
+  return '-';
+}
+
+/* Set the 's' and 't' flags in file attributes string CHARS,
+   according to the file mode BITS. */
+
+static void
+setst (bits, chars)
+     unsigned long bits;
+     char *chars;
+{
+#ifdef S_ISUID
+  if (bits & S_ISUID)
+    {
+      if (chars[3] != 'x')
+       /* Set-uid, but not executable by owner. */
+       chars[3] = 'S';
+      else
+       chars[3] = 's';
+    }
+#endif
+#ifdef S_ISGID
+  if (bits & S_ISGID)
+    {
+      if (chars[6] != 'x')
+       /* Set-gid, but not executable by group. */
+       chars[6] = 'S';
+      else
+       chars[6] = 's';
+    }
+#endif
+#ifdef S_ISVTX
+  if (bits & S_ISVTX)
+    {
+      if (chars[9] != 'x')
+       /* Sticky, but not executable by others. */
+       chars[9] = 'T';
+      else
+       chars[9] = 't';
+    }
+#endif
+}
diff --git a/binutils/ieee.c b/binutils/ieee.c
new file mode 100644 (file)
index 0000000..17a5b88
--- /dev/null
@@ -0,0 +1,7609 @@
+/* ieee.c -- Read and write IEEE-695 debugging information.
+   Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file reads and writes IEEE-695 debugging information.  */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "bfd.h"
+#include "ieee.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* This structure holds an entry on the block stack.  */
+
+struct ieee_block
+{
+  /* The kind of block.  */
+  int kind;
+  /* The source file name, for a BB5 block.  */
+  const char *filename;
+  /* The index of the function type, for a BB4 or BB6 block.  */
+  unsigned int fnindx;
+  /* True if this function is being skipped.  */
+  boolean skip;
+};
+
+/* This structure is the block stack.  */
+
+#define BLOCKSTACK_SIZE (16)
+
+struct ieee_blockstack
+{
+  /* The stack pointer.  */
+  struct ieee_block *bsp;
+  /* The stack.  */
+  struct ieee_block stack[BLOCKSTACK_SIZE];
+};
+
+/* This structure holds information for a variable.  */
+
+struct ieee_var
+{
+  /* Start of name.  */
+  const char *name;
+  /* Length of name.  */
+  unsigned long namlen;
+  /* Type.  */
+  debug_type type;
+  /* Slot if we make an indirect type.  */
+  debug_type *pslot;
+  /* Kind of variable or function.  */
+  enum
+    {
+      IEEE_UNKNOWN,
+      IEEE_EXTERNAL,
+      IEEE_GLOBAL,
+      IEEE_STATIC,
+      IEEE_LOCAL,
+      IEEE_FUNCTION
+    } kind;
+};
+
+/* This structure holds all the variables.  */
+
+struct ieee_vars
+{
+  /* Number of slots allocated.  */
+  unsigned int alloc;
+  /* Variables.  */
+  struct ieee_var *vars;
+};
+
+/* This structure holds information for a type.  We need this because
+   we don't want to represent bitfields as real types.  */
+
+struct ieee_type
+{
+  /* Type.  */
+  debug_type type;
+  /* Slot if this is type is referenced before it is defined.  */
+  debug_type *pslot;
+  /* Slots for arguments if we make indirect types for them.  */
+  debug_type *arg_slots;
+  /* If this is a bitfield, this is the size in bits.  If this is not
+     a bitfield, this is zero.  */
+  unsigned long bitsize;
+};
+
+/* This structure holds all the type information.  */
+
+struct ieee_types
+{
+  /* Number of slots allocated.  */
+  unsigned int alloc;
+  /* Types.  */
+  struct ieee_type *types;
+  /* Builtin types.  */
+#define BUILTIN_TYPE_COUNT (60)
+  debug_type builtins[BUILTIN_TYPE_COUNT];
+};
+
+/* This structure holds a linked last of structs with their tag names,
+   so that we can convert them to C++ classes if necessary.  */
+
+struct ieee_tag
+{
+  /* Next tag.  */
+  struct ieee_tag *next;
+  /* This tag name.  */
+  const char *name;
+  /* The type of the tag.  */
+  debug_type type;
+  /* The tagged type is an indirect type pointing at this slot.  */
+  debug_type slot;
+  /* This is an array of slots used when a field type is converted
+     into a indirect type, in case it needs to be later converted into
+     a reference type.  */
+  debug_type *fslots;
+};
+
+/* This structure holds the information we pass around to the parsing
+   functions.  */
+
+struct ieee_info
+{
+  /* The debugging handle.  */
+  PTR dhandle;
+  /* The BFD.  */
+  bfd *abfd;
+  /* The start of the bytes to be parsed.  */
+  const bfd_byte *bytes;
+  /* The end of the bytes to be parsed.  */
+  const bfd_byte *pend;
+  /* The block stack.  */
+  struct ieee_blockstack blockstack;
+  /* Whether we have seen a BB1 or BB2.  */
+  boolean saw_filename;
+  /* The variables.  */
+  struct ieee_vars vars;
+  /* The global variables, after a global typedef block.  */
+  struct ieee_vars *global_vars;
+  /* The types.  */
+  struct ieee_types types;
+  /* The global types, after a global typedef block.  */
+  struct ieee_types *global_types;
+  /* The list of tagged structs.  */
+  struct ieee_tag *tags;
+};
+
+/* Basic builtin types, not including the pointers.  */
+
+enum builtin_types
+{
+  builtin_unknown = 0,
+  builtin_void = 1,
+  builtin_signed_char = 2,
+  builtin_unsigned_char = 3,
+  builtin_signed_short_int = 4,
+  builtin_unsigned_short_int = 5,
+  builtin_signed_long = 6,
+  builtin_unsigned_long = 7,
+  builtin_signed_long_long = 8,
+  builtin_unsigned_long_long = 9,
+  builtin_float = 10,
+  builtin_double = 11,
+  builtin_long_double = 12,
+  builtin_long_long_double = 13,
+  builtin_quoted_string = 14,
+  builtin_instruction_address = 15,
+  builtin_int = 16,
+  builtin_unsigned = 17,
+  builtin_unsigned_int = 18,
+  builtin_char = 19,
+  builtin_long = 20,
+  builtin_short = 21,
+  builtin_unsigned_short = 22,
+  builtin_short_int = 23,
+  builtin_signed_short = 24,
+  builtin_bcd_float = 25
+};
+
+/* These are the values found in the derivation flags of a 'b'
+   component record of a 'T' type extension record in a C++ pmisc
+   record.  These are bitmasks.  */
+
+/* Set for a private base class, clear for a public base class.
+   Protected base classes are not supported.  */
+#define BASEFLAGS_PRIVATE (0x1)
+/* Set for a virtual base class.  */
+#define BASEFLAGS_VIRTUAL (0x2)
+/* Set for a friend class, clear for a base class.  */
+#define BASEFLAGS_FRIEND (0x10)
+
+/* These are the values found in the specs flags of a 'd', 'm', or 'v'
+   component record of a 'T' type extension record in a C++ pmisc
+   record.  The same flags are used for a 'M' record in a C++ pmisc
+   record.  */
+
+/* The lower two bits hold visibility information.  */
+#define CXXFLAGS_VISIBILITY (0x3)
+/* This value in the lower two bits indicates a public member.  */
+#define CXXFLAGS_VISIBILITY_PUBLIC (0x0)
+/* This value in the lower two bits indicates a private member.  */
+#define CXXFLAGS_VISIBILITY_PRIVATE (0x1)
+/* This value in the lower two bits indicates a protected member.  */
+#define CXXFLAGS_VISIBILITY_PROTECTED (0x2)
+/* Set for a static member.  */
+#define CXXFLAGS_STATIC (0x4)
+/* Set for a virtual override.  */
+#define CXXFLAGS_OVERRIDE (0x8)
+/* Set for a friend function.  */
+#define CXXFLAGS_FRIEND (0x10)
+/* Set for a const function.  */
+#define CXXFLAGS_CONST (0x20)
+/* Set for a volatile function.  */
+#define CXXFLAGS_VOLATILE (0x40)
+/* Set for an overloaded function.  */
+#define CXXFLAGS_OVERLOADED (0x80)
+/* Set for an operator function.  */
+#define CXXFLAGS_OPERATOR (0x100)
+/* Set for a constructor or destructor.  */
+#define CXXFLAGS_CTORDTOR (0x400)
+/* Set for a constructor.  */
+#define CXXFLAGS_CTOR (0x200)
+/* Set for an inline function.  */
+#define CXXFLAGS_INLINE (0x800)
+
+/* Local functions.  */
+
+static void ieee_error
+  PARAMS ((struct ieee_info *, const bfd_byte *, const char *));
+static void ieee_eof PARAMS ((struct ieee_info *));
+static char *savestring PARAMS ((const char *, unsigned long));
+static boolean ieee_read_number
+  PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static boolean ieee_read_optional_number
+  PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *, boolean *));
+static boolean ieee_read_id
+  PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+          unsigned long *));
+static boolean ieee_read_optional_id
+  PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+          unsigned long *, boolean *));
+static boolean ieee_read_expression
+  PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static debug_type ieee_builtin_type
+  PARAMS ((struct ieee_info *, const bfd_byte *, unsigned int));
+static boolean ieee_alloc_type
+  PARAMS ((struct ieee_info *, unsigned int, boolean));
+static boolean ieee_read_type_index
+  PARAMS ((struct ieee_info *, const bfd_byte **, debug_type *));
+static int ieee_regno_to_genreg PARAMS ((bfd *, int));
+static int ieee_genreg_to_regno PARAMS ((bfd *, int));
+static boolean parse_ieee_bb PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_be PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_nn PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_ty PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean parse_ieee_atn PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean ieee_read_cxx_misc
+  PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_cxx_class
+  PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_cxx_defaults
+  PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long));
+static boolean ieee_read_reference
+  PARAMS ((struct ieee_info *, const bfd_byte **));
+static boolean ieee_require_asn
+  PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *));
+static boolean ieee_require_atn65
+  PARAMS ((struct ieee_info *, const bfd_byte **, const char **,
+          unsigned long *));
+
+/* Report an error in the IEEE debugging information.  */
+
+static void
+ieee_error (info, p, s)
+     struct ieee_info *info;
+     const bfd_byte *p;
+     const char *s;
+{
+  if (p != NULL)
+    fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd),
+            (unsigned long) (p - info->bytes), s, *p);
+  else
+    fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s);
+}
+
+/* Report an unexpected EOF in the IEEE debugging information.  */
+
+static void
+ieee_eof (info)
+     struct ieee_info *info;
+{
+  ieee_error (info, (const bfd_byte *) NULL,
+             _("unexpected end of debugging information"));
+}
+
+/* Save a string in memory.  */
+
+static char *
+savestring (start, len)
+     const char *start;
+     unsigned long len;
+{
+  char *ret;
+
+  ret = (char *) xmalloc (len + 1);
+  memcpy (ret, start, len);
+  ret[len] = '\0';
+  return ret;
+}
+
+/* Read a number which must be present in an IEEE file.  */
+
+static boolean
+ieee_read_number (info, pp, pv)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     bfd_vma *pv;
+{
+  return ieee_read_optional_number (info, pp, pv, (boolean *) NULL);
+}
+
+/* Read a number in an IEEE file.  If ppresent is not NULL, the number
+   need not be there. */
+
+static boolean
+ieee_read_optional_number (info, pp, pv, ppresent)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     bfd_vma *pv;
+     boolean *ppresent;
+{
+  ieee_record_enum_type b;
+
+  if (*pp >= info->pend)
+    {
+      if (ppresent != NULL)
+       {
+         *ppresent = false;
+         return true;
+       }
+      ieee_eof (info);
+      return false;
+    }
+
+  b = (ieee_record_enum_type) **pp;
+  ++*pp;
+
+  if (b <= ieee_number_end_enum)
+    {
+      *pv = (bfd_vma) b;
+      if (ppresent != NULL)
+       *ppresent = true;
+      return true;
+    }
+
+  if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum)
+    {
+      unsigned int i;
+
+      i = (int) b - (int) ieee_number_repeat_start_enum;
+      if (*pp + i - 1 >= info->pend)
+       {
+         ieee_eof (info);
+         return false;
+       }
+
+      *pv = 0;
+      for (; i > 0; i--)
+       {
+         *pv <<= 8;
+         *pv += **pp;
+         ++*pp;
+       }
+
+      if (ppresent != NULL)
+       *ppresent = true;
+
+      return true;
+    }
+
+  if (ppresent != NULL)
+    {
+      --*pp;
+      *ppresent = false;
+      return true;
+    }
+
+  ieee_error (info, *pp - 1, _("invalid number"));
+  return false;  
+}
+
+/* Read a required string from an IEEE file.  */
+
+static boolean
+ieee_read_id (info, pp, pname, pnamlen)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     const char **pname;
+     unsigned long *pnamlen;
+{
+  return ieee_read_optional_id (info, pp, pname, pnamlen, (boolean *) NULL);
+}
+
+/* Read a string from an IEEE file.  If ppresent is not NULL, the
+   string is optional.  */
+
+static boolean
+ieee_read_optional_id (info, pp, pname, pnamlen, ppresent)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     const char **pname;
+     unsigned long *pnamlen;
+     boolean *ppresent;
+{
+  bfd_byte b;
+  unsigned long len;
+
+  if (*pp >= info->pend)
+    {
+      ieee_eof (info);
+      return false;
+    }
+
+  b = **pp;
+  ++*pp;
+
+  if (b <= 0x7f)
+    len = b;
+  else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum)
+    {
+      len = **pp;
+      ++*pp;
+    }
+  else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum)
+    {
+      len = (**pp << 8) + (*pp)[1];
+      *pp += 2;
+    }
+  else
+    {
+      if (ppresent != NULL)
+       {
+         --*pp;
+         *ppresent = false;
+         return true;
+       }
+      ieee_error (info, *pp - 1, _("invalid string length"));
+      return false;
+    }
+
+  if ((unsigned long) (info->pend - *pp) < len)
+    {
+      ieee_eof (info);
+      return false;
+    }
+
+  *pname = (const char *) *pp;
+  *pnamlen = len;
+  *pp += len;
+
+  if (ppresent != NULL)
+    *ppresent = true;
+
+  return true;
+}
+
+/* Read an expression from an IEEE file.  Since this code is only used
+   to parse debugging information, I haven't bothered to write a full
+   blown IEEE expression parser.  I've only thrown in the things I've
+   seen in debugging information.  This can be easily extended if
+   necessary.  */
+
+static boolean
+ieee_read_expression (info, pp, pv)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     bfd_vma *pv;
+{
+  const bfd_byte *expr_start;
+#define EXPR_STACK_SIZE (10)
+  bfd_vma expr_stack[EXPR_STACK_SIZE];
+  bfd_vma *esp;
+
+  expr_start = *pp;
+
+  esp = expr_stack;
+
+  while (1)
+    {
+      const bfd_byte *start;
+      bfd_vma val;
+      boolean present;
+      ieee_record_enum_type c;
+
+      start = *pp;
+
+      if (! ieee_read_optional_number (info, pp, &val, &present))
+       return false;
+
+      if (present)
+       {
+         if (esp - expr_stack >= EXPR_STACK_SIZE)
+           {
+             ieee_error (info, start, _("expression stack overflow"));
+             return false;
+           }
+         *esp++ = val;
+         continue;
+       }
+
+      c = (ieee_record_enum_type) **pp;
+
+      if (c >= ieee_module_beginning_enum)
+       break;
+
+      ++*pp;
+
+      if (c == ieee_comma)
+       break;
+
+      switch (c)
+       {
+       default:
+         ieee_error (info, start, _("unsupported IEEE expression operator"));
+         break;
+
+       case ieee_variable_R_enum:
+         {
+           bfd_vma indx;
+           asection *s;
+
+           if (! ieee_read_number (info, pp, &indx))
+             return false;
+           for (s = info->abfd->sections; s != NULL; s = s->next)
+             if ((bfd_vma) s->target_index == indx)
+               break;
+           if (s == NULL)
+             {
+               ieee_error (info, start, _("unknown section"));
+               return false;
+             }
+           
+           if (esp - expr_stack >= EXPR_STACK_SIZE)
+             {
+               ieee_error (info, start, _("expression stack overflow"));
+               return false;
+             }
+
+           *esp++ = bfd_get_section_vma (info->abfd, s);
+         }
+         break;
+
+       case ieee_function_plus_enum:
+       case ieee_function_minus_enum:
+         {
+           bfd_vma v1, v2;
+
+           if (esp - expr_stack < 2)
+             {
+               ieee_error (info, start, _("expression stack underflow"));
+               return false;
+             }
+
+           v1 = *--esp;
+           v2 = *--esp;
+           *esp++ = v1 + v2;
+         }
+         break;
+       }
+    }
+
+  if (esp - 1 != expr_stack)
+    {
+      ieee_error (info, expr_start, _("expression stack mismatch"));
+      return false;
+    }
+
+  *pv = *--esp;
+
+  return true;
+}
+
+/* Return an IEEE builtin type.  */
+
+static debug_type
+ieee_builtin_type (info, p, indx)
+     struct ieee_info *info;
+     const bfd_byte *p;
+     unsigned int indx;
+{
+  PTR dhandle;
+  debug_type type;
+  const char *name;
+
+  if (indx < BUILTIN_TYPE_COUNT
+      && info->types.builtins[indx] != DEBUG_TYPE_NULL)
+    return info->types.builtins[indx];
+
+  dhandle = info->dhandle;
+
+  if (indx >= 32 && indx < 64)
+    {
+      type = debug_make_pointer_type (dhandle,
+                                     ieee_builtin_type (info, p, indx - 32));
+      assert (indx < BUILTIN_TYPE_COUNT);
+      info->types.builtins[indx] = type;
+      return type;
+    }
+
+  switch ((enum builtin_types) indx)
+    {
+    default:
+      ieee_error (info, p, _("unknown builtin type"));
+      return NULL;
+
+    case builtin_unknown:
+      type = debug_make_void_type (dhandle);
+      name = NULL;
+      break;
+
+    case builtin_void:
+      type = debug_make_void_type (dhandle);
+      name = "void";
+      break;
+
+    case builtin_signed_char:
+      type = debug_make_int_type (dhandle, 1, false);
+      name = "signed char";
+      break;
+
+    case builtin_unsigned_char:
+      type = debug_make_int_type (dhandle, 1, true);
+      name = "unsigned char";
+      break;
+
+    case builtin_signed_short_int:
+      type = debug_make_int_type (dhandle, 2, false);
+      name = "signed short int";
+      break;
+
+    case builtin_unsigned_short_int:
+      type = debug_make_int_type (dhandle, 2, true);
+      name = "unsigned short int";
+      break;
+
+    case builtin_signed_long:
+      type = debug_make_int_type (dhandle, 4, false);
+      name = "signed long";
+      break;
+
+    case builtin_unsigned_long:
+      type = debug_make_int_type (dhandle, 4, true);
+      name = "unsigned long";
+      break;
+
+    case builtin_signed_long_long:
+      type = debug_make_int_type (dhandle, 8, false);
+      name = "signed long long";
+      break;
+
+    case builtin_unsigned_long_long:
+      type = debug_make_int_type (dhandle, 8, true);
+      name = "unsigned long long";
+      break;
+
+    case builtin_float:
+      type = debug_make_float_type (dhandle, 4);
+      name = "float";
+      break;
+
+    case builtin_double:
+      type = debug_make_float_type (dhandle, 8);
+      name = "double";
+      break;
+
+    case builtin_long_double:
+      /* FIXME: The size for this type should depend upon the
+         processor.  */
+      type = debug_make_float_type (dhandle, 12);
+      name = "long double";
+      break;
+
+    case builtin_long_long_double:
+      type = debug_make_float_type (dhandle, 16);
+      name = "long long double";
+      break;
+
+    case builtin_quoted_string:
+      type = debug_make_array_type (dhandle,
+                                   ieee_builtin_type (info, p,
+                                                      ((unsigned int)
+                                                       builtin_char)),
+                                   ieee_builtin_type (info, p,
+                                                      ((unsigned int)
+                                                       builtin_int)),
+                                   0, -1, true);
+      name = "QUOTED STRING";
+      break;
+
+    case builtin_instruction_address:
+      /* FIXME: This should be a code address.  */
+      type = debug_make_int_type (dhandle, 4, true);
+      name = "instruction address";
+      break;
+
+    case builtin_int:
+      /* FIXME: The size for this type should depend upon the
+         processor.  */
+      type = debug_make_int_type (dhandle, 4, false);
+      name = "int";
+      break;
+
+    case builtin_unsigned:
+      /* FIXME: The size for this type should depend upon the
+         processor.  */
+      type = debug_make_int_type (dhandle, 4, true);
+      name = "unsigned";
+      break;
+
+    case builtin_unsigned_int:
+      /* FIXME: The size for this type should depend upon the
+         processor.  */
+      type = debug_make_int_type (dhandle, 4, true);
+      name = "unsigned int";
+      break;
+
+    case builtin_char:
+      type = debug_make_int_type (dhandle, 1, false);
+      name = "char";
+      break;
+
+    case builtin_long:
+      type = debug_make_int_type (dhandle, 4, false);
+      name = "long";
+      break;
+
+    case builtin_short:
+      type = debug_make_int_type (dhandle, 2, false);
+      name = "short";
+      break;
+
+    case builtin_unsigned_short:
+      type = debug_make_int_type (dhandle, 2, true);
+      name = "unsigned short";
+      break;
+
+    case builtin_short_int:
+      type = debug_make_int_type (dhandle, 2, false);
+      name = "short int";
+      break;
+
+    case builtin_signed_short:
+      type = debug_make_int_type (dhandle, 2, false);
+      name = "signed short";
+      break;
+
+    case builtin_bcd_float:
+      ieee_error (info, p, _("BCD float type not supported"));
+      return false;
+    }
+
+  if (name != NULL)
+    type = debug_name_type (dhandle, name, type);
+
+  assert (indx < BUILTIN_TYPE_COUNT);
+
+  info->types.builtins[indx] = type;
+
+  return type;
+}
+
+/* Allocate more space in the type table.  If ref is true, this is a
+   reference to the type; if it is not already defined, we should set
+   up an indirect type.  */
+
+static boolean
+ieee_alloc_type (info, indx, ref)
+     struct ieee_info *info;
+     unsigned int indx;
+     boolean ref;
+{
+  unsigned int nalloc;
+  register struct ieee_type *t;
+  struct ieee_type *tend;
+
+  if (indx >= info->types.alloc)
+    {
+      nalloc = info->types.alloc;
+      if (nalloc == 0)
+       nalloc = 4;
+      while (indx >= nalloc)
+       nalloc *= 2;
+
+      info->types.types = ((struct ieee_type *)
+                          xrealloc (info->types.types,
+                                    nalloc * sizeof *info->types.types));
+
+      memset (info->types.types + info->types.alloc, 0,
+             (nalloc - info->types.alloc) * sizeof *info->types.types);
+
+      tend = info->types.types + nalloc;
+      for (t = info->types.types + info->types.alloc; t < tend; t++)
+       t->type = DEBUG_TYPE_NULL;
+
+      info->types.alloc = nalloc;
+    }
+
+  if (ref)
+    {
+      t = info->types.types + indx;
+      if (t->type == NULL)
+       {
+         t->pslot = (debug_type *) xmalloc (sizeof *t->pslot);
+         *t->pslot = DEBUG_TYPE_NULL;
+         t->type = debug_make_indirect_type (info->dhandle, t->pslot,
+                                             (const char *) NULL);
+         if (t->type == NULL)
+           return false;
+       }
+    }
+
+  return true;
+}
+
+/* Read a type index and return the corresponding type.  */
+
+static boolean
+ieee_read_type_index (info, pp, ptype)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     debug_type *ptype;
+{
+  const bfd_byte *start;
+  bfd_vma indx;
+
+  start = *pp;
+
+  if (! ieee_read_number (info, pp, &indx))
+    return false;
+
+  if (indx < 256)
+    {
+      *ptype = ieee_builtin_type (info, start, indx);
+      if (*ptype == NULL)
+       return false;
+      return true;
+    }
+
+  indx -= 256;
+  if (! ieee_alloc_type (info, indx, true))
+    return false;
+
+  *ptype = info->types.types[indx].type;
+
+  return true;
+}
+
+/* Parse IEEE debugging information for a file.  This is passed the
+   bytes which compose the Debug Information Part of an IEEE file.  */
+
+boolean
+parse_ieee (dhandle, abfd, bytes, len)
+     PTR dhandle;
+     bfd *abfd;
+     const bfd_byte *bytes;
+     bfd_size_type len;
+{
+  struct ieee_info info;
+  unsigned int i;
+  const bfd_byte *p, *pend;
+
+  info.dhandle = dhandle;
+  info.abfd = abfd;
+  info.bytes = bytes;
+  info.pend = bytes + len;
+  info.blockstack.bsp = info.blockstack.stack;
+  info.saw_filename = false;
+  info.vars.alloc = 0;
+  info.vars.vars = NULL;
+  info.global_vars = NULL;
+  info.types.alloc = 0;
+  info.types.types = NULL;
+  info.global_types = NULL;
+  info.tags = NULL;
+  for (i = 0; i < BUILTIN_TYPE_COUNT; i++)
+    info.types.builtins[i] = DEBUG_TYPE_NULL;
+
+  p = bytes;
+  pend = info.pend;
+  while (p < pend)
+    {
+      const bfd_byte *record_start;
+      ieee_record_enum_type c;
+
+      record_start = p;
+
+      c = (ieee_record_enum_type) *p++;
+
+      if (c == ieee_at_record_enum)
+       c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++);
+
+      if (c <= ieee_number_repeat_end_enum)
+       {
+         ieee_error (&info, record_start, _("unexpected number"));
+         return false;
+       }
+
+      switch (c)
+       {
+       default:
+         ieee_error (&info, record_start, _("unexpected record type"));
+         return false;
+
+       case ieee_bb_record_enum:
+         if (! parse_ieee_bb (&info, &p))
+           return false;
+         break;
+
+       case ieee_be_record_enum:
+         if (! parse_ieee_be (&info, &p))
+           return false;
+         break;
+
+       case ieee_nn_record:
+         if (! parse_ieee_nn (&info, &p))
+           return false;
+         break;
+
+       case ieee_ty_record_enum:
+         if (! parse_ieee_ty (&info, &p))
+           return false;
+         break;
+
+       case ieee_atn_record_enum:
+         if (! parse_ieee_atn (&info, &p))
+           return false;
+         break;
+       }
+    }
+
+  if (info.blockstack.bsp != info.blockstack.stack)
+    {
+      ieee_error (&info, (const bfd_byte *) NULL,
+                 _("blocks left on stack at end"));
+      return false;
+    }
+
+  return true;
+}
+
+/* Handle an IEEE BB record.  */
+
+static boolean
+parse_ieee_bb (info, pp)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+{
+  const bfd_byte *block_start;
+  bfd_byte b;
+  bfd_vma size;
+  const char *name;
+  unsigned long namlen;
+  char *namcopy = NULL;
+  unsigned int fnindx;
+  boolean skip;
+
+  block_start = *pp;
+
+  b = **pp;
+  ++*pp;
+
+  if (! ieee_read_number (info, pp, &size)
+      || ! ieee_read_id (info, pp, &name, &namlen))
+    return false;
+
+  fnindx = (unsigned int) -1;
+  skip = false;
+
+  switch (b)
+    {
+    case 1:
+      /* BB1: Type definitions local to a module.  */
+      namcopy = savestring (name, namlen);
+      if (namcopy == NULL)
+       return false;
+      if (! debug_set_filename (info->dhandle, namcopy))
+       return false;
+      info->saw_filename = true;
+
+      /* Discard any variables or types we may have seen before.  */
+      if (info->vars.vars != NULL)
+       free (info->vars.vars);
+      info->vars.vars = NULL;
+      info->vars.alloc = 0;
+      if (info->types.types != NULL)
+       free (info->types.types);
+      info->types.types = NULL;
+      info->types.alloc = 0;
+
+      /* Initialize the types to the global types.  */
+      if (info->global_types != NULL)
+       {
+         info->types.alloc = info->global_types->alloc;
+         info->types.types = ((struct ieee_type *)
+                              xmalloc (info->types.alloc
+                                       * sizeof (*info->types.types)));
+         memcpy (info->types.types, info->global_types->types,
+                 info->types.alloc * sizeof (*info->types.types));
+       }
+
+      break;
+
+    case 2:
+      /* BB2: Global type definitions.  The name is supposed to be
+        empty, but we don't check. */
+      if (! debug_set_filename (info->dhandle, "*global*"))
+       return false;
+      info->saw_filename = true;
+      break;
+
+    case 3:
+      /* BB3: High level module block begin.  We don't have to do
+        anything here.  The name is supposed to be the same as for
+        the BB1, but we don't check.  */
+      break;
+
+    case 4:
+      /* BB4: Global function.  */
+      {
+       bfd_vma stackspace, typindx, offset;
+       debug_type return_type;
+
+       if (! ieee_read_number (info, pp, &stackspace)
+           || ! ieee_read_number (info, pp, &typindx)
+           || ! ieee_read_expression (info, pp, &offset))
+         return false;
+
+       /* We have no way to record the stack space.  FIXME.  */
+
+       if (typindx < 256)
+         {
+           return_type = ieee_builtin_type (info, block_start, typindx);
+           if (return_type == DEBUG_TYPE_NULL)
+             return false;
+         }
+       else
+         {
+           typindx -= 256;
+           if (! ieee_alloc_type (info, typindx, true))
+             return false;
+           fnindx = typindx;
+           return_type = info->types.types[typindx].type;
+           if (debug_get_type_kind (info->dhandle, return_type)
+               == DEBUG_KIND_FUNCTION)
+             return_type = debug_get_return_type (info->dhandle,
+                                                  return_type);
+         }
+
+       namcopy = savestring (name, namlen);
+       if (namcopy == NULL)
+         return false;
+       if (! debug_record_function (info->dhandle, namcopy, return_type,
+                                    true, offset))
+         return false;
+      }
+      break;
+
+    case 5:
+      /* BB5: File name for source line numbers.  */
+      {
+       unsigned int i;
+
+       /* We ignore the date and time.  FIXME.  */
+       for (i = 0; i < 6; i++)
+         {
+           bfd_vma ignore;
+           boolean present;
+
+           if (! ieee_read_optional_number (info, pp, &ignore, &present))
+             return false;
+           if (! present)
+             break;
+         }
+
+       namcopy = savestring (name, namlen);
+       if (namcopy == NULL)
+         return false;
+       if (! debug_start_source (info->dhandle, namcopy))
+         return false;
+      }
+      break;
+
+    case 6:
+      /* BB6: Local function or block.  */
+      {
+       bfd_vma stackspace, typindx, offset;
+
+       if (! ieee_read_number (info, pp, &stackspace)
+           || ! ieee_read_number (info, pp, &typindx)
+           || ! ieee_read_expression (info, pp, &offset))
+         return false;
+
+       /* We have no way to record the stack space.  FIXME.  */
+
+       if (namlen == 0)
+         {
+           if (! debug_start_block (info->dhandle, offset))
+             return false;
+           /* Change b to indicate that this is a block
+              rather than a function.  */
+           b = 0x86;
+         }
+       else
+         {
+           /* The MRI C++ compiler will output a fake function named
+              __XRYCPP to hold C++ debugging information.  We skip
+              that function.  This is not crucial, but it makes
+              converting from IEEE to other debug formats work
+              better.  */
+           if (strncmp (name, "__XRYCPP", namlen) == 0)
+             skip = true;
+           else
+             {
+               debug_type return_type;
+
+               if (typindx < 256)
+                 {
+                   return_type = ieee_builtin_type (info, block_start,
+                                                    typindx);
+                   if (return_type == NULL)
+                     return false;
+                 }
+               else
+                 {
+                   typindx -= 256;
+                   if (! ieee_alloc_type (info, typindx, true))
+                     return false;
+                   fnindx = typindx;
+                   return_type = info->types.types[typindx].type;
+                   if (debug_get_type_kind (info->dhandle, return_type)
+                       == DEBUG_KIND_FUNCTION)
+                     return_type = debug_get_return_type (info->dhandle,
+                                                          return_type);
+                 }
+
+               namcopy = savestring (name, namlen);
+               if (namcopy == NULL)
+                 return false;
+               if (! debug_record_function (info->dhandle, namcopy,
+                                            return_type, false, offset))
+                 return false;
+             }
+         }
+      }
+      break;
+
+    case 10:
+      /* BB10: Assembler module scope.  In the normal case, we
+        completely ignore all this information.  FIXME.  */
+      {
+       const char *inam, *vstr;
+       unsigned long inamlen, vstrlen;
+       bfd_vma tool_type;
+       boolean present;
+       unsigned int i;
+
+       if (! info->saw_filename)
+         {
+           namcopy = savestring (name, namlen);
+           if (namcopy == NULL)
+             return false;
+           if (! debug_set_filename (info->dhandle, namcopy))
+             return false;
+           info->saw_filename = true;
+         }
+
+       if (! ieee_read_id (info, pp, &inam, &inamlen)
+           || ! ieee_read_number (info, pp, &tool_type)
+           || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present))
+         return false;
+       for (i = 0; i < 6; i++)
+         {
+           bfd_vma ignore;
+
+           if (! ieee_read_optional_number (info, pp, &ignore, &present))
+             return false;
+           if (! present)
+             break;
+         }
+      }
+      break;
+
+    case 11:
+      /* BB11: Module section.  We completely ignore all this
+        information.  FIXME.  */
+      {
+       bfd_vma sectype, secindx, offset, map;
+       boolean present;
+
+       if (! ieee_read_number (info, pp, &sectype)
+           || ! ieee_read_number (info, pp, &secindx)
+           || ! ieee_read_expression (info, pp, &offset)
+           || ! ieee_read_optional_number (info, pp, &map, &present))
+         return false;
+      }
+      break;
+
+    default:
+      ieee_error (info, block_start, _("unknown BB type"));
+      return false;
+    }
+
+
+  /* Push this block on the block stack.  */
+
+  if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE)
+    {
+      ieee_error (info, (const bfd_byte *) NULL, _("stack overflow"));
+      return false;
+    }
+
+  info->blockstack.bsp->kind = b;
+  if (b == 5)
+    info->blockstack.bsp->filename = namcopy;
+  info->blockstack.bsp->fnindx = fnindx;
+  info->blockstack.bsp->skip = skip;
+  ++info->blockstack.bsp;
+
+  return true;
+}
+
+/* Handle an IEEE BE record.  */
+
+static boolean
+parse_ieee_be (info, pp)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+{
+  bfd_vma offset;
+
+  if (info->blockstack.bsp <= info->blockstack.stack)
+    {
+      ieee_error (info, *pp, _("stack underflow"));
+      return false;
+    }
+  --info->blockstack.bsp;
+
+  switch (info->blockstack.bsp->kind)
+    {
+    case 2:
+      /* When we end the global typedefs block, we copy out the the
+         contents of info->vars.  This is because the variable indices
+         may be reused in the local blocks.  However, we need to
+         preserve them so that we can locate a function returning a
+         reference variable whose type is named in the global typedef
+         block.  */
+      info->global_vars = ((struct ieee_vars *)
+                          xmalloc (sizeof *info->global_vars));
+      info->global_vars->alloc = info->vars.alloc;
+      info->global_vars->vars = ((struct ieee_var *)
+                                xmalloc (info->vars.alloc
+                                         * sizeof (*info->vars.vars)));
+      memcpy (info->global_vars->vars, info->vars.vars,
+             info->vars.alloc * sizeof (*info->vars.vars));
+
+      /* We also copy out the non builtin parts of info->types, since
+         the types are discarded when we start a new block.  */
+      info->global_types = ((struct ieee_types *)
+                           xmalloc (sizeof *info->global_types));
+      info->global_types->alloc = info->types.alloc;
+      info->global_types->types = ((struct ieee_type *)
+                                  xmalloc (info->types.alloc
+                                           * sizeof (*info->types.types)));
+      memcpy (info->global_types->types, info->types.types,
+             info->types.alloc * sizeof (*info->types.types));
+      memset (info->global_types->builtins, 0,
+             sizeof (info->global_types->builtins));
+
+      break;
+
+    case 4:
+    case 6:
+      if (! ieee_read_expression (info, pp, &offset))
+       return false;
+      if (! info->blockstack.bsp->skip)
+       {
+         if (! debug_end_function (info->dhandle, offset + 1))
+           return false;
+       }
+      break;
+
+    case 0x86:
+      /* This is BE6 when BB6 started a block rather than a local
+        function.  */
+      if (! ieee_read_expression (info, pp, &offset))
+       return false;
+      if (! debug_end_block (info->dhandle, offset + 1))
+       return false;
+      break;
+
+    case 5:
+      /* When we end a BB5, we look up the stack for the last BB5, if
+         there is one, so that we can call debug_start_source.  */
+      if (info->blockstack.bsp > info->blockstack.stack)
+       {
+         struct ieee_block *bl;
+
+         bl = info->blockstack.bsp;
+         do
+           {
+             --bl;
+             if (bl->kind == 5)
+               {
+                 if (! debug_start_source (info->dhandle, bl->filename))
+                   return false;
+                 break;
+               }
+           }
+         while (bl != info->blockstack.stack);
+       }
+      break;
+
+    case 11:
+      if (! ieee_read_expression (info, pp, &offset))
+       return false;
+      /* We just ignore the module size.  FIXME.  */
+      break;
+
+    default:
+      /* Other block types do not have any trailing information.  */
+      break;
+    }
+
+  return true;
+}
+
+/* Parse an NN record.  */
+
+static boolean
+parse_ieee_nn (info, pp)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+{
+  const bfd_byte *nn_start;
+  bfd_vma varindx;
+  const char *name;
+  unsigned long namlen;
+
+  nn_start = *pp;
+
+  if (! ieee_read_number (info, pp, &varindx)
+      || ! ieee_read_id (info, pp, &name, &namlen))
+    return false;
+
+  if (varindx < 32)
+    {
+      ieee_error (info, nn_start, _("illegal variable index"));
+      return false;
+    }
+  varindx -= 32;
+
+  if (varindx >= info->vars.alloc)
+    {
+      unsigned int alloc;
+
+      alloc = info->vars.alloc;
+      if (alloc == 0)
+       alloc = 4;
+      while (varindx >= alloc)
+       alloc *= 2;
+      info->vars.vars = ((struct ieee_var *)
+                        xrealloc (info->vars.vars,
+                                  alloc * sizeof *info->vars.vars));
+      memset (info->vars.vars + info->vars.alloc, 0,
+             (alloc - info->vars.alloc) * sizeof *info->vars.vars);
+      info->vars.alloc = alloc;
+    }
+
+  info->vars.vars[varindx].name = name;
+  info->vars.vars[varindx].namlen = namlen;
+
+  return true;
+}
+
+/* Parse a TY record.  */
+
+static boolean
+parse_ieee_ty (info, pp)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+{
+  const bfd_byte *ty_start, *ty_var_start, *ty_code_start;
+  bfd_vma typeindx, varindx, tc;
+  PTR dhandle;
+  boolean tag, typdef;
+  debug_type *arg_slots;
+  unsigned long type_bitsize;
+  debug_type type;
+
+  ty_start = *pp;
+
+  if (! ieee_read_number (info, pp, &typeindx))
+    return false;
+
+  if (typeindx < 256)
+    {
+      ieee_error (info, ty_start, _("illegal type index"));
+      return false;
+    }
+
+  typeindx -= 256;
+  if (! ieee_alloc_type (info, typeindx, false))
+    return false;
+
+  if (**pp != 0xce)
+    {
+      ieee_error (info, *pp, _("unknown TY code"));
+      return false;
+    }
+  ++*pp;
+
+  ty_var_start = *pp;
+
+  if (! ieee_read_number (info, pp, &varindx))
+    return false;
+
+  if (varindx < 32)
+    {
+      ieee_error (info, ty_var_start, _("illegal variable index"));
+      return false;
+    }
+  varindx -= 32;
+
+  if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL)
+    {
+      ieee_error (info, ty_var_start, _("undefined variable in TY"));
+      return false;
+    }
+
+  ty_code_start = *pp;
+
+  if (! ieee_read_number (info, pp, &tc))
+    return false;
+
+  dhandle = info->dhandle;
+
+  tag = false;
+  typdef = false;
+  arg_slots = NULL;
+  type_bitsize = 0;
+  switch (tc)
+    {
+    default:
+      ieee_error (info, ty_code_start, _("unknown TY code"));
+      return false;
+
+    case '!':
+      /* Unknown type, with size.  We treat it as int.  FIXME.  */
+      {
+       bfd_vma size;
+
+       if (! ieee_read_number (info, pp, &size))
+         return false;
+       type = debug_make_int_type (dhandle, size, false);
+      }
+      break;
+
+    case 'A': /* Array.  */
+    case 'a': /* FORTRAN array in column/row order.  FIXME: Not
+                distinguished from normal array.  */
+      {
+       debug_type ele_type;
+       bfd_vma lower, upper;
+
+       if (! ieee_read_type_index (info, pp, &ele_type)
+           || ! ieee_read_number (info, pp, &lower)
+           || ! ieee_read_number (info, pp, &upper))
+         return false;
+       type = debug_make_array_type (dhandle, ele_type,
+                                     ieee_builtin_type (info, ty_code_start,
+                                                        ((unsigned int)
+                                                         builtin_int)),
+                                     (bfd_signed_vma) lower,
+                                     (bfd_signed_vma) upper,
+                                     false);
+      }
+      break;
+
+    case 'E':
+      /* Simple enumeration.  */
+      {
+       bfd_vma size;
+       unsigned int alloc;
+       const char **names;
+       unsigned int c;
+       bfd_signed_vma *vals;
+       unsigned int i;
+
+       if (! ieee_read_number (info, pp, &size))
+         return false;
+       /* FIXME: we ignore the enumeration size.  */
+
+       alloc = 10;
+       names = (const char **) xmalloc (alloc * sizeof *names);
+       memset (names, 0, alloc * sizeof *names);
+       c = 0;
+       while (1)
+         {
+           const char *name;
+           unsigned long namlen;
+           boolean present;
+
+           if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+             return false;
+           if (! present)
+             break;
+
+           if (c + 1 >= alloc)
+             {
+               alloc += 10;
+               names = ((const char **)
+                        xrealloc (names, alloc * sizeof *names));
+             }
+
+           names[c] = savestring (name, namlen);
+           if (names[c] == NULL)
+             return false;
+           ++c;
+         }
+
+       names[c] = NULL;
+
+       vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals);
+       for (i = 0; i < c; i++)
+         vals[i] = i;
+
+       type = debug_make_enum_type (dhandle, names, vals);
+       tag = true;
+      }
+      break;
+
+    case 'G':
+      /* Struct with bit fields.  */
+      {
+       bfd_vma size;
+       unsigned int alloc;
+       debug_field *fields;
+       unsigned int c;
+
+       if (! ieee_read_number (info, pp, &size))
+         return false;
+
+       alloc = 10;
+       fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+       c = 0;
+       while (1)
+         {
+           const char *name;
+           unsigned long namlen;
+           boolean present;
+           debug_type ftype;
+           bfd_vma bitpos, bitsize;
+
+           if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+             return false;
+           if (! present)
+             break;
+           if (! ieee_read_type_index (info, pp, &ftype)
+               || ! ieee_read_number (info, pp, &bitpos)
+               || ! ieee_read_number (info, pp, &bitsize))
+             return false;
+
+           if (c + 1 >= alloc)
+             {
+               alloc += 10;
+               fields = ((debug_field *)
+                         xrealloc (fields, alloc * sizeof *fields));
+             }
+
+           fields[c] = debug_make_field (dhandle, savestring (name, namlen),
+                                         ftype, bitpos, bitsize,
+                                         DEBUG_VISIBILITY_PUBLIC);
+           if (fields[c] == NULL)
+             return false;
+           ++c;
+         }
+
+       fields[c] = NULL;
+
+       type = debug_make_struct_type (dhandle, true, size, fields);
+       tag = true;
+      }
+      break;
+
+    case 'N':
+      /* Enumeration.  */
+      {
+       unsigned int alloc;
+       const char **names;
+       bfd_signed_vma *vals;
+       unsigned int c;
+
+       alloc = 10;
+       names = (const char **) xmalloc (alloc * sizeof *names);
+       vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names);
+       c = 0;
+       while (1)
+         {
+           const char *name;
+           unsigned long namlen;
+           boolean present;
+           bfd_vma val;
+
+           if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+             return false;
+           if (! present)
+             break;
+           if (! ieee_read_number (info, pp, &val))
+             return false;
+
+           /* If the length of the name is zero, then the value is
+               actually the size of the enum.  We ignore this
+               information.  FIXME.  */
+           if (namlen == 0)
+             continue;
+
+           if (c + 1 >= alloc)
+             {
+               alloc += 10;
+               names = ((const char **)
+                        xrealloc (names, alloc * sizeof *names));
+               vals = ((bfd_signed_vma *)
+                       xrealloc (vals, alloc * sizeof *vals));
+             }
+
+           names[c] = savestring (name, namlen);
+           if (names[c] == NULL)
+             return false;
+           vals[c] = (bfd_signed_vma) val;
+           ++c;
+         }
+
+       names[c] = NULL;
+
+       type = debug_make_enum_type (dhandle, names, vals);
+       tag = true;
+      }
+      break;
+
+    case 'O': /* Small pointer.  We don't distinguish small and large
+                pointers.  FIXME.  */
+    case 'P': /* Large pointer.  */
+      {
+       debug_type t;
+
+       if (! ieee_read_type_index (info, pp, &t))
+         return false;
+       type = debug_make_pointer_type (dhandle, t);
+      }
+      break;
+
+    case 'R':
+      /* Range.  */
+      {
+       bfd_vma low, high, signedp, size;
+
+       if (! ieee_read_number (info, pp, &low)
+           || ! ieee_read_number (info, pp, &high)
+           || ! ieee_read_number (info, pp, &signedp)
+           || ! ieee_read_number (info, pp, &size))
+         return false;
+
+       type = debug_make_range_type (dhandle,
+                                     debug_make_int_type (dhandle, size,
+                                                          ! signedp),
+                                     (bfd_signed_vma) low,
+                                     (bfd_signed_vma) high);
+      }
+      break;
+
+    case 'S': /* Struct.  */
+    case 'U': /* Union.  */
+      {
+       bfd_vma size;
+       unsigned int alloc;
+       debug_field *fields;
+       unsigned int c;
+
+       if (! ieee_read_number (info, pp, &size))
+         return false;
+
+       alloc = 10;
+       fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+       c = 0;
+       while (1)
+         {
+           const char *name;
+           unsigned long namlen;
+           boolean present;
+           bfd_vma tindx;
+           bfd_vma offset;
+           debug_type ftype;
+           bfd_vma bitsize;
+
+           if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+             return false;
+           if (! present)
+             break;
+           if (! ieee_read_number (info, pp, &tindx)
+               || ! ieee_read_number (info, pp, &offset))
+             return false;
+
+           if (tindx < 256)
+             {
+               ftype = ieee_builtin_type (info, ty_code_start, tindx);
+               bitsize = 0;
+               offset *= 8;
+             }
+           else
+             {
+               struct ieee_type *t;
+
+               tindx -= 256;
+               if (! ieee_alloc_type (info, tindx, true))
+                 return false;
+               t = info->types.types + tindx;
+               ftype = t->type;
+               bitsize = t->bitsize;
+               if (bitsize == 0)
+                 offset *= 8;
+             }
+
+           if (c + 1 >= alloc)
+             {
+               alloc += 10;
+               fields = ((debug_field *)
+                         xrealloc (fields, alloc * sizeof *fields));
+             }
+
+           fields[c] = debug_make_field (dhandle, savestring (name, namlen),
+                                         ftype, offset, bitsize,
+                                         DEBUG_VISIBILITY_PUBLIC);
+           if (fields[c] == NULL)
+             return false;
+           ++c;
+         }
+
+       fields[c] = NULL;
+
+       type = debug_make_struct_type (dhandle, tc == 'S', size, fields);
+       tag = true;
+      }
+      break;
+
+    case 'T':
+      /* Typedef.  */
+      if (! ieee_read_type_index (info, pp, &type))
+       return false;
+      typdef = true;
+      break;
+
+    case 'X':
+      /* Procedure.  FIXME: This is an extern declaration, which we
+         have no way of representing.  */
+      {
+       bfd_vma attr;
+       debug_type rtype;
+       bfd_vma nargs;
+       boolean present;
+       struct ieee_var *pv;
+
+       /* FIXME: We ignore the attribute and the argument names.  */
+
+       if (! ieee_read_number (info, pp, &attr)
+           || ! ieee_read_type_index (info, pp, &rtype)
+           || ! ieee_read_number (info, pp, &nargs))
+         return false;
+       do
+         {
+           const char *name;
+           unsigned long namlen;
+
+           if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+             return false;
+         }
+       while (present);
+
+       pv = info->vars.vars + varindx;
+       pv->kind = IEEE_EXTERNAL;
+       if (pv->namlen > 0
+           && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
+         {
+           /* Set up the return type as an indirect type pointing to
+               the variable slot, so that we can change it to a
+               reference later if appropriate.  */
+           pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
+           *pv->pslot = rtype;
+           rtype = debug_make_indirect_type (dhandle, pv->pslot,
+                                             (const char *) NULL);
+         }
+
+       type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL,
+                                        false);
+      }
+      break;
+
+    case 'V':
+      /* Void.  This is not documented, but the MRI compiler emits it.  */
+      type = debug_make_void_type (dhandle);
+      break;
+
+    case 'Z':
+      /* Array with 0 lower bound.  */
+      {
+       debug_type etype;
+       bfd_vma high;
+
+       if (! ieee_read_type_index (info, pp, &etype)
+           || ! ieee_read_number (info, pp, &high))
+         return false;
+
+       type = debug_make_array_type (dhandle, etype,
+                                     ieee_builtin_type (info, ty_code_start,
+                                                        ((unsigned int)
+                                                         builtin_int)),
+                                     0, (bfd_signed_vma) high, false);
+      }
+      break;
+
+    case 'c': /* Complex.  */
+    case 'd': /* Double complex.  */
+      {
+       const char *name;
+       unsigned long namlen;
+
+       /* FIXME: I don't know what the name means.  */
+
+       if (! ieee_read_id (info, pp, &name, &namlen))
+         return false;
+
+       type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8);
+      }
+      break;
+
+    case 'f':
+      /* Pascal file name.  FIXME.  */
+      ieee_error (info, ty_code_start, _("Pascal file name not supported"));
+      return false;
+
+    case 'g':
+      /* Bitfield type.  */
+      {
+       bfd_vma signedp, bitsize, dummy;
+       const bfd_byte *hold;
+       boolean present;
+
+       if (! ieee_read_number (info, pp, &signedp)
+           || ! ieee_read_number (info, pp, &bitsize))
+         return false;
+
+       /* I think the documentation says that there is a type index,
+           but some actual files do not have one.  */
+       hold = *pp;
+       if (! ieee_read_optional_number (info, pp, &dummy, &present))
+         return false;
+       if (! present)
+         {
+           /* FIXME: This is just a guess.  */
+           type = debug_make_int_type (dhandle, 4,
+                                       signedp ? false : true);
+         }
+       else
+         {
+           *pp = hold;
+           if (! ieee_read_type_index (info, pp, &type))
+             return false;
+         }
+       type_bitsize = bitsize;
+      }
+      break;
+
+    case 'n':
+      /* Qualifier.  */
+      {
+       bfd_vma kind;
+       debug_type t;
+
+       if (! ieee_read_number (info, pp, &kind)
+           || ! ieee_read_type_index (info, pp, &t))
+         return false;
+
+       switch (kind)
+         {
+         default:
+           ieee_error (info, ty_start, _("unsupported qualifer"));
+           return false;
+
+         case 1:
+           type = debug_make_const_type (dhandle, t);
+           break;
+
+         case 2:
+           type = debug_make_volatile_type (dhandle, t);
+           break;
+         }
+      }
+      break;
+
+    case 's':
+      /* Set.  */
+      {
+       bfd_vma size;
+       debug_type etype;
+
+       if (! ieee_read_number (info, pp, &size)
+           || ! ieee_read_type_index (info, pp, &etype))
+         return false;
+
+       /* FIXME: We ignore the size.  */
+
+       type = debug_make_set_type (dhandle, etype, false);
+      }
+      break;
+
+    case 'x':
+      /* Procedure with compiler dependencies.  */
+      {
+       struct ieee_var *pv;
+       bfd_vma attr, frame_type, push_mask, nargs, level, father;
+       debug_type rtype;
+       debug_type *arg_types;
+       boolean varargs;
+       boolean present;
+
+       /* FIXME: We ignore some of this information.  */
+
+       pv = info->vars.vars + varindx;
+
+       if (! ieee_read_number (info, pp, &attr)
+           || ! ieee_read_number (info, pp, &frame_type)
+           || ! ieee_read_number (info, pp, &push_mask)
+           || ! ieee_read_type_index (info, pp, &rtype)
+           || ! ieee_read_number (info, pp, &nargs))
+         return false;
+       if (nargs == (bfd_vma) -1)
+         {
+           arg_types = NULL;
+           varargs = false;
+         }
+       else
+         {
+           unsigned int i;
+
+           arg_types = ((debug_type *)
+                        xmalloc ((nargs + 1) * sizeof *arg_types));
+           for (i = 0; i < nargs; i++)
+             if (! ieee_read_type_index (info, pp, arg_types + i))
+               return false;
+
+           /* If the last type is pointer to void, this is really a
+               varargs function.  */
+           varargs = false;
+           if (nargs > 0)
+             {
+               debug_type last;
+
+               last = arg_types[nargs - 1];
+               if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER
+                   && (debug_get_type_kind (dhandle,
+                                            debug_get_target_type (dhandle,
+                                                                   last))
+                       == DEBUG_KIND_VOID))
+                 {
+                   --nargs;
+                   varargs = true;
+                 }
+             }
+
+           /* If there are any pointer arguments, turn them into
+               indirect types in case we later need to convert them to
+               reference types.  */
+           for (i = 0; i < nargs; i++)
+             {
+               if (debug_get_type_kind (dhandle, arg_types[i])
+                   == DEBUG_KIND_POINTER)
+                 {
+                   if (arg_slots == NULL)
+                     {
+                       arg_slots = ((debug_type *)
+                                    xmalloc (nargs * sizeof *arg_slots));
+                       memset (arg_slots, 0, nargs * sizeof *arg_slots);
+                     }
+                   arg_slots[i] = arg_types[i];
+                   arg_types[i] =
+                     debug_make_indirect_type (dhandle,
+                                               arg_slots + i,
+                                               (const char *) NULL);
+                 }
+             }
+
+           arg_types[nargs] = DEBUG_TYPE_NULL;
+         }
+       if (! ieee_read_number (info, pp, &level)
+           || ! ieee_read_optional_number (info, pp, &father, &present))
+         return false;
+
+       /* We can't distinguish between a global function and a static
+           function.  */
+       pv->kind = IEEE_FUNCTION;
+
+       if (pv->namlen > 0
+           && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER)
+         {
+           /* Set up the return type as an indirect type pointing to
+               the variable slot, so that we can change it to a
+               reference later if appropriate.  */
+           pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot);
+           *pv->pslot = rtype;
+           rtype = debug_make_indirect_type (dhandle, pv->pslot,
+                                             (const char *) NULL);
+         }
+
+       type = debug_make_function_type (dhandle, rtype, arg_types, varargs);
+      }
+      break;
+    }
+
+  /* Record the type in the table.  */
+
+  if (type == DEBUG_TYPE_NULL)
+    return false;
+
+  info->vars.vars[varindx].type = type;
+
+  if ((tag || typdef)
+      && info->vars.vars[varindx].namlen > 0)
+    {
+      const char *name;
+
+      name = savestring (info->vars.vars[varindx].name,
+                        info->vars.vars[varindx].namlen);
+      if (typdef)
+       type = debug_name_type (dhandle, name, type);
+      else if (tc == 'E' || tc == 'N')
+       type = debug_tag_type (dhandle, name, type);
+      else
+       {
+         struct ieee_tag *it;
+
+         /* We must allocate all struct tags as indirect types, so
+             that if we later see a definition of the tag as a C++
+             record we can update the indirect slot and automatically
+             change all the existing references.  */
+         it = (struct ieee_tag *) xmalloc (sizeof *it);
+         memset (it, 0, sizeof *it);
+         it->next = info->tags;
+         info->tags = it;
+         it->name = name;
+         it->slot = type;
+
+         type = debug_make_indirect_type (dhandle, &it->slot, name);
+         type = debug_tag_type (dhandle, name, type);
+
+         it->type = type;
+       }
+      if (type == NULL)
+       return false;
+    }
+
+  info->types.types[typeindx].type = type;
+  info->types.types[typeindx].arg_slots = arg_slots;
+  info->types.types[typeindx].bitsize = type_bitsize;
+
+  /* We may have already allocated type as an indirect type pointing
+     to slot.  It does no harm to replace the indirect type with the
+     real type.  Filling in slot as well handles the indirect types
+     which are already hanging around.  */
+  if (info->types.types[typeindx].pslot != NULL)
+    *info->types.types[typeindx].pslot = type;
+
+  return true;
+}
+
+/* Parse an ATN record.  */
+
+static boolean
+parse_ieee_atn (info, pp)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+{
+  const bfd_byte *atn_start, *atn_code_start;
+  bfd_vma varindx;
+  struct ieee_var *pvar;
+  debug_type type;
+  bfd_vma atn_code;
+  PTR dhandle;
+  bfd_vma v, v2, v3, v4, v5;
+  const char *name;
+  unsigned long namlen;
+  char *namcopy;
+  boolean present;
+  int blocktype;
+
+  atn_start = *pp;
+
+  if (! ieee_read_number (info, pp, &varindx)
+      || ! ieee_read_type_index (info, pp, &type))
+    return false;
+
+  atn_code_start = *pp;
+
+  if (! ieee_read_number (info, pp, &atn_code))
+    return false;
+
+  if (varindx == 0)
+    {
+      pvar = NULL;
+      name = "";
+      namlen = 0;
+    }
+  else if (varindx < 32)
+    {
+      /* The MRI compiler reportedly sometimes emits variable lifetime
+         information for a register.  We just ignore it.  */
+      if (atn_code == 9)
+       return ieee_read_number (info, pp, &v);
+
+      ieee_error (info, atn_start, _("illegal variable index"));
+      return false;
+    }
+  else
+    {
+      varindx -= 32;
+      if (varindx >= info->vars.alloc
+         || info->vars.vars[varindx].name == NULL)
+       {
+         /* The MRI compiler or linker sometimes omits the NN record
+             for a pmisc record.  */
+         if (atn_code == 62)
+           {
+             if (varindx >= info->vars.alloc)
+               {
+                 unsigned int alloc;
+
+                 alloc = info->vars.alloc;
+                 if (alloc == 0)
+                   alloc = 4;
+                 while (varindx >= alloc)
+                   alloc *= 2;
+                 info->vars.vars = ((struct ieee_var *)
+                                    xrealloc (info->vars.vars,
+                                              (alloc
+                                               * sizeof *info->vars.vars)));
+                 memset (info->vars.vars + info->vars.alloc, 0,
+                         ((alloc - info->vars.alloc)
+                          * sizeof *info->vars.vars));
+                 info->vars.alloc = alloc;
+               }
+
+             pvar = info->vars.vars + varindx;
+             pvar->name = "";
+             pvar->namlen = 0;
+           }
+         else
+           {
+             ieee_error (info, atn_start, _("undefined variable in ATN"));
+             return false;
+           }
+       }
+
+      pvar = info->vars.vars + varindx;
+
+      pvar->type = type;
+
+      name = pvar->name;
+      namlen = pvar->namlen;
+    }
+
+  dhandle = info->dhandle;
+
+  /* If we are going to call debug_record_variable with a pointer
+     type, change the type to an indirect type so that we can later
+     change it to a reference type if we encounter a C++ pmisc 'R'
+     record.  */
+  if (pvar != NULL
+      && type != DEBUG_TYPE_NULL
+      && debug_get_type_kind (dhandle, type) == DEBUG_KIND_POINTER)
+    {
+      switch (atn_code)
+       {
+       case 1:
+       case 2:
+       case 3:
+       case 5:
+       case 8:
+       case 10:
+         pvar->pslot = (debug_type *) xmalloc (sizeof *pvar->pslot);
+         *pvar->pslot = type;
+         type = debug_make_indirect_type (dhandle, pvar->pslot,
+                                          (const char *) NULL);
+         pvar->type = type;
+         break;
+       }
+    }
+
+  switch (atn_code)
+    {
+    default:
+      ieee_error (info, atn_code_start, _("unknown ATN type"));
+      return false;
+
+    case 1:
+      /* Automatic variable.  */
+      if (! ieee_read_number (info, pp, &v))
+       return false;
+      namcopy = savestring (name, namlen);
+      if (type == NULL)
+       type = debug_make_void_type (dhandle);
+      if (pvar != NULL)
+       pvar->kind = IEEE_LOCAL;
+      return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v);
+
+    case 2:
+      /* Register variable.  */
+      if (! ieee_read_number (info, pp, &v))
+       return false;
+      namcopy = savestring (name, namlen);
+      if (type == NULL)
+       type = debug_make_void_type (dhandle);
+      if (pvar != NULL)
+       pvar->kind = IEEE_LOCAL;
+      return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER,
+                                   ieee_regno_to_genreg (info->abfd, v));
+
+    case 3:
+      /* Static variable.  */
+      if (! ieee_require_asn (info, pp, &v))
+       return false;
+      namcopy = savestring (name, namlen);
+      if (type == NULL)
+       type = debug_make_void_type (dhandle);
+      if (info->blockstack.bsp <= info->blockstack.stack)
+       blocktype = 0;
+      else
+       blocktype = info->blockstack.bsp[-1].kind;
+      if (pvar != NULL)
+       {
+         if (blocktype == 4 || blocktype == 6)
+           pvar->kind = IEEE_LOCAL;
+         else
+           pvar->kind = IEEE_STATIC;
+       }
+      return debug_record_variable (dhandle, namcopy, type,
+                                   (blocktype == 4 || blocktype == 6
+                                    ? DEBUG_LOCAL_STATIC
+                                    : DEBUG_STATIC),
+                                   v);
+
+    case 4:
+      /* External function.  We don't currently record these.  FIXME.  */
+      if (pvar != NULL)
+       pvar->kind = IEEE_EXTERNAL;
+      return true;
+
+    case 5:
+      /* External variable.  We don't currently record these.  FIXME.  */
+      if (pvar != NULL)
+       pvar->kind = IEEE_EXTERNAL;
+      return true;
+
+    case 7:
+      if (! ieee_read_number (info, pp, &v)
+         || ! ieee_read_number (info, pp, &v2)
+         || ! ieee_read_optional_number (info, pp, &v3, &present))
+       return false;
+      if (present)
+       {
+         if (! ieee_read_optional_number (info, pp, &v4, &present))
+           return false;
+       }
+
+      /* We just ignore the two optional fields in v3 and v4, since
+         they are not defined.  */
+
+      if (! ieee_require_asn (info, pp, &v3))
+       return false;
+
+      /* We have no way to record the column number.  FIXME.  */
+
+      return debug_record_line (dhandle, v, v3);
+
+    case 8:
+      /* Global variable.  */
+      if (! ieee_require_asn (info, pp, &v))
+       return false;
+      namcopy = savestring (name, namlen);
+      if (type == NULL)
+       type = debug_make_void_type (dhandle);
+      if (pvar != NULL)
+       pvar->kind = IEEE_GLOBAL;
+      return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v);
+
+    case 9:
+      /* Variable lifetime information.  */
+      if (! ieee_read_number (info, pp, &v))
+       return false;
+
+      /* We have no way to record this information.  FIXME.  */
+      return true;
+
+    case 10:
+      /* Locked register.  The spec says that there are two required
+         fields, but at least on occasion the MRI compiler only emits
+         one.  */
+      if (! ieee_read_number (info, pp, &v)
+         || ! ieee_read_optional_number (info, pp, &v2, &present))
+       return false;
+
+      /* I think this means a variable that is both in a register and
+         a frame slot.  We ignore the frame slot.  FIXME.  */
+
+      namcopy = savestring (name, namlen);
+      if (type == NULL)
+       type = debug_make_void_type (dhandle);
+      if (pvar != NULL)
+       pvar->kind = IEEE_LOCAL;
+      return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v);
+
+    case 11:
+      /* Reserved for FORTRAN common.  */
+      ieee_error (info, atn_code_start, _("unsupported ATN11"));
+
+      /* Return true to keep going.  */
+      return true;
+
+    case 12:
+      /* Based variable.  */
+      v3 = 0;
+      v4 = 0x80;
+      v5 = 0;
+      if (! ieee_read_number (info, pp, &v)
+         || ! ieee_read_number (info, pp, &v2)
+         || ! ieee_read_optional_number (info, pp, &v3, &present))
+       return false;
+      if (present)
+       {
+         if (! ieee_read_optional_number (info, pp, &v4, &present))
+           return false;
+         if (present)
+           {
+             if (! ieee_read_optional_number (info, pp, &v5, &present))
+               return false;
+           }
+       }
+
+      /* We have no way to record this information.  FIXME.  */
+
+      ieee_error (info, atn_code_start, _("unsupported ATN12"));
+
+      /* Return true to keep going.  */
+      return true;
+
+    case 16:
+      /* Constant.  The description of this that I have is ambiguous,
+         so I'm not going to try to implement it.  */
+      if (! ieee_read_number (info, pp, &v)
+         || ! ieee_read_optional_number (info, pp, &v2, &present))
+       return false;
+      if (present)
+       {
+         if (! ieee_read_optional_number (info, pp, &v2, &present))
+           return false;
+         if (present)
+           {
+             if (! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+               return false;
+           }
+       }
+
+      if ((ieee_record_enum_type) **pp == ieee_e2_first_byte_enum)
+       {
+         if (! ieee_require_asn (info, pp, &v3))
+           return false;
+       }
+
+      return true;
+
+    case 19:
+      /* Static variable from assembler.  */
+      v2 = 0;
+      if (! ieee_read_number (info, pp, &v)
+         || ! ieee_read_optional_number (info, pp, &v2, &present)
+         || ! ieee_require_asn (info, pp, &v3))
+       return false;
+      namcopy = savestring (name, namlen);
+      /* We don't really handle this correctly.  FIXME.  */
+      return debug_record_variable (dhandle, namcopy,
+                                   debug_make_void_type (dhandle),
+                                   v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC,
+                                   v3);
+
+    case 62:
+      /* Procedure miscellaneous information.  */
+    case 63:
+      /* Variable miscellaneous information.  */
+    case 64:
+      /* Module miscellaneous information.  */
+      if (! ieee_read_number (info, pp, &v)
+         || ! ieee_read_number (info, pp, &v2)
+         || ! ieee_read_optional_id (info, pp, &name, &namlen, &present))
+       return false;
+
+      if (atn_code == 62 && v == 80)
+       {
+         if (present)
+           {
+             ieee_error (info, atn_code_start,
+                         _("unexpected string in C++ misc"));
+             return false;
+           }
+         return ieee_read_cxx_misc (info, pp, v2);
+       }
+
+      /* We just ignore all of this stuff.  FIXME.  */
+
+      for (; v2 > 0; --v2)
+       {
+         switch ((ieee_record_enum_type) **pp)
+           {
+           default:
+             ieee_error (info, *pp, _("bad misc record"));
+             return false;
+
+           case ieee_at_record_enum:
+             if (! ieee_require_atn65 (info, pp, &name, &namlen))
+               return false;
+             break;
+
+           case ieee_e2_first_byte_enum:
+             if (! ieee_require_asn (info, pp, &v3))
+               return false;
+             break;
+           }
+       }
+
+      return true;
+    }
+
+  /*NOTREACHED*/
+}
+
+/* Handle C++ debugging miscellaneous records.  This is called for
+   procedure miscellaneous records of type 80.  */
+
+static boolean
+ieee_read_cxx_misc (info, pp, count)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     unsigned long count;
+{
+  const bfd_byte *start;
+  bfd_vma category;
+
+  start = *pp;
+
+  /* Get the category of C++ misc record.  */
+  if (! ieee_require_asn (info, pp, &category))
+    return false;
+  --count;
+
+  switch (category)
+    {
+    default:
+      ieee_error (info, start, _("unrecognized C++ misc record"));
+      return false;
+
+    case 'T':
+      if (! ieee_read_cxx_class (info, pp, count))
+       return false;
+      break;
+
+    case 'M':
+      {
+       bfd_vma flags;
+       const char *name;
+       unsigned long namlen;
+
+       /* The IEEE spec indicates that the 'M' record only has a
+           flags field.  The MRI compiler also emits the name of the
+           function.  */
+
+       if (! ieee_require_asn (info, pp, &flags))
+         return false;
+       if (*pp < info->pend
+           && (ieee_record_enum_type) **pp == ieee_at_record_enum)
+         {
+           if (! ieee_require_atn65 (info, pp, &name, &namlen))
+             return false;
+         }
+
+       /* This is emitted for method functions, but I don't think we
+           care very much.  It might help if it told us useful
+           information like the class with which this function is
+           associated, but it doesn't, so it isn't helpful.  */
+      }
+      break;
+
+    case 'B':
+      if (! ieee_read_cxx_defaults (info, pp, count))
+       return false;
+      break;
+
+    case 'z':
+      {
+       const char *name, *mangled, *class;
+       unsigned long namlen, mangledlen, classlen;
+       bfd_vma control;
+
+       /* Pointer to member.  */
+
+       if (! ieee_require_atn65 (info, pp, &name, &namlen)
+           || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen)
+           || ! ieee_require_atn65 (info, pp, &class, &classlen)
+           || ! ieee_require_asn (info, pp, &control))
+         return false;
+
+       /* FIXME: We should now track down name and change its type.  */
+      }
+      break;
+
+    case 'R':
+      if (! ieee_read_reference (info, pp))
+       return false;
+      break;
+    }
+
+  return true;
+}
+
+/* Read a C++ class definition.  This is a pmisc type 80 record of
+   category 'T'.  */
+
+static boolean
+ieee_read_cxx_class (info, pp, count)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     unsigned long count;
+{
+  const bfd_byte *start;
+  bfd_vma class;
+  const char *tag;
+  unsigned long taglen;
+  struct ieee_tag *it;
+  PTR dhandle;
+  debug_field *fields;
+  unsigned int field_count, field_alloc;
+  debug_baseclass *baseclasses;
+  unsigned int baseclasses_count, baseclasses_alloc;
+  const debug_field *structfields;
+  struct ieee_method
+    {
+      const char *name;
+      unsigned long namlen;
+      debug_method_variant *variants;
+      unsigned count;
+      unsigned int alloc;
+    } *methods;
+  unsigned int methods_count, methods_alloc;
+  debug_type vptrbase;
+  boolean ownvptr;
+  debug_method *dmethods;
+
+  start = *pp;
+
+  if (! ieee_require_asn (info, pp, &class))
+    return false;
+  --count;
+
+  if (! ieee_require_atn65 (info, pp, &tag, &taglen))
+    return false;
+  --count;
+
+  /* Find the C struct with this name.  */
+  for (it = info->tags; it != NULL; it = it->next)
+    if (it->name[0] == tag[0]
+       && strncmp (it->name, tag, taglen) == 0
+       && strlen (it->name) == taglen)
+      break;
+  if (it == NULL)
+    {
+      ieee_error (info, start, _("undefined C++ object"));
+      return false;
+    }
+
+  dhandle = info->dhandle;
+
+  fields = NULL;
+  field_count = 0;
+  field_alloc = 0;
+  baseclasses = NULL;
+  baseclasses_count = 0;
+  baseclasses_alloc = 0;
+  methods = NULL;
+  methods_count = 0;
+  methods_alloc = 0;
+  vptrbase = DEBUG_TYPE_NULL;
+  ownvptr = false;
+
+  structfields = debug_get_fields (dhandle, it->type);
+
+  while (count > 0)
+    {
+      bfd_vma id;
+      const bfd_byte *spec_start;
+
+      spec_start = *pp;
+
+      if (! ieee_require_asn (info, pp, &id))
+       return false;
+      --count;
+
+      switch (id)
+       {
+       default:
+         ieee_error (info, spec_start, _("unrecognized C++ object spec"));
+         return false;
+
+       case 'b':
+         {
+           bfd_vma flags, cinline;
+           const char *basename, *fieldname;
+           unsigned long baselen, fieldlen;
+           char *basecopy;
+           debug_type basetype;
+           bfd_vma bitpos;
+           boolean virtualp;
+           enum debug_visibility visibility;
+           debug_baseclass baseclass;
+
+           /* This represents a base or friend class.  */
+
+           if (! ieee_require_asn (info, pp, &flags)
+               || ! ieee_require_atn65 (info, pp, &basename, &baselen)
+               || ! ieee_require_asn (info, pp, &cinline)
+               || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen))
+             return false;
+           count -= 4;
+
+           /* We have no way of recording friend information, so we
+               just ignore it.  */
+           if ((flags & BASEFLAGS_FRIEND) != 0)
+             break;
+
+           /* I assume that either all of the members of the
+               baseclass are included in the object, starting at the
+               beginning of the object, or that none of them are
+               included.  */
+
+           if ((fieldlen == 0) == (cinline == 0))
+             {
+               ieee_error (info, start, _("unsupported C++ object type"));
+               return false;
+             }
+
+           basecopy = savestring (basename, baselen);
+           basetype = debug_find_tagged_type (dhandle, basecopy,
+                                              DEBUG_KIND_ILLEGAL);
+           free (basecopy);
+           if (basetype == DEBUG_TYPE_NULL)
+             {
+               ieee_error (info, start, _("C++ base class not defined"));
+               return false;
+             }
+
+           if (fieldlen == 0)
+             bitpos = 0;
+           else
+             {
+               const debug_field *pf;
+
+               if (structfields == NULL)
+                 {
+                   ieee_error (info, start, _("C++ object has no fields"));
+                   return false;
+                 }
+
+               for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++)
+                 {
+                   const char *fname;
+
+                   fname = debug_get_field_name (dhandle, *pf);
+                   if (fname == NULL)
+                     return false;
+                   if (fname[0] == fieldname[0]
+                       && strncmp (fname, fieldname, fieldlen) == 0
+                       && strlen (fname) == fieldlen)
+                     break;
+                 }
+               if (*pf == DEBUG_FIELD_NULL)
+                 {
+                   ieee_error (info, start,
+                               _("C++ base class not found in container"));
+                   return false;
+                 }
+
+               bitpos = debug_get_field_bitpos (dhandle, *pf);
+             }
+
+           if ((flags & BASEFLAGS_VIRTUAL) != 0)
+             virtualp = true;
+           else
+             virtualp = false;
+           if ((flags & BASEFLAGS_PRIVATE) != 0)
+             visibility = DEBUG_VISIBILITY_PRIVATE;
+           else
+             visibility = DEBUG_VISIBILITY_PUBLIC;
+
+           baseclass = debug_make_baseclass (dhandle, basetype, bitpos,
+                                             virtualp, visibility);
+           if (baseclass == DEBUG_BASECLASS_NULL)
+             return false;
+
+           if (baseclasses_count + 1 >= baseclasses_alloc)
+             {
+               baseclasses_alloc += 10;
+               baseclasses = ((debug_baseclass *)
+                              xrealloc (baseclasses,
+                                        (baseclasses_alloc
+                                         * sizeof *baseclasses)));
+             }
+
+           baseclasses[baseclasses_count] = baseclass;
+           ++baseclasses_count;
+           baseclasses[baseclasses_count] = DEBUG_BASECLASS_NULL;
+         }
+         break;
+
+       case 'd':
+         {
+           bfd_vma flags;
+           const char *fieldname, *mangledname;
+           unsigned long fieldlen, mangledlen;
+           char *fieldcopy;
+           boolean staticp;
+           debug_type ftype;
+           const debug_field *pf = NULL;
+           enum debug_visibility visibility;
+           debug_field field;
+
+           /* This represents a data member.  */
+
+           if (! ieee_require_asn (info, pp, &flags)
+               || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen)
+               || ! ieee_require_atn65 (info, pp, &mangledname, &mangledlen))
+             return false;
+           count -= 3;
+
+           fieldcopy = savestring (fieldname, fieldlen);
+
+           staticp = (flags & CXXFLAGS_STATIC) != 0 ? true : false;
+
+           if (staticp)
+             {
+               struct ieee_var *pv, *pvend;
+
+               /* See if we can find a definition for this variable.  */
+               pv = info->vars.vars;
+               pvend = pv + info->vars.alloc;
+               for (; pv < pvend; pv++)
+                 if (pv->namlen == mangledlen
+                     && strncmp (pv->name, mangledname, mangledlen) == 0)
+                   break;
+               if (pv < pvend)
+                 ftype = pv->type;
+               else
+                 {
+                   /* This can happen if the variable is never used.  */
+                   ftype = ieee_builtin_type (info, start,
+                                              (unsigned int) builtin_void);
+                 }
+             }
+           else
+             {
+               unsigned int findx;
+
+               if (structfields == NULL)
+                 {
+                   ieee_error (info, start, _("C++ object has no fields"));
+                   return false;
+                 }
+
+               for (pf = structfields, findx = 0;
+                    *pf != DEBUG_FIELD_NULL;
+                    pf++, findx++)
+                 {
+                   const char *fname;
+
+                   fname = debug_get_field_name (dhandle, *pf);
+                   if (fname == NULL)
+                     return false;
+                   if (fname[0] == mangledname[0]
+                       && strncmp (fname, mangledname, mangledlen) == 0
+                       && strlen (fname) == mangledlen)
+                     break;
+                 }
+               if (*pf == DEBUG_FIELD_NULL)
+                 {
+                   ieee_error (info, start,
+                               _("C++ data member not found in container"));
+                   return false;
+                 }
+
+               ftype = debug_get_field_type (dhandle, *pf);
+
+               if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER)
+                 {
+                   /* We might need to convert this field into a
+                       reference type later on, so make it an indirect
+                       type.  */
+                   if (it->fslots == NULL)
+                     {
+                       unsigned int fcnt;
+                       const debug_field *pfcnt;
+
+                       fcnt = 0;
+                       for (pfcnt = structfields;
+                            *pfcnt != DEBUG_FIELD_NULL;
+                            pfcnt++)
+                         ++fcnt;
+                       it->fslots = ((debug_type *)
+                                     xmalloc (fcnt * sizeof *it->fslots));
+                       memset (it->fslots, 0,
+                               fcnt * sizeof *it->fslots);
+                     }
+
+                   if (ftype == DEBUG_TYPE_NULL)
+                     return false;
+                   it->fslots[findx] = ftype;
+                   ftype = debug_make_indirect_type (dhandle,
+                                                     it->fslots + findx,
+                                                     (const char *) NULL);
+                 }
+             }
+           if (ftype == DEBUG_TYPE_NULL)
+             return false;
+
+           switch (flags & CXXFLAGS_VISIBILITY)
+             {
+             default:
+               ieee_error (info, start, _("unknown C++ visibility"));
+               return false;
+
+             case CXXFLAGS_VISIBILITY_PUBLIC:
+               visibility = DEBUG_VISIBILITY_PUBLIC;
+               break;
+
+             case CXXFLAGS_VISIBILITY_PRIVATE:
+               visibility = DEBUG_VISIBILITY_PRIVATE;
+               break;
+
+             case CXXFLAGS_VISIBILITY_PROTECTED:
+               visibility = DEBUG_VISIBILITY_PROTECTED;
+               break;
+             }
+
+           if (staticp)
+             {
+               char *mangledcopy;
+
+               mangledcopy = savestring (mangledname, mangledlen);
+
+               field = debug_make_static_member (dhandle, fieldcopy,
+                                                 ftype, mangledcopy,
+                                                 visibility);
+             }
+           else
+             {
+               bfd_vma bitpos, bitsize;
+
+               bitpos = debug_get_field_bitpos (dhandle, *pf);
+               bitsize = debug_get_field_bitsize (dhandle, *pf);
+               if (bitpos == (bfd_vma) -1 || bitsize == (bfd_vma) -1)
+                 {
+                   ieee_error (info, start, _("bad C++ field bit pos or size"));
+                   return false;
+                 }
+               field = debug_make_field (dhandle, fieldcopy, ftype, bitpos,
+                                         bitsize, visibility);
+             }
+
+           if (field == DEBUG_FIELD_NULL)
+             return false;
+
+           if (field_count + 1 >= field_alloc)
+             {
+               field_alloc += 10;
+               fields = ((debug_field *)
+                         xrealloc (fields, field_alloc * sizeof *fields));
+             }
+
+           fields[field_count] = field;
+           ++field_count;
+           fields[field_count] = DEBUG_FIELD_NULL;
+         }
+         break;
+
+       case 'm':
+       case 'v':
+         {
+           bfd_vma flags, voffset, control;
+           const char *name, *mangled;
+           unsigned long namlen, mangledlen;
+           struct ieee_var *pv, *pvend;
+           debug_type type;
+           enum debug_visibility visibility;
+           boolean constp, volatilep;
+           char *mangledcopy;
+           debug_method_variant mv;
+           struct ieee_method *meth;
+           unsigned int im;
+
+           if (! ieee_require_asn (info, pp, &flags)
+               || ! ieee_require_atn65 (info, pp, &name, &namlen)
+               || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
+             return false;
+           count -= 3;
+           if (id != 'v')
+             voffset = 0;
+           else
+             {
+               if (! ieee_require_asn (info, pp, &voffset))
+                 return false;
+               --count;
+             }
+           if (! ieee_require_asn (info, pp, &control))
+             return false;
+           --count;
+
+           /* We just ignore the control information.  */
+
+           /* We have no way to represent friend information, so we
+               just ignore it.  */
+           if ((flags & CXXFLAGS_FRIEND) != 0)
+             break;
+
+           /* We should already have seen a type for the function.  */
+           pv = info->vars.vars;
+           pvend = pv + info->vars.alloc;
+           for (; pv < pvend; pv++)
+             if (pv->namlen == mangledlen
+                 && strncmp (pv->name, mangled, mangledlen) == 0)
+               break;
+
+           if (pv >= pvend)
+             {
+               /* We won't have type information for this function if
+                  it is not included in this file.  We don't try to
+                  handle this case.  FIXME.  */
+               type = (debug_make_function_type
+                       (dhandle,
+                        ieee_builtin_type (info, start,
+                                           (unsigned int) builtin_void),
+                        (debug_type *) NULL,
+                        false));
+             }
+           else
+             {
+               debug_type return_type;
+               const debug_type *arg_types;
+               boolean varargs;
+
+               if (debug_get_type_kind (dhandle, pv->type)
+                   != DEBUG_KIND_FUNCTION)
+                 {
+                   ieee_error (info, start,
+                               _("bad type for C++ method function"));
+                   return false;
+                 }
+
+               return_type = debug_get_return_type (dhandle, pv->type);
+               arg_types = debug_get_parameter_types (dhandle, pv->type,
+                                                      &varargs);
+               if (return_type == DEBUG_TYPE_NULL || arg_types == NULL)
+                 {
+                   ieee_error (info, start,
+                               _("no type information for C++ method function"));
+                   return false;
+                 }
+
+               type = debug_make_method_type (dhandle, return_type, it->type,
+                                              (debug_type *) arg_types,
+                                              varargs);
+             }
+           if (type == DEBUG_TYPE_NULL)
+             return false;
+
+           switch (flags & CXXFLAGS_VISIBILITY)
+             {
+             default:
+               ieee_error (info, start, _("unknown C++ visibility"));
+               return false;
+
+             case CXXFLAGS_VISIBILITY_PUBLIC:
+               visibility = DEBUG_VISIBILITY_PUBLIC;
+               break;
+
+             case CXXFLAGS_VISIBILITY_PRIVATE:
+               visibility = DEBUG_VISIBILITY_PRIVATE;
+               break;
+
+             case CXXFLAGS_VISIBILITY_PROTECTED:
+               visibility = DEBUG_VISIBILITY_PROTECTED;
+               break;
+             }
+
+           constp = (flags & CXXFLAGS_CONST) != 0 ? true : false;
+           volatilep = (flags & CXXFLAGS_VOLATILE) != 0 ? true : false;
+
+           mangledcopy = savestring (mangled, mangledlen);
+
+           if ((flags & CXXFLAGS_STATIC) != 0)
+             {
+               if (id == 'v')
+                 {
+                   ieee_error (info, start, _("C++ static virtual method"));
+                   return false;
+                 }
+               mv = debug_make_static_method_variant (dhandle, mangledcopy,
+                                                      type, visibility,
+                                                      constp, volatilep);
+             }
+           else
+             {
+               debug_type vcontext;
+
+               if (id != 'v')
+                 vcontext = DEBUG_TYPE_NULL;
+               else
+                 {
+                   /* FIXME: How can we calculate this correctly?  */
+                   vcontext = it->type;
+                 }
+               mv = debug_make_method_variant (dhandle, mangledcopy, type,
+                                               visibility, constp,
+                                               volatilep, voffset,
+                                               vcontext);
+             }
+           if (mv == DEBUG_METHOD_VARIANT_NULL)
+             return false;
+
+           for (meth = methods, im = 0; im < methods_count; meth++, im++)
+             if (meth->namlen == namlen
+                 && strncmp (meth->name, name, namlen) == 0)
+               break;
+           if (im >= methods_count)
+             {
+               if (methods_count >= methods_alloc)
+                 {
+                   methods_alloc += 10;
+                   methods = ((struct ieee_method *)
+                              xrealloc (methods,
+                                        methods_alloc * sizeof *methods));
+                 }
+               methods[methods_count].name = name;
+               methods[methods_count].namlen = namlen;
+               methods[methods_count].variants = NULL;
+               methods[methods_count].count = 0;
+               methods[methods_count].alloc = 0;
+               meth = methods + methods_count;
+               ++methods_count;
+             }
+
+           if (meth->count + 1 >= meth->alloc)
+             {
+               meth->alloc += 10;
+               meth->variants = ((debug_method_variant *)
+                                 xrealloc (meth->variants,
+                                           (meth->alloc
+                                            * sizeof *meth->variants)));
+             }
+
+           meth->variants[meth->count] = mv;
+           ++meth->count;
+           meth->variants[meth->count] = DEBUG_METHOD_VARIANT_NULL;
+         }
+         break;
+
+       case 'o':
+         {
+           bfd_vma spec;
+
+           /* We have no way to store this information, so we just
+              ignore it.  */
+           if (! ieee_require_asn (info, pp, &spec))
+             return false;
+           --count;
+           if ((spec & 4) != 0)
+             {
+               const char *filename;
+               unsigned long filenamlen;
+               bfd_vma lineno;
+
+               if (! ieee_require_atn65 (info, pp, &filename, &filenamlen)
+                   || ! ieee_require_asn (info, pp, &lineno))
+                 return false;
+               count -= 2;
+             }
+           else if ((spec & 8) != 0)
+             {
+               const char *mangled;
+               unsigned long mangledlen;
+
+               if (! ieee_require_atn65 (info, pp, &mangled, &mangledlen))
+                 return false;
+               --count;
+             }
+           else
+             {
+               ieee_error (info, start,
+                           _("unrecognized C++ object overhead spec"));
+               return false;
+             }
+         }
+         break;
+
+       case 'z':
+         {
+           const char *vname, *basename;
+           unsigned long vnamelen, baselen;
+           bfd_vma vsize, control;
+
+           /* A virtual table pointer.  */
+
+           if (! ieee_require_atn65 (info, pp, &vname, &vnamelen)
+               || ! ieee_require_asn (info, pp, &vsize)
+               || ! ieee_require_atn65 (info, pp, &basename, &baselen)
+               || ! ieee_require_asn (info, pp, &control))
+             return false;
+           count -= 4;
+
+           /* We just ignore the control number.  We don't care what
+              the virtual table name is.  We have no way to store the
+              virtual table size, and I don't think we care anyhow.  */
+
+           /* FIXME: We can't handle multiple virtual table pointers.  */
+
+           if (baselen == 0)
+             ownvptr = true;
+           else
+             {
+               char *basecopy;
+
+               basecopy = savestring (basename, baselen);
+               vptrbase = debug_find_tagged_type (dhandle, basecopy,
+                                                  DEBUG_KIND_ILLEGAL);
+               free (basecopy);
+               if (vptrbase == DEBUG_TYPE_NULL)
+                 {
+                   ieee_error (info, start, _("undefined C++ vtable"));
+                   return false;
+                 }
+             }
+         }
+         break;
+       }
+    }
+
+  /* Now that we have seen all the method variants, we can call
+     debug_make_method for each one.  */
+
+  if (methods_count == 0)
+    dmethods = NULL;
+  else
+    {
+      unsigned int i;
+
+      dmethods = ((debug_method *)
+                 xmalloc ((methods_count + 1) * sizeof *dmethods));
+      for (i = 0; i < methods_count; i++)
+       {
+         char *namcopy;
+
+         namcopy = savestring (methods[i].name, methods[i].namlen);
+         dmethods[i] = debug_make_method (dhandle, namcopy,
+                                          methods[i].variants);
+         if (dmethods[i] == DEBUG_METHOD_NULL)
+           return false;
+       }
+      dmethods[i] = DEBUG_METHOD_NULL;
+      free (methods);
+    }
+
+  /* The struct type was created as an indirect type pointing at
+     it->slot.  We update it->slot to automatically update all
+     references to this struct.  */
+  it->slot = debug_make_object_type (dhandle,
+                                    class != 'u',
+                                    debug_get_type_size (dhandle,
+                                                         it->slot),
+                                    fields, baseclasses, dmethods,
+                                    vptrbase, ownvptr);
+  if (it->slot == DEBUG_TYPE_NULL)
+    return false;
+
+  return true;
+}
+
+/* Read C++ default argument value and reference type information.  */
+
+static boolean
+ieee_read_cxx_defaults (info, pp, count)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     unsigned long count;
+{
+  const bfd_byte *start;
+  const char *fnname;
+  unsigned long fnlen;
+  bfd_vma defcount;
+
+  start = *pp;
+
+  /* Giving the function name before the argument count is an addendum
+     to the spec.  The function name is demangled, though, so this
+     record must always refer to the current function.  */
+
+  if (info->blockstack.bsp <= info->blockstack.stack
+      || info->blockstack.bsp[-1].fnindx == (unsigned int) -1)
+    {
+      ieee_error (info, start, _("C++ default values not in a function"));
+      return false;
+    }
+
+  if (! ieee_require_atn65 (info, pp, &fnname, &fnlen)
+      || ! ieee_require_asn (info, pp, &defcount))
+    return false;
+  count -= 2;
+
+  while (defcount-- > 0)
+    {
+      bfd_vma type, val;
+      const char *strval;
+      unsigned long strvallen;
+
+      if (! ieee_require_asn (info, pp, &type))
+       return false;
+      --count;
+
+      switch (type)
+       {
+       case 0:
+       case 4:
+         break;
+
+       case 1:
+       case 2:
+         if (! ieee_require_asn (info, pp, &val))
+           return false;
+         --count;
+         break;
+
+       case 3:
+       case 7:
+         if (! ieee_require_atn65 (info, pp, &strval, &strvallen))
+           return false;
+         --count;
+         break;
+
+       default:
+         ieee_error (info, start, _("unrecognized C++ default type"));
+         return false;
+       }
+
+      /* We have no way to record the default argument values, so we
+         just ignore them.  FIXME.  */
+    }
+
+  /* Any remaining arguments are indices of parameters that are really
+     reference type.  */
+  if (count > 0)
+    {
+      PTR dhandle;
+      debug_type *arg_slots;
+
+      dhandle = info->dhandle;
+      arg_slots = info->types.types[info->blockstack.bsp[-1].fnindx].arg_slots;
+      while (count-- > 0)
+       {
+         bfd_vma indx;
+         debug_type target;
+
+         if (! ieee_require_asn (info, pp, &indx))
+           return false;
+         /* The index is 1 based.  */
+         --indx;
+         if (arg_slots == NULL
+             || arg_slots[indx] == DEBUG_TYPE_NULL
+             || (debug_get_type_kind (dhandle, arg_slots[indx])
+                 != DEBUG_KIND_POINTER))
+           {
+             ieee_error (info, start, _("reference parameter is not a pointer"));
+             return false;
+           }
+
+         target = debug_get_target_type (dhandle, arg_slots[indx]);
+         arg_slots[indx] = debug_make_reference_type (dhandle, target);
+         if (arg_slots[indx] == DEBUG_TYPE_NULL)
+           return false;
+       }
+    }
+
+  return true;
+}
+
+/* Read a C++ reference definition.  */
+
+static boolean
+ieee_read_reference (info, pp)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+{
+  const bfd_byte *start;
+  bfd_vma flags;
+  const char *class, *name;
+  unsigned long classlen, namlen;
+  debug_type *pslot;
+  debug_type target;
+
+  start = *pp;
+
+  if (! ieee_require_asn (info, pp, &flags))
+    return false;
+
+  /* Giving the class name before the member name is in an addendum to
+     the spec.  */
+  if (flags == 3)
+    {
+      if (! ieee_require_atn65 (info, pp, &class, &classlen))
+       return false;
+    }
+
+  if (! ieee_require_atn65 (info, pp, &name, &namlen))
+    return false;
+
+  pslot = NULL;
+  if (flags != 3)
+    {
+      int pass;
+
+      /* We search from the last variable indices to the first in
+        hopes of finding local variables correctly.  We search the
+        local variables on the first pass, and the global variables
+        on the second.  FIXME: This probably won't work in all cases.
+        On the other hand, I don't know what will.  */
+      for (pass = 0; pass < 2; pass++)
+       {
+         struct ieee_vars *vars;
+         int i;
+         struct ieee_var *pv = NULL;
+
+         if (pass == 0)
+           vars = &info->vars;
+         else
+           {
+             vars = info->global_vars;
+             if (vars == NULL)
+               break;
+           }
+
+         for (i = (int) vars->alloc - 1; i >= 0; i--)
+           {
+             boolean found;
+
+             pv = vars->vars + i;
+
+             if (pv->pslot == NULL
+                 || pv->namlen != namlen
+                 || strncmp (pv->name, name, namlen) != 0)
+               continue;
+
+             found = false;
+             switch (flags)
+               {
+               default:
+                 ieee_error (info, start,
+                             _("unrecognized C++ reference type"));
+                 return false;
+
+               case 0:
+                 /* Global variable or function.  */
+                 if (pv->kind == IEEE_GLOBAL
+                     || pv->kind == IEEE_EXTERNAL
+                     || pv->kind == IEEE_FUNCTION)
+                   found = true;
+                 break;
+
+               case 1:
+                 /* Global static variable or function.  */
+                 if (pv->kind == IEEE_STATIC
+                     || pv->kind == IEEE_FUNCTION)
+                   found = true;
+                 break;
+
+               case 2:
+                 /* Local variable.  */
+                 if (pv->kind == IEEE_LOCAL)
+                   found = true;
+                 break;
+               }
+
+             if (found)
+               break;
+           }
+
+         if (i >= 0)
+           {
+             pslot = pv->pslot;
+             break;
+           }
+       }
+    }
+  else
+    {
+      struct ieee_tag *it;
+
+      for (it = info->tags; it != NULL; it = it->next)
+       {
+         if (it->name[0] == class[0]
+             && strncmp (it->name, class, classlen) == 0
+             && strlen (it->name) == classlen)
+           {
+             if (it->fslots != NULL)
+               {
+                 const debug_field *pf;
+                 unsigned int findx;
+
+                 pf = debug_get_fields (info->dhandle, it->type);
+                 if (pf == NULL)
+                   {
+                     ieee_error (info, start,
+                                 "C++ reference in class with no fields");
+                     return false;
+                   }
+
+                 for (findx = 0; *pf != DEBUG_FIELD_NULL; pf++, findx++)
+                   {
+                     const char *fname;
+
+                     fname = debug_get_field_name (info->dhandle, *pf);
+                     if (fname == NULL)
+                       return false;
+                     if (strncmp (fname, name, namlen) == 0
+                         && strlen (fname) == namlen)
+                       {
+                         pslot = it->fslots + findx;
+                         break;
+                       }
+                   }
+               }
+
+             break;
+           }
+       }
+    }
+
+  if (pslot == NULL)
+    {
+      ieee_error (info, start, _("C++ reference not found"));
+      return false;
+    }
+
+  /* We allocated the type of the object as an indirect type pointing
+     to *pslot, which we can now update to be a reference type.  */
+  if (debug_get_type_kind (info->dhandle, *pslot) != DEBUG_KIND_POINTER)
+    {
+      ieee_error (info, start, _("C++ reference is not pointer"));
+      return false;
+    }
+
+  target = debug_get_target_type (info->dhandle, *pslot);
+  *pslot = debug_make_reference_type (info->dhandle, target);
+  if (*pslot == DEBUG_TYPE_NULL)
+    return false;
+
+  return true;
+}
+
+/* Require an ASN record.  */
+
+static boolean
+ieee_require_asn (info, pp, pv)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     bfd_vma *pv;
+{
+  const bfd_byte *start;
+  ieee_record_enum_type c;
+  bfd_vma varindx;
+
+  start = *pp;
+
+  c = (ieee_record_enum_type) **pp;
+  if (c != ieee_e2_first_byte_enum)
+    {
+      ieee_error (info, start, _("missing required ASN"));
+      return false;
+    }
+  ++*pp;
+
+  c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
+  if (c != ieee_asn_record_enum)
+    {
+      ieee_error (info, start, _("missing required ASN"));
+      return false;
+    }
+  ++*pp;
+
+  /* Just ignore the variable index.  */
+  if (! ieee_read_number (info, pp, &varindx))
+    return false;
+
+  return ieee_read_expression (info, pp, pv);
+}
+
+/* Require an ATN65 record.  */
+
+static boolean
+ieee_require_atn65 (info, pp, pname, pnamlen)
+     struct ieee_info *info;
+     const bfd_byte **pp;
+     const char **pname;
+     unsigned long *pnamlen;
+{
+  const bfd_byte *start;
+  ieee_record_enum_type c;
+  bfd_vma name_indx, type_indx, atn_code;
+
+  start = *pp;
+
+  c = (ieee_record_enum_type) **pp;
+  if (c != ieee_at_record_enum)
+    {
+      ieee_error (info, start, _("missing required ATN65"));
+      return false;
+    }
+  ++*pp;
+
+  c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp);
+  if (c != ieee_atn_record_enum)
+    {
+      ieee_error (info, start, _("missing required ATN65"));
+      return false;
+    }
+  ++*pp;
+
+  if (! ieee_read_number (info, pp, &name_indx)
+      || ! ieee_read_number (info, pp, &type_indx)
+      || ! ieee_read_number (info, pp, &atn_code))
+    return false;
+
+  /* Just ignore name_indx.  */
+
+  if (type_indx != 0 || atn_code != 65)
+    {
+      ieee_error (info, start, _("bad ATN65 record"));
+      return false;
+    }
+
+  return ieee_read_id (info, pp, pname, pnamlen);
+}
+\f
+/* Convert a register number in IEEE debugging information into a
+   generic register number.  */
+
+static int
+ieee_regno_to_genreg (abfd, r)
+     bfd *abfd;
+     int r;
+{
+  switch (bfd_get_arch (abfd))
+    {
+    case bfd_arch_m68k:
+      /* For some reasons stabs adds 2 to the floating point register
+         numbers.  */
+      if (r >= 16)
+       r += 2;
+      break;
+
+    case bfd_arch_i960:
+      /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
+         32 to 35 for fp0 to fp3.  */
+      --r;
+      break;
+
+    default:
+      break;
+    }
+
+  return r;
+}
+
+/* Convert a generic register number to an IEEE specific one.  */
+
+static int
+ieee_genreg_to_regno (abfd, r)
+     bfd *abfd;
+     int r;
+{
+  switch (bfd_get_arch (abfd))
+    {
+    case bfd_arch_m68k:
+      /* For some reason stabs add 2 to the floating point register
+         numbers.  */
+      if (r >= 18)
+       r -= 2;
+      break;
+
+    case bfd_arch_i960:
+      /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and
+         32 to 35 for fp0 to fp3.  */
+      ++r;
+      break;
+
+    default:
+      break;
+    }
+
+  return r;
+}
+\f
+/* These routines build IEEE debugging information out of the generic
+   debugging information.  */
+
+/* We build the IEEE debugging information byte by byte.  Rather than
+   waste time copying data around, we use a linked list of buffers to
+   hold the data.  */
+
+#define IEEE_BUFSIZE (490)
+
+struct ieee_buf
+{
+  /* Next buffer.  */
+  struct ieee_buf *next;
+  /* Number of data bytes in this buffer.  */
+  unsigned int c;
+  /* Bytes.  */
+  bfd_byte buf[IEEE_BUFSIZE];
+};
+
+/* A list of buffers.  */
+
+struct ieee_buflist
+{
+  /* Head of list.  */
+  struct ieee_buf *head;
+  /* Tail--last buffer on list.  */
+  struct ieee_buf *tail;
+};
+
+/* In order to generate the BB11 blocks required by the HP emulator,
+   we keep track of ranges of addresses which correspond to a given
+   compilation unit.  */
+
+struct ieee_range
+{
+  /* Next range.  */
+  struct ieee_range *next;
+  /* Low address.  */
+  bfd_vma low;
+  /* High address.  */
+  bfd_vma high;
+};
+
+/* This structure holds information for a class on the type stack.  */
+
+struct ieee_type_class
+{
+  /* The name index in the debugging information.  */
+  unsigned int indx;
+  /* The pmisc records for the class.  */
+  struct ieee_buflist pmiscbuf;
+  /* The number of pmisc records.  */
+  unsigned int pmisccount;
+  /* The name of the class holding the virtual table, if not this
+     class.  */
+  const char *vclass;
+  /* Whether this class holds its own virtual table.  */
+  boolean ownvptr;
+  /* The largest virtual table offset seen so far.  */
+  bfd_vma voffset;
+  /* The current method.  */
+  const char *method;
+  /* Additional pmisc records used to record fields of reference type.  */
+  struct ieee_buflist refs;
+};
+
+/* This is how we store types for the writing routines.  Most types
+   are simply represented by a type index.  */
+
+struct ieee_write_type
+{
+  /* Type index.  */
+  unsigned int indx;
+  /* The size of the type, if known.  */
+  unsigned int size;
+  /* The name of the type, if any.  */
+  const char *name;
+  /* If this is a function or method type, we build the type here, and
+     only add it to the output buffers if we need it.  */
+  struct ieee_buflist fndef;
+  /* If this is a struct, this is where the struct definition is
+     built.  */
+  struct ieee_buflist strdef;
+  /* If this is a class, this is where the class information is built.  */
+  struct ieee_type_class *classdef;
+  /* Whether the type is unsigned.  */
+  unsigned int unsignedp : 1;
+  /* Whether this is a reference type.  */
+  unsigned int referencep : 1;
+  /* Whether this is in the local type block.  */
+  unsigned int localp : 1;
+  /* Whether this is a duplicate struct definition which we are
+     ignoring.  */
+  unsigned int ignorep : 1;
+};
+
+/* This is the type stack used by the debug writing routines.  FIXME:
+   We could generate more efficient output if we remembered when we
+   have output a particular type before.  */
+
+struct ieee_type_stack
+{
+  /* Next entry on stack.  */
+  struct ieee_type_stack *next;
+  /* Type information.  */
+  struct ieee_write_type type;
+};
+
+/* This is a list of associations between a name and some types.
+   These are used for typedefs and tags.  */
+
+struct ieee_name_type
+{
+  /* Next type for this name.  */
+  struct ieee_name_type *next;
+  /* ID number.  For a typedef, this is the index of the type to which
+     this name is typedefed.  */
+  unsigned int id;
+  /* Type.  */
+  struct ieee_write_type type;
+  /* If this is a tag which has not yet been defined, this is the
+     kind.  If the tag has been defined, this is DEBUG_KIND_ILLEGAL.  */
+  enum debug_type_kind kind;
+};
+
+/* We use a hash table to associate names and types.  */
+
+struct ieee_name_type_hash_table
+{
+  struct bfd_hash_table root;
+};
+
+struct ieee_name_type_hash_entry
+{
+  struct bfd_hash_entry root;
+  /* Information for this name.  */
+  struct ieee_name_type *types;
+};
+
+/* This is a list of enums.  */
+
+struct ieee_defined_enum
+{
+  /* Next enum.  */
+  struct ieee_defined_enum *next;
+  /* Type index.  */
+  unsigned int indx;
+  /* Whether this enum has been defined.  */
+  boolean defined;
+  /* Tag.  */
+  const char *tag;
+  /* Names.  */
+  const char **names;
+  /* Values.  */
+  bfd_signed_vma *vals;
+};
+
+/* We keep a list of modified versions of types, so that we don't
+   output them more than once.  */
+
+struct ieee_modified_type
+{
+  /* Pointer to this type.  */
+  unsigned int pointer;
+  /* Function with unknown arguments returning this type.  */
+  unsigned int function;
+  /* Const version of this type.  */
+  unsigned int const_qualified;
+  /* Volatile version of this type.  */
+  unsigned int volatile_qualified;
+  /* List of arrays of this type of various bounds.  */
+  struct ieee_modified_array_type *arrays;
+};
+
+/* A list of arrays bounds.  */
+
+struct ieee_modified_array_type
+{
+  /* Next array bounds.  */
+  struct ieee_modified_array_type *next;
+  /* Type index with these bounds.  */
+  unsigned int indx;
+  /* Low bound.  */
+  bfd_signed_vma low;
+  /* High bound.  */
+  bfd_signed_vma high;
+};
+
+/* This is a list of pending function parameter information.  We don't
+   output them until we see the first block.  */
+
+struct ieee_pending_parm
+{
+  /* Next pending parameter.  */
+  struct ieee_pending_parm *next;
+  /* Name.  */
+  const char *name;
+  /* Type index.  */
+  unsigned int type;
+  /* Whether the type is a reference.  */
+  boolean referencep;
+  /* Kind.  */
+  enum debug_parm_kind kind;
+  /* Value.  */
+  bfd_vma val;
+};
+
+/* This is the handle passed down by debug_write.  */
+
+struct ieee_handle
+{
+  /* BFD we are writing to.  */
+  bfd *abfd;
+  /* Whether we got an error in a subroutine called via traverse or
+     map_over_sections.  */
+  boolean error;
+  /* Current data buffer list.  */
+  struct ieee_buflist *current;
+  /* Current data buffer.  */
+  struct ieee_buf *curbuf;
+  /* Filename of current compilation unit.  */
+  const char *filename;
+  /* Module name of current compilation unit.  */
+  const char *modname;
+  /* List of buffer for global types.  */
+  struct ieee_buflist global_types;
+  /* List of finished data buffers.  */
+  struct ieee_buflist data;
+  /* List of buffers for typedefs in the current compilation unit.  */
+  struct ieee_buflist types;
+  /* List of buffers for variables and functions in the current
+     compilation unit.  */
+  struct ieee_buflist vars;
+  /* List of buffers for C++ class definitions in the current
+     compilation unit.  */
+  struct ieee_buflist cxx;
+  /* List of buffers for line numbers in the current compilation unit.  */
+  struct ieee_buflist linenos;
+  /* Ranges for the current compilation unit.  */
+  struct ieee_range *ranges;
+  /* Ranges for all debugging information.  */
+  struct ieee_range *global_ranges;
+  /* Nested pending ranges.  */
+  struct ieee_range *pending_ranges;
+  /* Type stack.  */
+  struct ieee_type_stack *type_stack;
+  /* Next unallocated type index.  */
+  unsigned int type_indx;
+  /* Next unallocated name index.  */
+  unsigned int name_indx;
+  /* Typedefs.  */
+  struct ieee_name_type_hash_table typedefs;
+  /* Tags.  */
+  struct ieee_name_type_hash_table tags;
+  /* Enums.  */
+  struct ieee_defined_enum *enums;
+  /* Modified versions of types.  */
+  struct ieee_modified_type *modified;
+  /* Number of entries allocated in modified.  */
+  unsigned int modified_alloc;
+  /* 4 byte complex type.  */
+  unsigned int complex_float_index;
+  /* 8 byte complex type.  */
+  unsigned int complex_double_index;
+  /* The depth of block nesting.  This is 0 outside a function, and 1
+     just after start_function is called.  */
+  unsigned int block_depth;
+  /* The name of the current function.  */
+  const char *fnname;
+  /* List of buffers for the type of the function we are currently
+     writing out.  */
+  struct ieee_buflist fntype;
+  /* List of buffers for the parameters of the function we are
+     currently writing out.  */
+  struct ieee_buflist fnargs;
+  /* Number of arguments written to fnargs.  */
+  unsigned int fnargcount;
+  /* Pending function parameters.  */
+  struct ieee_pending_parm *pending_parms;
+  /* Current line number filename.  */
+  const char *lineno_filename;
+  /* Line number name index.  */
+  unsigned int lineno_name_indx;
+  /* Filename of pending line number.  */
+  const char *pending_lineno_filename;
+  /* Pending line number.  */
+  unsigned long pending_lineno;
+  /* Address of pending line number.  */
+  bfd_vma pending_lineno_addr;
+  /* Highest address seen at end of procedure.  */
+  bfd_vma highaddr;
+};
+
+static boolean ieee_init_buffer
+  PARAMS ((struct ieee_handle *, struct ieee_buflist *));
+static boolean ieee_change_buffer
+  PARAMS ((struct ieee_handle *, struct ieee_buflist *));
+static boolean ieee_append_buffer
+  PARAMS ((struct ieee_handle *, struct ieee_buflist *,
+          struct ieee_buflist *));
+static boolean ieee_real_write_byte PARAMS ((struct ieee_handle *, int));
+static boolean ieee_write_2bytes PARAMS ((struct ieee_handle *, int));
+static boolean ieee_write_number PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_write_id PARAMS ((struct ieee_handle *, const char *));
+static boolean ieee_write_asn
+  PARAMS ((struct ieee_handle *, unsigned int, bfd_vma));
+static boolean ieee_write_atn65
+  PARAMS ((struct ieee_handle *, unsigned int, const char *));
+static boolean ieee_push_type
+  PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean,
+          boolean));
+static unsigned int ieee_pop_type PARAMS ((struct ieee_handle *));
+static void ieee_pop_unused_type PARAMS ((struct ieee_handle *));
+static unsigned int ieee_pop_type_used
+  PARAMS ((struct ieee_handle *, boolean));
+static boolean ieee_add_range
+  PARAMS ((struct ieee_handle *, boolean, bfd_vma, bfd_vma));
+static boolean ieee_start_range PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_end_range PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_define_type
+  PARAMS ((struct ieee_handle *, unsigned int, boolean, boolean));
+static boolean ieee_define_named_type
+  PARAMS ((struct ieee_handle *, const char *, unsigned int, unsigned int,
+          boolean, boolean, struct ieee_buflist *));
+static struct ieee_modified_type *ieee_get_modified_info
+  PARAMS ((struct ieee_handle *, unsigned int));
+static struct bfd_hash_entry *ieee_name_type_newfunc
+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean ieee_write_undefined_tag
+  PARAMS ((struct ieee_name_type_hash_entry *, PTR));
+static boolean ieee_finish_compilation_unit PARAMS ((struct ieee_handle *));
+static void ieee_add_bb11_blocks PARAMS ((bfd *, asection *, PTR));
+static boolean ieee_add_bb11
+  PARAMS ((struct ieee_handle *, asection *, bfd_vma, bfd_vma));
+static boolean ieee_output_pending_parms PARAMS ((struct ieee_handle *));
+static unsigned int ieee_vis_to_flags PARAMS ((enum debug_visibility));
+static boolean ieee_class_method_var
+  PARAMS ((struct ieee_handle *, const char *, enum debug_visibility, boolean,
+          boolean, boolean, bfd_vma, boolean));
+
+static boolean ieee_start_compilation_unit PARAMS ((PTR, const char *));
+static boolean ieee_start_source PARAMS ((PTR, const char *));
+static boolean ieee_empty_type PARAMS ((PTR));
+static boolean ieee_void_type PARAMS ((PTR));
+static boolean ieee_int_type PARAMS ((PTR, unsigned int, boolean));
+static boolean ieee_float_type PARAMS ((PTR, unsigned int));
+static boolean ieee_complex_type PARAMS ((PTR, unsigned int));
+static boolean ieee_bool_type PARAMS ((PTR, unsigned int));
+static boolean ieee_enum_type
+  PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static boolean ieee_pointer_type PARAMS ((PTR));
+static boolean ieee_function_type PARAMS ((PTR, int, boolean));
+static boolean ieee_reference_type PARAMS ((PTR));
+static boolean ieee_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+static boolean ieee_array_type
+  PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
+static boolean ieee_set_type PARAMS ((PTR, boolean));
+static boolean ieee_offset_type PARAMS ((PTR));
+static boolean ieee_method_type PARAMS ((PTR, boolean, int, boolean));
+static boolean ieee_const_type PARAMS ((PTR));
+static boolean ieee_volatile_type PARAMS ((PTR));
+static boolean ieee_start_struct_type
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
+static boolean ieee_struct_field
+  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static boolean ieee_end_struct_type PARAMS ((PTR));
+static boolean ieee_start_class_type
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+          boolean));
+static boolean ieee_class_static_member
+  PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static boolean ieee_class_baseclass
+  PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
+static boolean ieee_class_start_method PARAMS ((PTR, const char *));
+static boolean ieee_class_method_variant
+  PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
+          bfd_vma, boolean));
+static boolean ieee_class_static_method_variant
+  PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
+static boolean ieee_class_end_method PARAMS ((PTR));
+static boolean ieee_end_class_type PARAMS ((PTR));
+static boolean ieee_typedef_type PARAMS ((PTR, const char *));
+static boolean ieee_tag_type
+  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static boolean ieee_typdef PARAMS ((PTR, const char *));
+static boolean ieee_tag PARAMS ((PTR, const char *));
+static boolean ieee_int_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean ieee_float_constant PARAMS ((PTR, const char *, double));
+static boolean ieee_typed_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean ieee_variable
+  PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static boolean ieee_start_function PARAMS ((PTR, const char *, boolean));
+static boolean ieee_function_parameter
+  PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static boolean ieee_start_block PARAMS ((PTR, bfd_vma));
+static boolean ieee_end_block PARAMS ((PTR, bfd_vma));
+static boolean ieee_end_function PARAMS ((PTR));
+static boolean ieee_lineno
+  PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
+static const struct debug_write_fns ieee_fns =
+{
+  ieee_start_compilation_unit,
+  ieee_start_source,
+  ieee_empty_type,
+  ieee_void_type,
+  ieee_int_type,
+  ieee_float_type,
+  ieee_complex_type,
+  ieee_bool_type,
+  ieee_enum_type,
+  ieee_pointer_type,
+  ieee_function_type,
+  ieee_reference_type,
+  ieee_range_type,
+  ieee_array_type,
+  ieee_set_type,
+  ieee_offset_type,
+  ieee_method_type,
+  ieee_const_type,
+  ieee_volatile_type,
+  ieee_start_struct_type,
+  ieee_struct_field,
+  ieee_end_struct_type,
+  ieee_start_class_type,
+  ieee_class_static_member,
+  ieee_class_baseclass,
+  ieee_class_start_method,
+  ieee_class_method_variant,
+  ieee_class_static_method_variant,
+  ieee_class_end_method,
+  ieee_end_class_type,
+  ieee_typedef_type,
+  ieee_tag_type,
+  ieee_typdef,
+  ieee_tag,
+  ieee_int_constant,
+  ieee_float_constant,
+  ieee_typed_constant,
+  ieee_variable,
+  ieee_start_function,
+  ieee_function_parameter,
+  ieee_start_block,
+  ieee_end_block,
+  ieee_end_function,
+  ieee_lineno
+};
+
+/* Initialize a buffer to be empty.  */
+
+/*ARGSUSED*/
+static boolean
+ieee_init_buffer (info, buflist)
+     struct ieee_handle *info;
+     struct ieee_buflist *buflist;
+{
+  buflist->head = NULL;
+  buflist->tail = NULL;
+  return true;
+}
+
+/* See whether a buffer list has any data.  */
+
+#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL)
+
+/* Change the current buffer to a specified buffer chain.  */
+
+static boolean
+ieee_change_buffer (info, buflist)
+     struct ieee_handle *info;
+     struct ieee_buflist *buflist;
+{
+  if (buflist->head == NULL)
+    {
+      struct ieee_buf *buf;
+
+      buf = (struct ieee_buf *) xmalloc (sizeof *buf);
+      buf->next = NULL;
+      buf->c = 0;
+      buflist->head = buf;
+      buflist->tail = buf;
+    }
+
+  info->current = buflist;
+  info->curbuf = buflist->tail;
+
+  return true;
+}
+
+/* Append a buffer chain.  */
+
+/*ARGSUSED*/
+static boolean
+ieee_append_buffer (info, mainbuf, newbuf)
+     struct ieee_handle *info;
+     struct ieee_buflist *mainbuf;
+     struct ieee_buflist *newbuf;
+{
+  if (newbuf->head != NULL)
+    {
+      if (mainbuf->head == NULL)
+       mainbuf->head = newbuf->head;
+      else
+       mainbuf->tail->next = newbuf->head;
+      mainbuf->tail = newbuf->tail;
+    }
+  return true;
+}
+
+/* Write a byte into the buffer.  We use a macro for speed and a
+   function for the complex cases.  */
+
+#define ieee_write_byte(info, b)                               \
+  ((info)->curbuf->c < IEEE_BUFSIZE                            \
+   ? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), true)    \
+   : ieee_real_write_byte ((info), (b)))
+
+static boolean
+ieee_real_write_byte (info, b)
+     struct ieee_handle *info;
+     int b;
+{
+  if (info->curbuf->c >= IEEE_BUFSIZE)
+    {
+      struct ieee_buf *n;
+
+      n = (struct ieee_buf *) xmalloc (sizeof *n);
+      n->next = NULL;
+      n->c = 0;
+      if (info->current->head == NULL)
+       info->current->head = n;
+      else
+       info->current->tail->next = n;
+      info->current->tail = n;
+      info->curbuf = n;
+    }
+
+  info->curbuf->buf[info->curbuf->c] = b;
+  ++info->curbuf->c;
+
+  return true;
+}
+
+/* Write out two bytes.  */
+
+static boolean
+ieee_write_2bytes (info, i)
+     struct ieee_handle *info;
+     int i;
+{
+  return (ieee_write_byte (info, i >> 8)
+         && ieee_write_byte (info, i & 0xff));
+}
+
+/* Write out an integer.  */
+
+static boolean
+ieee_write_number (info, v)
+     struct ieee_handle *info;
+     bfd_vma v;
+{
+  bfd_vma t;
+  bfd_byte ab[20];
+  bfd_byte *p;
+  unsigned int c;
+
+  if (v <= (bfd_vma) ieee_number_end_enum)
+    return ieee_write_byte (info, (int) v);
+
+  t = v;
+  p = ab + sizeof ab;
+  while (t != 0)
+    {
+      *--p = t & 0xff;
+      t >>= 8;
+    }
+  c = (ab + 20) - p;
+
+  if (c > (unsigned int) (ieee_number_repeat_end_enum
+                         - ieee_number_repeat_start_enum))
+    {
+      fprintf (stderr, _("IEEE numeric overflow: 0x"));
+      fprintf_vma (stderr, v);
+      fprintf (stderr, "\n");
+      return false;
+    }
+
+  if (! ieee_write_byte (info, (int) ieee_number_repeat_start_enum + c))
+    return false;
+  for (; c > 0; --c, ++p)
+    {
+      if (! ieee_write_byte (info, *p))
+       return false;
+    }
+
+  return true;
+}
+
+/* Write out a string.  */
+
+static boolean
+ieee_write_id (info, s)
+     struct ieee_handle *info;
+     const char *s;
+{
+  unsigned int len;
+
+  len = strlen (s);
+  if (len <= 0x7f)
+    {
+      if (! ieee_write_byte (info, len))
+       return false;
+    }
+  else if (len <= 0xff)
+    {
+      if (! ieee_write_byte (info, (int) ieee_extension_length_1_enum)
+         || ! ieee_write_byte (info, len))
+       return false;
+    }
+  else if (len <= 0xffff)
+    {
+      if (! ieee_write_byte (info, (int) ieee_extension_length_2_enum)
+         || ! ieee_write_2bytes (info, len))
+       return false;
+    }
+  else
+    {
+      fprintf (stderr, _("IEEE string length overflow: %u\n"), len);
+      return false;
+    }
+
+  for (; *s != '\0'; s++)
+    if (! ieee_write_byte (info, *s))
+      return false;
+
+  return true;
+}
+
+/* Write out an ASN record.  */
+
+static boolean
+ieee_write_asn (info, indx, val)
+     struct ieee_handle *info;
+     unsigned int indx;
+     bfd_vma val;
+{
+  return (ieee_write_2bytes (info, (int) ieee_asn_record_enum)
+         && ieee_write_number (info, indx)
+         && ieee_write_number (info, val));
+}
+
+/* Write out an ATN65 record.  */
+
+static boolean
+ieee_write_atn65 (info, indx, s)
+     struct ieee_handle *info;
+     unsigned int indx;
+     const char *s;
+{
+  return (ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+         && ieee_write_number (info, indx)
+         && ieee_write_number (info, 0)
+         && ieee_write_number (info, 65)
+         && ieee_write_id (info, s));
+}
+
+/* Push a type index onto the type stack.  */
+
+static boolean
+ieee_push_type (info, indx, size, unsignedp, localp)
+     struct ieee_handle *info;
+     unsigned int indx;
+     unsigned int size;
+     boolean unsignedp;
+     boolean localp;
+{
+  struct ieee_type_stack *ts;
+
+  ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
+  memset (ts, 0, sizeof *ts);
+
+  ts->type.indx = indx;
+  ts->type.size = size;
+  ts->type.unsignedp = unsignedp;
+  ts->type.localp = localp;
+
+  ts->next = info->type_stack;
+  info->type_stack = ts;
+
+  return true;
+}
+
+/* Pop a type index off the type stack.  */
+
+static unsigned int
+ieee_pop_type (info)
+     struct ieee_handle *info;
+{
+  return ieee_pop_type_used (info, true);
+}
+
+/* Pop an unused type index off the type stack.  */
+
+static void
+ieee_pop_unused_type (info)
+     struct ieee_handle *info;
+{
+  (void) ieee_pop_type_used (info, false);
+}
+
+/* Pop a used or unused type index off the type stack.  */
+
+static unsigned int
+ieee_pop_type_used (info, used)
+     struct ieee_handle *info;
+     boolean used;
+{
+  struct ieee_type_stack *ts;
+  unsigned int ret;
+
+  ts = info->type_stack;
+  assert (ts != NULL);
+
+  /* If this is a function type, and we need it, we need to append the
+     actual definition to the typedef block now.  */
+  if (used && ! ieee_buffer_emptyp (&ts->type.fndef))
+    {
+      struct ieee_buflist *buflist;
+
+      if (ts->type.localp)
+       {
+         /* Make sure we have started the types block.  */
+         if (ieee_buffer_emptyp (&info->types))
+           {
+             if (! ieee_change_buffer (info, &info->types)
+                 || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+                 || ! ieee_write_byte (info, 1)
+                 || ! ieee_write_number (info, 0)
+                 || ! ieee_write_id (info, info->modname))
+               return false;
+           }
+         buflist = &info->types;
+       }
+      else
+       {
+         /* Make sure we started the global type block.  */
+         if (ieee_buffer_emptyp (&info->global_types))
+           {
+             if (! ieee_change_buffer (info, &info->global_types)
+                 || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+                 || ! ieee_write_byte (info, 2)
+                 || ! ieee_write_number (info, 0)
+                 || ! ieee_write_id (info, ""))
+               return false;
+           }
+         buflist = &info->global_types;
+       }
+
+      if (! ieee_append_buffer (info, buflist, &ts->type.fndef))
+       return false;
+    }
+
+  ret = ts->type.indx;
+  info->type_stack = ts->next;
+  free (ts);
+  return ret;
+}
+
+/* Add a range of bytes included in the current compilation unit.  */
+
+static boolean
+ieee_add_range (info, global, low, high)
+     struct ieee_handle *info;
+     boolean global;
+     bfd_vma low;
+     bfd_vma high;
+{
+  struct ieee_range **plist, *r, **pr;
+
+  if (low == (bfd_vma) -1 || high == (bfd_vma) -1 || low == high)
+    return true;
+
+  if (global)
+    plist = &info->global_ranges;
+  else
+    plist = &info->ranges;
+
+  for (r = *plist; r != NULL; r = r->next)
+    {
+      if (high >= r->low && low <= r->high)
+       {
+         /* The new range overlaps r.  */
+         if (low < r->low)
+           r->low = low;
+         if (high > r->high)
+           r->high = high;
+         pr = &r->next;
+         while (*pr != NULL && (*pr)->low <= r->high)
+           {
+             struct ieee_range *n;
+
+             if ((*pr)->high > r->high)
+               r->high = (*pr)->high;
+             n = (*pr)->next;
+             free (*pr);
+             *pr = n;
+           }
+         return true;
+       }
+    }
+
+  r = (struct ieee_range *) xmalloc (sizeof *r);
+  memset (r, 0, sizeof *r);
+
+  r->low = low;
+  r->high = high;
+
+  /* Store the ranges sorted by address.  */
+  for (pr = plist; *pr != NULL; pr = &(*pr)->next)
+    if ((*pr)->low > high)
+      break;
+  r->next = *pr;
+  *pr = r;
+
+  return true;
+}
+
+/* Start a new range for which we only have the low address.  */
+
+static boolean
+ieee_start_range (info, low)
+     struct ieee_handle *info;
+     bfd_vma low;
+{
+  struct ieee_range *r;
+
+  r = (struct ieee_range *) xmalloc (sizeof *r);
+  memset (r, 0, sizeof *r);
+  r->low = low;
+  r->next = info->pending_ranges;
+  info->pending_ranges = r;
+  return true;
+}  
+
+/* Finish a range started by ieee_start_range.  */
+
+static boolean
+ieee_end_range (info, high)
+     struct ieee_handle *info;
+     bfd_vma high;
+{
+  struct ieee_range *r;
+  bfd_vma low;
+
+  assert (info->pending_ranges != NULL);
+  r = info->pending_ranges;
+  low = r->low;
+  info->pending_ranges = r->next;
+  free (r);
+  return ieee_add_range (info, false, low, high);
+}
+
+/* Start defining a type.  */
+
+static boolean
+ieee_define_type (info, size, unsignedp, localp)
+     struct ieee_handle *info;
+     unsigned int size;
+     boolean unsignedp;
+     boolean localp;
+{
+  return ieee_define_named_type (info, (const char *) NULL,
+                                (unsigned int) -1, size, unsignedp,
+                                localp, (struct ieee_buflist *) NULL);
+}
+
+/* Start defining a named type.  */
+
+static boolean
+ieee_define_named_type (info, name, indx, size, unsignedp, localp, buflist)
+     struct ieee_handle *info;
+     const char *name;
+     unsigned int indx;
+     unsigned int size;
+     boolean unsignedp;
+     boolean localp;
+     struct ieee_buflist *buflist;
+{
+  unsigned int type_indx;
+  unsigned int name_indx;
+
+  if (indx != (unsigned int) -1)
+    type_indx = indx;
+  else
+    {
+      type_indx = info->type_indx;
+      ++info->type_indx;
+    }
+
+  name_indx = info->name_indx;
+  ++info->name_indx;
+
+  if (name == NULL)
+    name = "";
+
+  /* If we were given a buffer, use it; otherwise, use either the
+     local or the global type information, and make sure that the type
+     block is started.  */
+  if (buflist != NULL)
+    {
+      if (! ieee_change_buffer (info, buflist))
+       return false;
+    }
+  else if (localp)
+    {
+      if (! ieee_buffer_emptyp (&info->types))
+       {
+         if (! ieee_change_buffer (info, &info->types))
+           return false;
+       }
+      else
+       {
+         if (! ieee_change_buffer (info, &info->types)
+             || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+             || ! ieee_write_byte (info, 1)
+             || ! ieee_write_number (info, 0)
+             || ! ieee_write_id (info, info->modname))
+           return false;
+       }
+    }
+  else
+    {
+      if (! ieee_buffer_emptyp (&info->global_types))
+       {
+         if (! ieee_change_buffer (info, &info->global_types))
+           return false;
+       }
+      else
+       {
+         if (! ieee_change_buffer (info, &info->global_types)
+             || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+             || ! ieee_write_byte (info, 2)
+             || ! ieee_write_number (info, 0)
+             || ! ieee_write_id (info, ""))
+           return false;
+       }
+    }
+
+  /* Push the new type on the type stack, write out an NN record, and
+     write out the start of a TY record.  The caller will then finish
+     the TY record.  */
+  if (! ieee_push_type (info, type_indx, size, unsignedp, localp))
+    return false;
+
+  return (ieee_write_byte (info, (int) ieee_nn_record)
+         && ieee_write_number (info, name_indx)
+         && ieee_write_id (info, name)
+         && ieee_write_byte (info, (int) ieee_ty_record_enum)
+         && ieee_write_number (info, type_indx)
+         && ieee_write_byte (info, 0xce)
+         && ieee_write_number (info, name_indx));
+}
+
+/* Get an entry to the list of modified versions of a type.  */
+
+static struct ieee_modified_type *
+ieee_get_modified_info (info, indx)
+     struct ieee_handle *info;
+     unsigned int indx;
+{
+  if (indx >= info->modified_alloc)
+    {
+      unsigned int nalloc;
+
+      nalloc = info->modified_alloc;
+      if (nalloc == 0)
+       nalloc = 16;
+      while (indx >= nalloc)
+       nalloc *= 2;
+      info->modified = ((struct ieee_modified_type *)
+                       xrealloc (info->modified,
+                                 nalloc * sizeof *info->modified));
+      memset (info->modified + info->modified_alloc, 0,
+             (nalloc - info->modified_alloc) * sizeof *info->modified);
+      info->modified_alloc = nalloc;
+    }
+
+  return info->modified + indx;
+}
+\f
+/* Routines for the hash table mapping names to types.  */
+
+/* Initialize an entry in the hash table.  */
+
+static struct bfd_hash_entry *
+ieee_name_type_newfunc (entry, table, string)
+     struct bfd_hash_entry *entry;
+     struct bfd_hash_table *table;
+     const char *string;
+{
+  struct ieee_name_type_hash_entry *ret =
+    (struct ieee_name_type_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (ret == NULL)
+    ret = ((struct ieee_name_type_hash_entry *)
+          bfd_hash_allocate (table, sizeof *ret));
+  if (ret == NULL)
+    return NULL;
+
+  /* Call the allocation method of the superclass.  */
+  ret = ((struct ieee_name_type_hash_entry *)
+        bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+  if (ret)
+    {
+      /* Set local fields.  */
+      ret->types = NULL;
+    }
+
+  return (struct bfd_hash_entry *) ret;
+}
+
+/* Look up an entry in the hash table.  */
+
+#define ieee_name_type_hash_lookup(table, string, create, copy) \
+  ((struct ieee_name_type_hash_entry *) \
+   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+/* Traverse the hash table.  */
+
+#define ieee_name_type_hash_traverse(table, func, info)                        \
+  (bfd_hash_traverse                                                   \
+   (&(table)->root,                                                    \
+    (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func),      \
+    (info)))
+\f
+/* The general routine to write out IEEE debugging information.  */
+
+boolean
+write_ieee_debugging_info (abfd, dhandle)
+     bfd *abfd;
+     PTR dhandle;
+{
+  struct ieee_handle info;
+  asection *s;
+  const char *err;
+  struct ieee_buf *b;
+
+  memset (&info, 0, sizeof info);
+  info.abfd = abfd;
+  info.type_indx = 256;
+  info.name_indx = 32;
+
+  if (! bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc)
+      || ! bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc))
+    return false;
+
+  if (! ieee_init_buffer (&info, &info.global_types)
+      || ! ieee_init_buffer (&info, &info.data)
+      || ! ieee_init_buffer (&info, &info.types)
+      || ! ieee_init_buffer (&info, &info.vars)
+      || ! ieee_init_buffer (&info, &info.cxx)
+      || ! ieee_init_buffer (&info, &info.linenos)
+      || ! ieee_init_buffer (&info, &info.fntype)
+      || ! ieee_init_buffer (&info, &info.fnargs))
+    return false;
+
+  if (! debug_write (dhandle, &ieee_fns, (PTR) &info))
+    return false;
+
+  if (info.filename != NULL)
+    {
+      if (! ieee_finish_compilation_unit (&info))
+       return false;
+    }
+
+  /* Put any undefined tags in the global typedef information.  */
+  info.error = false;
+  ieee_name_type_hash_traverse (&info.tags,
+                               ieee_write_undefined_tag,
+                               (PTR) &info);
+  if (info.error)
+    return false;
+
+  /* Prepend the global typedef information to the other data.  */
+  if (! ieee_buffer_emptyp (&info.global_types))
+    {
+      /* The HP debugger seems to have a bug in which it ignores the
+         last entry in the global types, so we add a dummy entry.  */
+      if (! ieee_change_buffer (&info, &info.global_types)
+         || ! ieee_write_byte (&info, (int) ieee_nn_record)
+         || ! ieee_write_number (&info, info.name_indx)
+         || ! ieee_write_id (&info, "")
+         || ! ieee_write_byte (&info, (int) ieee_ty_record_enum)
+         || ! ieee_write_number (&info, info.type_indx)
+         || ! ieee_write_byte (&info, 0xce)
+         || ! ieee_write_number (&info, info.name_indx)
+         || ! ieee_write_number (&info, 'P')
+         || ! ieee_write_number (&info, (int) builtin_void + 32)
+         || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
+       return false;
+
+      if (! ieee_append_buffer (&info, &info.global_types, &info.data))
+       return false;
+      info.data = info.global_types;
+    }
+
+  /* Make sure that we have declare BB11 blocks for each range in the
+     file.  They are added to info->vars.  */
+  info.error = false;
+  if (! ieee_init_buffer (&info, &info.vars))
+    return false;
+  bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (PTR) &info);
+  if (info.error)
+    return false;
+  if (! ieee_buffer_emptyp (&info.vars))
+    {
+      if (! ieee_change_buffer (&info, &info.vars)
+         || ! ieee_write_byte (&info, (int) ieee_be_record_enum))
+       return false;
+
+      if (! ieee_append_buffer (&info, &info.data, &info.vars))
+       return false;
+    }
+
+  /* Now all the data is in info.data.  Write it out to the BFD.  We
+     normally would need to worry about whether all the other sections
+     are set up yet, but the IEEE backend will handle this particular
+     case correctly regardless.  */
+  if (ieee_buffer_emptyp (&info.data))
+    {
+      /* There is no debugging information.  */
+      return true;
+    }
+  err = NULL;
+  s = bfd_make_section (abfd, ".debug");
+  if (s == NULL)
+    err = "bfd_make_section";
+  if (err == NULL)
+    {
+      if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS))
+       err = "bfd_set_section_flags";
+    }
+  if (err == NULL)
+    {
+      bfd_size_type size;
+
+      size = 0;
+      for (b = info.data.head; b != NULL; b = b->next)
+       size += b->c;
+      if (! bfd_set_section_size (abfd, s, size))
+       err = "bfd_set_section_size";
+    }
+  if (err == NULL)
+    {
+      file_ptr offset;
+
+      offset = 0;
+      for (b = info.data.head; b != NULL; b = b->next)
+       {
+         if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c))
+           {
+             err = "bfd_set_section_contents";
+             break;
+           }
+         offset += b->c;
+       }
+    }
+
+  if (err != NULL)
+    {
+      fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err,
+              bfd_errmsg (bfd_get_error ()));
+      return false;
+    }
+
+  bfd_hash_table_free (&info.typedefs.root);
+  bfd_hash_table_free (&info.tags.root);
+
+  return true;
+}
+
+/* Write out information for an undefined tag.  This is called via
+   ieee_name_type_hash_traverse.  */
+
+static boolean
+ieee_write_undefined_tag (h, p)
+     struct ieee_name_type_hash_entry *h;
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  struct ieee_name_type *nt;
+
+  for (nt = h->types; nt != NULL; nt = nt->next)
+    {
+      unsigned int name_indx;
+      char code;
+
+      if (nt->kind == DEBUG_KIND_ILLEGAL)
+       continue;
+
+      if (ieee_buffer_emptyp (&info->global_types))
+       {
+         if (! ieee_change_buffer (info, &info->global_types)
+             || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+             || ! ieee_write_byte (info, 2)
+             || ! ieee_write_number (info, 0)
+             || ! ieee_write_id (info, ""))
+           {
+             info->error = true;
+             return false;
+           }
+       }
+      else
+       {
+         if (! ieee_change_buffer (info, &info->global_types))
+           {
+             info->error = true;
+             return false;
+           }
+       }
+
+      name_indx = info->name_indx;
+      ++info->name_indx;
+      if (! ieee_write_byte (info, (int) ieee_nn_record)
+         || ! ieee_write_number (info, name_indx)
+         || ! ieee_write_id (info, nt->type.name)
+         || ! ieee_write_byte (info, (int) ieee_ty_record_enum)
+         || ! ieee_write_number (info, nt->type.indx)
+         || ! ieee_write_byte (info, 0xce)
+         || ! ieee_write_number (info, name_indx))
+       {
+         info->error = true;
+         return false;
+       }
+
+      switch (nt->kind)
+       {
+       default:
+         abort ();
+         info->error = true;
+         return false;
+       case DEBUG_KIND_STRUCT:
+       case DEBUG_KIND_CLASS:
+         code = 'S';
+         break;
+       case DEBUG_KIND_UNION:
+       case DEBUG_KIND_UNION_CLASS:
+         code = 'U';
+         break;
+       case DEBUG_KIND_ENUM:
+         code = 'E';
+         break;
+       }
+      if (! ieee_write_number (info, code)
+         || ! ieee_write_number (info, 0))
+       {
+         info->error = true;
+         return false;
+       }
+    }
+
+  return true;
+}
+
+/* Start writing out information for a compilation unit.  */
+
+static boolean
+ieee_start_compilation_unit (p, filename)
+     PTR p;
+     const char *filename;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  const char *modname;
+  char *c, *s;
+  unsigned int nindx;
+
+  if (info->filename != NULL)
+    {
+      if (! ieee_finish_compilation_unit (info))
+       return false;
+    }
+
+  info->filename = filename;
+  modname = strrchr (filename, '/');
+  if (modname != NULL)
+    ++modname;
+  else
+    {
+      modname = strrchr (filename, '\\');
+      if (modname != NULL)
+       ++modname;
+      else
+       modname = filename;
+    }
+  c = xstrdup (modname);
+  s = strrchr (c, '.');
+  if (s != NULL)
+    *s = '\0';
+  info->modname = c;
+
+  if (! ieee_init_buffer (info, &info->types)
+      || ! ieee_init_buffer (info, &info->vars)
+      || ! ieee_init_buffer (info, &info->cxx)
+      || ! ieee_init_buffer (info, &info->linenos))
+    return false;
+  info->ranges = NULL;
+
+  /* Always include a BB1 and a BB3 block.  That is what the output of
+     the MRI linker seems to look like.  */
+  if (! ieee_change_buffer (info, &info->types)
+      || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+      || ! ieee_write_byte (info, 1)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_id (info, info->modname))
+    return false;
+
+  nindx = info->name_indx;
+  ++info->name_indx;
+  if (! ieee_change_buffer (info, &info->vars)
+      || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+      || ! ieee_write_byte (info, 3)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_id (info, info->modname))
+    return false;
+
+  return true;
+}
+
+/* Finish up a compilation unit.  */
+
+static boolean
+ieee_finish_compilation_unit (info)
+     struct ieee_handle *info;
+{
+  struct ieee_range *r;
+
+  if (! ieee_buffer_emptyp (&info->types))
+    {
+      if (! ieee_change_buffer (info, &info->types)
+         || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+       return false;
+    }
+
+  if (! ieee_buffer_emptyp (&info->cxx))
+    {
+      /* Append any C++ information to the global function and
+         variable information.  */
+      assert (! ieee_buffer_emptyp (&info->vars));
+      if (! ieee_change_buffer (info, &info->vars))
+       return false;
+
+      /* We put the pmisc records in a dummy procedure, just as the
+         MRI compiler does.  */
+      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+         || ! ieee_write_byte (info, 6)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_id (info, "__XRYCPP")
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_number (info, info->highaddr - 1)
+         || ! ieee_append_buffer (info, &info->vars, &info->cxx)
+         || ! ieee_change_buffer (info, &info->vars)
+         || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+         || ! ieee_write_number (info, info->highaddr - 1))
+       return false;
+    }
+
+  if (! ieee_buffer_emptyp (&info->vars))
+    {
+      if (! ieee_change_buffer (info, &info->vars)
+         || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+       return false;
+    }
+
+  if (info->pending_lineno_filename != NULL)
+    {
+      /* Force out the pending line number.  */
+      if (! ieee_lineno ((PTR) info, (const char *) NULL, 0, (bfd_vma) -1))
+       return false;
+    }
+  if (! ieee_buffer_emptyp (&info->linenos))
+    {
+      if (! ieee_change_buffer (info, &info->linenos)
+         || ! ieee_write_byte (info, (int) ieee_be_record_enum))
+       return false;
+      if (strcmp (info->filename, info->lineno_filename) != 0)
+       {
+         /* We were not in the main file.  We just closed the
+             included line number block, and now we must close the
+             main line number block.  */
+         if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+           return false;
+       }
+    }
+
+  if (! ieee_append_buffer (info, &info->data, &info->types)
+      || ! ieee_append_buffer (info, &info->data, &info->vars)
+      || ! ieee_append_buffer (info, &info->data, &info->linenos))
+    return false;
+
+  /* Build BB10/BB11 blocks based on the ranges we recorded.  */
+  if (! ieee_change_buffer (info, &info->data))
+    return false;
+
+  if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+      || ! ieee_write_byte (info, 10)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_id (info, info->modname)
+      || ! ieee_write_id (info, "")
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_id (info, "GNU objcopy"))
+    return false;
+
+  for (r = info->ranges; r != NULL; r = r->next)
+    {
+      bfd_vma low, high;
+      asection *s;
+      int kind;
+
+      low = r->low;
+      high = r->high;
+
+      /* Find the section corresponding to this range.  */
+      for (s = info->abfd->sections; s != NULL; s = s->next)
+       {
+         if (bfd_get_section_vma (info->abfd, s) <= low
+             && high <= (bfd_get_section_vma (info->abfd, s)
+                         + bfd_section_size (info->abfd, s)))
+           break;
+       }
+
+      if (s == NULL)
+       {
+         /* Just ignore this range.  */
+         continue;
+       }
+
+      /* Coalesce ranges if it seems reasonable.  */
+      while (r->next != NULL
+            && high + 0x1000 >= r->next->low
+            && (r->next->high
+                <= (bfd_get_section_vma (info->abfd, s)
+                    + bfd_section_size (info->abfd, s))))
+       {
+         r = r->next;
+         high = r->high;
+       }
+
+      if ((s->flags & SEC_CODE) != 0)
+       kind = 1;
+      else if ((s->flags & SEC_READONLY) != 0)
+       kind = 3;
+      else
+       kind = 2;
+
+      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+         || ! ieee_write_byte (info, 11)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_id (info, "")
+         || ! ieee_write_number (info, kind)
+         || ! ieee_write_number (info, s->index + IEEE_SECTION_NUMBER_BASE)
+         || ! ieee_write_number (info, low)
+         || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+         || ! ieee_write_number (info, high - low))
+       return false;
+
+      /* Add this range to the list of global ranges.  */
+      if (! ieee_add_range (info, true, low, high))
+       return false;
+    }
+
+  if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+    return false;
+
+  return true;
+}
+
+/* Add BB11 blocks describing each range that we have not already
+   described.  */
+
+static void
+ieee_add_bb11_blocks (abfd, sec, data)
+     bfd *abfd;
+     asection *sec;
+     PTR data;
+{
+  struct ieee_handle *info = (struct ieee_handle *) data;
+  bfd_vma low, high;
+  struct ieee_range *r;
+
+  low = bfd_get_section_vma (abfd, sec);
+  high = low + bfd_section_size (abfd, sec);
+
+  /* Find the first range at or after this section.  The ranges are
+     sorted by address.  */
+  for (r = info->global_ranges; r != NULL; r = r->next)
+    if (r->high > low)
+      break;
+
+  while (low < high)
+    {
+      if (r == NULL || r->low >= high)
+       {
+         if (! ieee_add_bb11 (info, sec, low, high))
+           info->error = true;
+         return;
+       }
+
+      if (low < r->low
+         && r->low - low > 0x100)
+       {
+         if (! ieee_add_bb11 (info, sec, low, r->low))
+           {
+             info->error = true;
+             return;
+           }
+       }
+      low = r->high;
+
+      r = r->next;
+    }
+}
+
+/* Add a single BB11 block for a range.  We add it to info->vars.  */
+
+static boolean
+ieee_add_bb11 (info, sec, low, high)
+     struct ieee_handle *info;
+     asection *sec;
+     bfd_vma low;
+     bfd_vma high;
+{
+  int kind;
+
+  if (! ieee_buffer_emptyp (&info->vars))
+    {
+      if (! ieee_change_buffer (info, &info->vars))
+       return false;
+    }
+  else
+    {
+      const char *filename, *modname;
+      char *c, *s;
+
+      /* Start the enclosing BB10 block.  */
+      filename = bfd_get_filename (info->abfd);
+      modname = strrchr (filename, '/');
+      if (modname != NULL)
+       ++modname;
+      else
+       {
+         modname = strrchr (filename, '\\');
+         if (modname != NULL)
+           ++modname;
+         else
+           modname = filename;
+       }
+      c = xstrdup (modname);
+      s = strrchr (c, '.');
+      if (s != NULL)
+       *s = '\0';
+
+      if (! ieee_change_buffer (info, &info->vars)
+         || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+         || ! ieee_write_byte (info, 10)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_id (info, c)
+         || ! ieee_write_id (info, "")
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_id (info, "GNU objcopy"))
+       return false;
+
+      free (c);
+    }
+
+  if ((sec->flags & SEC_CODE) != 0)
+    kind = 1;
+  else if ((sec->flags & SEC_READONLY) != 0)
+    kind = 3;
+  else
+    kind = 2;
+
+  if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+      || ! ieee_write_byte (info, 11)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_id (info, "")
+      || ! ieee_write_number (info, kind)
+      || ! ieee_write_number (info, sec->index + IEEE_SECTION_NUMBER_BASE)
+      || ! ieee_write_number (info, low)
+      || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+      || ! ieee_write_number (info, high - low))
+    return false;
+
+  return true;
+}
+
+/* Start recording information from a particular source file.  This is
+   used to record which file defined which types, variables, etc.  It
+   is not used for line numbers, since the lineno entry point passes
+   down the file name anyhow.  IEEE debugging information doesn't seem
+   to store this information anywhere.  */
+
+/*ARGSUSED*/
+static boolean
+ieee_start_source (p, filename)
+     PTR p;
+     const char *filename;
+{
+  return true;
+}
+
+/* Make an empty type.  */
+
+static boolean
+ieee_empty_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  return ieee_push_type (info, (int) builtin_unknown, 0, false, false);
+}
+
+/* Make a void type.  */
+
+static boolean
+ieee_void_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  return ieee_push_type (info, (int) builtin_void, 0, false, false);
+}
+
+/* Make an integer type.  */
+
+static boolean
+ieee_int_type (p, size, unsignedp)
+     PTR p;
+     unsigned int size;
+     boolean unsignedp;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int indx;
+
+  switch (size)
+    {
+    case 1:
+      indx = (int) builtin_signed_char;
+      break;
+    case 2:
+      indx = (int) builtin_signed_short_int;
+      break;
+    case 4:
+      indx = (int) builtin_signed_long;
+      break;
+    case 8:
+      indx = (int) builtin_signed_long_long;
+      break;
+    default:
+      fprintf (stderr, _("IEEE unsupported integer type size %u\n"), size);
+      return false;
+    }
+
+  if (unsignedp)
+    ++indx;
+
+  return ieee_push_type (info, indx, size, unsignedp, false);
+}
+
+/* Make a floating point type.  */
+
+static boolean
+ieee_float_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int indx;
+
+  switch (size)
+    {
+    case 4:
+      indx = (int) builtin_float;
+      break;
+    case 8:
+      indx = (int) builtin_double;
+      break;
+    case 12:
+      /* FIXME: This size really depends upon the processor.  */
+      indx = (int) builtin_long_double;
+      break;
+    case 16:
+      indx = (int) builtin_long_long_double;
+      break;
+    default:
+      fprintf (stderr, _("IEEE unsupported float type size %u\n"), size);
+      return false;
+    }
+
+  return ieee_push_type (info, indx, size, false, false);
+}
+
+/* Make a complex type.  */
+
+static boolean
+ieee_complex_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  char code;
+
+  switch (size)
+    {
+    case 4:
+      if (info->complex_float_index != 0)
+       return ieee_push_type (info, info->complex_float_index, size * 2,
+                              false, false);
+      code = 'c';
+      break;
+    case 12:
+    case 16:
+      /* These cases can be output by gcc -gstabs.  Outputting the
+         wrong type is better than crashing.  */
+    case 8:
+      if (info->complex_double_index != 0)
+       return ieee_push_type (info, info->complex_double_index, size * 2,
+                              false, false);
+      code = 'd';
+      break;
+    default:
+      fprintf (stderr, _("IEEE unsupported complex type size %u\n"), size);
+      return false;
+    }
+
+  /* FIXME: I don't know what the string is for.  */
+  if (! ieee_define_type (info, size * 2, false, false)
+      || ! ieee_write_number (info, code)
+      || ! ieee_write_id (info, ""))
+    return false;
+
+  if (size == 4)
+    info->complex_float_index = info->type_stack->type.indx;
+  else
+    info->complex_double_index = info->type_stack->type.indx;
+
+  return true;
+}
+
+/* Make a boolean type.  IEEE doesn't support these, so we just make
+   an integer type instead.  */
+
+static boolean
+ieee_bool_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  return ieee_int_type (p, size, true);
+}
+
+/* Make an enumeration.  */
+
+static boolean
+ieee_enum_type (p, tag, names, vals)
+     PTR p;
+     const char *tag;
+     const char **names;
+     bfd_signed_vma *vals;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  struct ieee_defined_enum *e;
+  boolean localp, simple;
+  unsigned int indx;
+  int i = 0;
+
+  localp = false;
+  indx = (unsigned int) -1;
+  for (e = info->enums; e != NULL; e = e->next)
+    {
+      if (tag == NULL)
+       {
+         if (e->tag != NULL)
+           continue;
+       }
+      else
+       {
+         if (e->tag == NULL
+             || tag[0] != e->tag[0]
+             || strcmp (tag, e->tag) != 0)
+           continue;
+       }
+
+      if (! e->defined)
+       {
+         /* This enum tag has been seen but not defined.  */
+         indx = e->indx;
+         break;
+       }
+
+      if (names != NULL && e->names != NULL)
+       {
+         for (i = 0; names[i] != NULL && e->names[i] != NULL; i++)
+           {
+             if (names[i][0] != e->names[i][0]
+                 || vals[i] != e->vals[i]
+                 || strcmp (names[i], e->names[i]) != 0)
+               break;
+           }
+       }
+
+      if ((names == NULL && e->names == NULL)
+         || (names != NULL
+             && e->names != NULL
+             && names[i] == NULL
+             && e->names[i] == NULL))
+       {
+         /* We've seen this enum before.  */
+         return ieee_push_type (info, e->indx, 0, true, false);
+       }
+
+      if (tag != NULL)
+       {
+         /* We've already seen an enum of the same name, so we must make
+            sure to output this one locally.  */
+         localp = true;
+         break;
+       }
+    }
+
+  /* If this is a simple enumeration, in which the values start at 0
+     and always increment by 1, we can use type E.  Otherwise we must
+     use type N.  */
+
+  simple = true;
+  if (names != NULL)
+    {
+      for (i = 0; names[i] != NULL; i++)
+       {
+         if (vals[i] != i)
+           {
+             simple = false;
+             break;
+           }
+       }
+    }
+
+  if (! ieee_define_named_type (info, tag, indx, 0, true, localp,
+                               (struct ieee_buflist *) NULL)
+      || ! ieee_write_number (info, simple ? 'E' : 'N'))
+    return false;
+  if (simple)
+    {
+      /* FIXME: This is supposed to be the enumeration size, but we
+         don't store that.  */
+      if (! ieee_write_number (info, 4))
+       return false;
+    }
+  if (names != NULL)
+    {
+      for (i = 0; names[i] != NULL; i++)
+       {
+         if (! ieee_write_id (info, names[i]))
+           return false;
+         if (! simple)
+           {
+             if (! ieee_write_number (info, vals[i]))
+               return false;
+           }
+       }
+    }
+
+  if (! localp)
+    {
+      if (indx == (unsigned int) -1)
+       {
+         e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
+         memset (e, 0, sizeof *e);
+         e->indx = info->type_stack->type.indx;
+         e->tag = tag;
+
+         e->next = info->enums;
+         info->enums = e;
+       }
+
+      e->names = names;
+      e->vals = vals;
+      e->defined = true;
+    }
+
+  return true;
+}
+
+/* Make a pointer type.  */
+
+static boolean
+ieee_pointer_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  boolean localp;
+  unsigned int indx;
+  struct ieee_modified_type *m = NULL;
+
+  localp = info->type_stack->type.localp;
+  indx = ieee_pop_type (info);
+
+  /* A pointer to a simple builtin type can be obtained by adding 32.
+     FIXME: Will this be a short pointer, and will that matter?  */
+  if (indx < 32)
+    return ieee_push_type (info, indx + 32, 0, true, false);
+
+  if (! localp)
+    {
+      m = ieee_get_modified_info (p, indx);
+      if (m == NULL)
+       return false;
+
+      /* FIXME: The size should depend upon the architecture.  */
+      if (m->pointer > 0)
+       return ieee_push_type (info, m->pointer, 4, true, false);
+    }
+
+  if (! ieee_define_type (info, 4, true, localp)
+      || ! ieee_write_number (info, 'P')
+      || ! ieee_write_number (info, indx))
+    return false;
+
+  if (! localp)
+    m->pointer = info->type_stack->type.indx;
+
+  return true;
+}
+
+/* Make a function type.  This will be called for a method, but we
+   don't want to actually add it to the type table in that case.  We
+   handle this by defining the type in a private buffer, and only
+   adding that buffer to the typedef block if we are going to use it.  */
+
+static boolean
+ieee_function_type (p, argcount, varargs)
+     PTR p;
+     int argcount;
+     boolean varargs;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  boolean localp;
+  unsigned int *args = NULL;
+  int i;
+  unsigned int retindx;
+  struct ieee_buflist fndef;
+  struct ieee_modified_type *m;
+
+  localp = false;
+
+  if (argcount > 0)
+    {
+      args = (unsigned int *) xmalloc (argcount * sizeof *args);
+      for (i = argcount - 1; i >= 0; i--)
+       {
+         if (info->type_stack->type.localp)
+           localp = true;
+         args[i] = ieee_pop_type (info);
+       }
+    }
+  else if (argcount < 0)
+    varargs = false;
+
+  if (info->type_stack->type.localp)
+    localp = true;
+  retindx = ieee_pop_type (info);
+
+  m = NULL;
+  if (argcount < 0 && ! localp)
+    {
+      m = ieee_get_modified_info (p, retindx);
+      if (m == NULL)
+       return false;
+
+      if (m->function > 0)
+       return ieee_push_type (info, m->function, 0, true, false);
+    }
+
+  /* An attribute of 0x41 means that the frame and push mask are
+     unknown.  */
+  if (! ieee_init_buffer (info, &fndef)
+      || ! ieee_define_named_type (info, (const char *) NULL,
+                                  (unsigned int) -1, 0, true, localp,
+                                  &fndef)
+      || ! ieee_write_number (info, 'x')
+      || ! ieee_write_number (info, 0x41)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_number (info, retindx)
+      || ! ieee_write_number (info, (bfd_vma) argcount + (varargs ? 1 : 0)))
+    return false;
+  if (argcount > 0)
+    {
+      for (i = 0; i < argcount; i++)
+       if (! ieee_write_number (info, args[i]))
+         return false;
+      free (args);
+    }
+  if (varargs)
+    {
+      /* A varargs function is represented by writing out the last
+         argument as type void *, although this makes little sense.  */
+      if (! ieee_write_number (info, (bfd_vma) builtin_void + 32))
+       return false;
+    }
+
+  if (! ieee_write_number (info, 0))
+    return false;
+
+  /* We wrote the information into fndef, in case we don't need it.
+     It will be appended to info->types by ieee_pop_type.  */
+  info->type_stack->type.fndef = fndef;
+
+  if (m != NULL)
+    m->function = info->type_stack->type.indx;
+
+  return true;
+}
+
+/* Make a reference type.  */
+
+static boolean
+ieee_reference_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  /* IEEE appears to record a normal pointer type, and then use a
+     pmisc record to indicate that it is really a reference.  */
+
+  if (! ieee_pointer_type (p))
+    return false;
+  info->type_stack->type.referencep = true;
+  return true;
+}
+
+/* Make a range type.  */
+
+static boolean
+ieee_range_type (p, low, high)
+     PTR p;
+     bfd_signed_vma low;
+     bfd_signed_vma high;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int size;
+  boolean unsignedp, localp;
+
+  size = info->type_stack->type.size;
+  unsignedp = info->type_stack->type.unsignedp;
+  localp = info->type_stack->type.localp;
+  ieee_pop_unused_type (info);
+  return (ieee_define_type (info, size, unsignedp, localp)
+         && ieee_write_number (info, 'R')
+         && ieee_write_number (info, (bfd_vma) low)
+         && ieee_write_number (info, (bfd_vma) high)
+         && ieee_write_number (info, unsignedp ? 0 : 1)
+         && ieee_write_number (info, size));
+}
+
+/* Make an array type.  */
+
+/*ARGSUSED*/
+static boolean
+ieee_array_type (p, low, high, stringp)
+     PTR p;
+     bfd_signed_vma low;
+     bfd_signed_vma high;
+     boolean stringp;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int eleindx;
+  boolean localp;
+  unsigned int size;
+  struct ieee_modified_type *m = NULL;
+  struct ieee_modified_array_type *a;
+
+  /* IEEE does not store the range, so we just ignore it.  */
+  ieee_pop_unused_type (info);
+  localp = info->type_stack->type.localp;
+  size = info->type_stack->type.size;
+  eleindx = ieee_pop_type (info);
+
+  /* If we don't know the range, treat the size as exactly one
+     element.  */
+  if (low < high)
+    size *= (high - low) + 1;
+
+  if (! localp)
+    {
+      m = ieee_get_modified_info (info, eleindx);
+      if (m == NULL)
+       return false;
+
+      for (a = m->arrays; a != NULL; a = a->next)
+       {
+         if (a->low == low && a->high == high)
+           return ieee_push_type (info, a->indx, size, false, false);
+       }
+    }
+
+  if (! ieee_define_type (info, size, false, localp)
+      || ! ieee_write_number (info, low == 0 ? 'Z' : 'C')
+      || ! ieee_write_number (info, eleindx))
+    return false;
+  if (low != 0)
+    {
+      if (! ieee_write_number (info, low))
+       return false;
+    }
+
+  if (! ieee_write_number (info, high + 1))
+    return false;
+
+  if (! localp)
+    {
+      a = (struct ieee_modified_array_type *) xmalloc (sizeof *a);
+      memset (a, 0, sizeof *a);
+
+      a->indx = info->type_stack->type.indx;
+      a->low = low;
+      a->high = high;
+
+      a->next = m->arrays;
+      m->arrays = a;
+    }
+
+  return true;
+}
+
+/* Make a set type.  */
+
+static boolean
+ieee_set_type (p, bitstringp)
+     PTR p;
+     boolean bitstringp;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  boolean localp;
+  unsigned int eleindx;
+
+  localp = info->type_stack->type.localp;
+  eleindx = ieee_pop_type (info);
+
+  /* FIXME: We don't know the size, so we just use 4.  */
+
+  return (ieee_define_type (info, 0, true, localp)
+         && ieee_write_number (info, 's')
+         && ieee_write_number (info, 4)
+         && ieee_write_number (info, eleindx));
+}
+
+/* Make an offset type.  */
+
+static boolean
+ieee_offset_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int targetindx, baseindx;
+
+  targetindx = ieee_pop_type (info);
+  baseindx = ieee_pop_type (info);
+
+  /* FIXME: The MRI C++ compiler does not appear to generate any
+     useful type information about an offset type.  It just records a
+     pointer to member as an integer.  The MRI/HP IEEE spec does
+     describe a pmisc record which can be used for a pointer to
+     member.  Unfortunately, it does not describe the target type,
+     which seems pretty important.  I'm going to punt this for now.  */
+
+  return ieee_int_type (p, 4, true);
+}  
+
+/* Make a method type.  */
+
+static boolean
+ieee_method_type (p, domain, argcount, varargs)
+     PTR p;
+     boolean domain;
+     int argcount;
+     boolean varargs;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  /* FIXME: The MRI/HP IEEE spec defines a pmisc record to use for a
+     method, but the definition is incomplete.  We just output an 'x'
+     type.  */
+
+  if (domain)
+    ieee_pop_unused_type (info);
+
+  return ieee_function_type (p, argcount, varargs);
+}
+
+/* Make a const qualified type.  */
+
+static boolean
+ieee_const_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int size;
+  boolean unsignedp, localp;
+  unsigned int indx;
+  struct ieee_modified_type *m = NULL;
+
+  size = info->type_stack->type.size;
+  unsignedp = info->type_stack->type.unsignedp;
+  localp = info->type_stack->type.localp;
+  indx = ieee_pop_type (info);
+
+  if (! localp)
+    {
+      m = ieee_get_modified_info (info, indx);
+      if (m == NULL)
+       return false;
+
+      if (m->const_qualified > 0)
+       return ieee_push_type (info, m->const_qualified, size, unsignedp,
+                              false);
+    }
+
+  if (! ieee_define_type (info, size, unsignedp, localp)
+      || ! ieee_write_number (info, 'n')
+      || ! ieee_write_number (info, 1)
+      || ! ieee_write_number (info, indx))
+    return false;
+
+  if (! localp)
+    m->const_qualified = info->type_stack->type.indx;
+
+  return true;
+}
+
+/* Make a volatile qualified type.  */
+
+static boolean
+ieee_volatile_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int size;
+  boolean unsignedp, localp;
+  unsigned int indx;
+  struct ieee_modified_type *m = NULL;
+
+  size = info->type_stack->type.size;
+  unsignedp = info->type_stack->type.unsignedp;
+  localp = info->type_stack->type.localp;
+  indx = ieee_pop_type (info);
+
+  if (! localp)
+    {
+      m = ieee_get_modified_info (info, indx);
+      if (m == NULL)
+       return false;
+
+      if (m->volatile_qualified > 0)
+       return ieee_push_type (info, m->volatile_qualified, size, unsignedp,
+                              false);
+    }
+
+  if (! ieee_define_type (info, size, unsignedp, localp)
+      || ! ieee_write_number (info, 'n')
+      || ! ieee_write_number (info, 2)
+      || ! ieee_write_number (info, indx))
+    return false;
+
+  if (! localp)
+    m->volatile_qualified = info->type_stack->type.indx;
+
+  return true;
+}
+
+/* Convert an enum debug_visibility into a CXXFLAGS value.  */
+
+static unsigned int
+ieee_vis_to_flags (visibility)
+     enum debug_visibility visibility;
+{
+  switch (visibility)
+    {
+    default:
+      abort ();
+    case DEBUG_VISIBILITY_PUBLIC:
+      return CXXFLAGS_VISIBILITY_PUBLIC;
+    case DEBUG_VISIBILITY_PRIVATE:
+      return CXXFLAGS_VISIBILITY_PRIVATE;
+    case DEBUG_VISIBILITY_PROTECTED:
+      return CXXFLAGS_VISIBILITY_PROTECTED;
+    }
+  /*NOTREACHED*/
+}
+
+/* Start defining a struct type.  We build it in the strdef field on
+   the stack, to avoid confusing type definitions required by the
+   fields with the struct type itself.  */
+
+static boolean
+ieee_start_struct_type (p, tag, id, structp, size)
+     PTR p;
+     const char *tag;
+     unsigned int id;
+     boolean structp;
+     unsigned int size;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  boolean localp, ignorep;
+  boolean copy;
+  char ab[20];
+  const char *look;
+  struct ieee_name_type_hash_entry *h;
+  struct ieee_name_type *nt, *ntlook;
+  struct ieee_buflist strdef;
+
+  localp = false;
+  ignorep = false;
+
+  /* We need to create a tag for internal use even if we don't want
+     one for external use.  This will let us refer to an anonymous
+     struct.  */
+  if (tag != NULL)
+    {
+      look = tag;
+      copy = false;
+    }
+  else
+    {
+      sprintf (ab, "__anon%u", id);
+      look = ab;
+      copy = true;
+    }
+
+  /* If we already have references to the tag, we must use the
+     existing type index.  */
+  h = ieee_name_type_hash_lookup (&info->tags, look, true, copy);
+  if (h == NULL)
+    return false;
+
+  nt = NULL;
+  for (ntlook = h->types; ntlook != NULL; ntlook = ntlook->next)
+    {
+      if (ntlook->id == id)
+       nt = ntlook;
+      else if (! ntlook->type.localp)
+       {
+         /* We are creating a duplicate definition of a globally
+            defined tag.  Force it to be local to avoid
+            confusion.  */
+         localp = true;
+       }
+    }
+
+  if (nt != NULL)
+    {
+      assert (localp == nt->type.localp);
+      if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp)
+       {
+         /* We've already seen a global definition of the type.
+             Ignore this new definition.  */
+         ignorep = true;
+       }
+    }
+  else
+    {
+      nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+      memset (nt, 0, sizeof *nt);
+      nt->id = id;
+      nt->type.name = h->root.string;
+      nt->next = h->types;
+      h->types = nt;
+      nt->type.indx = info->type_indx;
+      ++info->type_indx;
+    }
+
+  nt->kind = DEBUG_KIND_ILLEGAL;
+
+  if (! ieee_init_buffer (info, &strdef)
+      || ! ieee_define_named_type (info, tag, nt->type.indx, size, true,
+                                  localp, &strdef)
+      || ! ieee_write_number (info, structp ? 'S' : 'U')
+      || ! ieee_write_number (info, size))
+    return false;
+
+  if (! ignorep)
+    {
+      const char *hold;
+
+      /* We never want nt->type.name to be NULL.  We want the rest of
+        the type to be the object set up on the type stack; it will
+        have a NULL name if tag is NULL.  */
+      hold = nt->type.name;
+      nt->type = info->type_stack->type;
+      nt->type.name = hold;
+    }
+
+  info->type_stack->type.name = tag;
+  info->type_stack->type.strdef = strdef;
+  info->type_stack->type.ignorep = ignorep;
+
+  return true;
+}
+
+/* Add a field to a struct.  */
+
+static boolean
+ieee_struct_field (p, name, bitpos, bitsize, visibility)
+     PTR p;
+     const char *name;
+     bfd_vma bitpos;
+     bfd_vma bitsize;
+     enum debug_visibility visibility;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int size;
+  boolean unsignedp;
+  boolean referencep;
+  boolean localp;
+  unsigned int indx;
+  bfd_vma offset;
+
+  assert (info->type_stack != NULL
+         && info->type_stack->next != NULL
+         && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
+
+  /* If we are ignoring this struct definition, just pop and ignore
+     the type.  */
+  if (info->type_stack->next->type.ignorep)
+    {
+      ieee_pop_unused_type (info);
+      return true;
+    }
+
+  size = info->type_stack->type.size;
+  unsignedp = info->type_stack->type.unsignedp;
+  referencep = info->type_stack->type.referencep;
+  localp = info->type_stack->type.localp;
+  indx = ieee_pop_type (info);
+
+  if (localp)
+    info->type_stack->type.localp = true;
+
+  if (info->type_stack->type.classdef != NULL)
+    {
+      unsigned int flags;
+      unsigned int nindx;
+
+      /* This is a class.  We must add a description of this field to
+         the class records we are building.  */
+
+      flags = ieee_vis_to_flags (visibility);
+      nindx = info->type_stack->type.classdef->indx;
+      if (! ieee_change_buffer (info,
+                               &info->type_stack->type.classdef->pmiscbuf)
+         || ! ieee_write_asn (info, nindx, 'd')
+         || ! ieee_write_asn (info, nindx, flags)
+         || ! ieee_write_atn65 (info, nindx, name)
+         || ! ieee_write_atn65 (info, nindx, name))
+       return false;
+      info->type_stack->type.classdef->pmisccount += 4;
+
+      if (referencep)
+       {
+         unsigned int nindx;
+
+         /* We need to output a record recording that this field is
+             really of reference type.  We put this on the refs field
+             of classdef, so that it can be appended to the C++
+             records after the class is defined.  */
+
+         nindx = info->name_indx;
+         ++info->name_indx;
+
+         if (! ieee_change_buffer (info,
+                                   &info->type_stack->type.classdef->refs)
+             || ! ieee_write_byte (info, (int) ieee_nn_record)
+             || ! ieee_write_number (info, nindx)
+             || ! ieee_write_id (info, "")
+             || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+             || ! ieee_write_number (info, nindx)
+             || ! ieee_write_number (info, 0)
+             || ! ieee_write_number (info, 62)
+             || ! ieee_write_number (info, 80)
+             || ! ieee_write_number (info, 4)
+             || ! ieee_write_asn (info, nindx, 'R')
+             || ! ieee_write_asn (info, nindx, 3)
+             || ! ieee_write_atn65 (info, nindx, info->type_stack->type.name)
+             || ! ieee_write_atn65 (info, nindx, name))
+           return false;
+       }
+    }
+
+  /* If the bitsize doesn't match the expected size, we need to output
+     a bitfield type.  */
+  if (size == 0 || bitsize == 0 || bitsize == size * 8)
+    offset = bitpos / 8;
+  else
+    {
+      if (! ieee_define_type (info, 0, unsignedp,
+                             info->type_stack->type.localp)
+         || ! ieee_write_number (info, 'g')
+         || ! ieee_write_number (info, unsignedp ? 0 : 1)
+         || ! ieee_write_number (info, bitsize)
+         || ! ieee_write_number (info, indx))
+       return false;
+      indx = ieee_pop_type (info);
+      offset = bitpos;
+    }
+
+  /* Switch to the struct we are building in order to output this
+     field definition.  */
+  return (ieee_change_buffer (info, &info->type_stack->type.strdef)
+         && ieee_write_id (info, name)
+         && ieee_write_number (info, indx)
+         && ieee_write_number (info, offset));
+}
+
+/* Finish up a struct type.  */
+
+static boolean
+ieee_end_struct_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  struct ieee_buflist *pb;
+
+  assert (info->type_stack != NULL
+         && ! ieee_buffer_emptyp (&info->type_stack->type.strdef));
+
+  /* If we were ignoring this struct definition because it was a
+     duplicate defintion, just through away whatever bytes we have
+     accumulated.  Leave the type on the stack. */
+  if (info->type_stack->type.ignorep)
+    return true;
+
+  /* If this is not a duplicate definition of this tag, then localp
+     will be false, and we can put it in the global type block.
+     FIXME: We should avoid outputting duplicate definitions which are
+     the same.  */
+  if (! info->type_stack->type.localp)
+    {
+      /* Make sure we have started the global type block.  */
+      if (ieee_buffer_emptyp (&info->global_types))
+       {
+         if (! ieee_change_buffer (info, &info->global_types)
+             || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+             || ! ieee_write_byte (info, 2)
+             || ! ieee_write_number (info, 0)
+             || ! ieee_write_id (info, ""))
+           return false;
+       }
+      pb = &info->global_types;
+    }
+  else
+    {
+      /* Make sure we have started the types block.  */
+      if (ieee_buffer_emptyp (&info->types))
+       {
+         if (! ieee_change_buffer (info, &info->types)
+             || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+             || ! ieee_write_byte (info, 1)
+             || ! ieee_write_number (info, 0)
+             || ! ieee_write_id (info, info->modname))
+           return false;
+       }
+      pb = &info->types;
+    }
+
+  /* Append the struct definition to the types.  */
+  if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef)
+      || ! ieee_init_buffer (info, &info->type_stack->type.strdef))
+    return false;
+
+  /* Leave the struct on the type stack.  */
+
+  return true;
+}
+
+/* Start a class type.  */
+
+static boolean
+ieee_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+     PTR p;
+     const char *tag;
+     unsigned int id;
+     boolean structp;
+     unsigned int size;
+     boolean vptr;
+     boolean ownvptr;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  const char *vclass;
+  struct ieee_buflist pmiscbuf;
+  unsigned int indx;
+  struct ieee_type_class *classdef;
+
+  /* A C++ class is output as a C++ struct along with a set of pmisc
+     records describing the class.  */
+
+  /* We need to have a name so that we can associate the struct and
+     the class.  */
+  if (tag == NULL)
+    {
+      char *t;
+
+      t = (char *) xmalloc (20);
+      sprintf (t, "__anon%u", id);
+      tag = t;
+    }
+
+  /* We can't write out the virtual table information until we have
+     finished the class, because we don't know the virtual table size.
+     We get the size from the largest voffset we see.  */
+  vclass = NULL;
+  if (vptr && ! ownvptr)
+    {
+      vclass = info->type_stack->type.name;
+      assert (vclass != NULL);
+      /* We don't call ieee_pop_unused_type, since the class should
+         get defined.  */
+      (void) ieee_pop_type (info);
+    }
+
+  if (! ieee_start_struct_type (p, tag, id, structp, size))
+    return false;
+
+  indx = info->name_indx;
+  ++info->name_indx;
+
+  /* We write out pmisc records into the classdef field.  We will
+     write out the pmisc start after we know the number of records we
+     need.  */
+  if (! ieee_init_buffer (info, &pmiscbuf)
+      || ! ieee_change_buffer (info, &pmiscbuf)
+      || ! ieee_write_asn (info, indx, 'T')
+      || ! ieee_write_asn (info, indx, structp ? 'o' : 'u')
+      || ! ieee_write_atn65 (info, indx, tag))
+    return false;
+
+  classdef = (struct ieee_type_class *) xmalloc (sizeof *classdef);
+  memset (classdef, 0, sizeof *classdef);
+
+  classdef->indx = indx;
+  classdef->pmiscbuf = pmiscbuf;
+  classdef->pmisccount = 3;
+  classdef->vclass = vclass;
+  classdef->ownvptr = ownvptr;
+
+  info->type_stack->type.classdef = classdef;
+
+  return true;
+}
+
+/* Add a static member to a class.  */
+
+static boolean
+ieee_class_static_member (p, name, physname, visibility)
+     PTR p;
+     const char *name;
+     const char *physname;
+     enum debug_visibility visibility;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int flags;
+  unsigned int nindx;
+
+  /* We don't care about the type.  Hopefully there will be a call to
+     ieee_variable declaring the physical name and the type, since
+     that is where an IEEE consumer must get the type.  */
+  ieee_pop_unused_type (info);
+
+  assert (info->type_stack != NULL
+         && info->type_stack->type.classdef != NULL);
+
+  flags = ieee_vis_to_flags (visibility);
+  flags |= CXXFLAGS_STATIC;
+
+  nindx = info->type_stack->type.classdef->indx;
+
+  if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
+      || ! ieee_write_asn (info, nindx, 'd')
+      || ! ieee_write_asn (info, nindx, flags)
+      || ! ieee_write_atn65 (info, nindx, name)
+      || ! ieee_write_atn65 (info, nindx, physname))
+    return false;
+  info->type_stack->type.classdef->pmisccount += 4;
+
+  return true;
+}
+
+/* Add a base class to a class.  */
+
+static boolean
+ieee_class_baseclass (p, bitpos, virtual, visibility)
+     PTR p;
+     bfd_vma bitpos;
+     boolean virtual;
+     enum debug_visibility visibility;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  const char *bname;
+  boolean localp;
+  unsigned int bindx;
+  char *fname;
+  unsigned int flags;
+  unsigned int nindx;
+
+  assert (info->type_stack != NULL
+         && info->type_stack->type.name != NULL
+         && info->type_stack->next != NULL
+         && info->type_stack->next->type.classdef != NULL
+         && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef));
+
+  bname = info->type_stack->type.name;
+  localp = info->type_stack->type.localp;
+  bindx = ieee_pop_type (info);
+
+  /* We are currently defining both a struct and a class.  We must
+     write out a field definition in the struct which holds the base
+     class.  The stabs debugging reader will create a field named
+     _vb$CLASS for a virtual base class, so we just use that.  FIXME:
+     we should not depend upon a detail of stabs debugging.  */
+  if (virtual)
+    {
+      fname = (char *) xmalloc (strlen (bname) + sizeof "_vb$");
+      sprintf (fname, "_vb$%s", bname);
+      flags = BASEFLAGS_VIRTUAL;
+    }
+  else
+    {
+      if (localp)
+       info->type_stack->type.localp = true;
+
+      fname = (char *) xmalloc (strlen (bname) + sizeof "_b$");
+      sprintf (fname, "_b$%s", bname);
+
+      if (! ieee_change_buffer (info, &info->type_stack->type.strdef)
+         || ! ieee_write_id (info, fname)
+         || ! ieee_write_number (info, bindx)
+         || ! ieee_write_number (info, bitpos / 8))
+       return false;
+      flags = 0;
+    }
+
+  if (visibility == DEBUG_VISIBILITY_PRIVATE)
+    flags |= BASEFLAGS_PRIVATE;
+
+  nindx = info->type_stack->type.classdef->indx;
+
+  if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf)
+      || ! ieee_write_asn (info, nindx, 'b')
+      || ! ieee_write_asn (info, nindx, flags)
+      || ! ieee_write_atn65 (info, nindx, bname)
+      || ! ieee_write_asn (info, nindx, 0)
+      || ! ieee_write_atn65 (info, nindx, fname))
+    return false;
+  info->type_stack->type.classdef->pmisccount += 5;
+
+  free (fname);
+
+  return true;
+}
+
+/* Start building a method for a class.  */
+
+static boolean
+ieee_class_start_method (p, name)
+     PTR p;
+     const char *name;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  assert (info->type_stack != NULL
+         && info->type_stack->type.classdef != NULL
+         && info->type_stack->type.classdef->method == NULL);
+
+  info->type_stack->type.classdef->method = name;
+
+  return true;
+}
+
+/* Define a new method variant, either static or not.  */
+
+static boolean
+ieee_class_method_var (info, physname, visibility, staticp, constp,
+                      volatilep, voffset, context)
+     struct ieee_handle *info;
+     const char *physname;
+     enum debug_visibility visibility;
+     boolean staticp;
+     boolean constp;
+     boolean volatilep;
+     bfd_vma voffset;
+     boolean context;
+{
+  unsigned int flags;
+  unsigned int nindx;
+  boolean virtual;
+
+  /* We don't need the type of the method.  An IEEE consumer which
+     wants the type must track down the function by the physical name
+     and get the type from that.  */
+  ieee_pop_unused_type (info);
+
+  /* We don't use the context.  FIXME: We probably ought to use it to
+     adjust the voffset somehow, but I don't really know how.  */
+  if (context)
+    ieee_pop_unused_type (info);
+
+  assert (info->type_stack != NULL
+         && info->type_stack->type.classdef != NULL
+         && info->type_stack->type.classdef->method != NULL);
+
+  flags = ieee_vis_to_flags (visibility);
+
+  /* FIXME: We never set CXXFLAGS_OVERRIDE, CXXFLAGS_OPERATOR,
+     CXXFLAGS_CTORDTOR, CXXFLAGS_CTOR, or CXXFLAGS_INLINE.  */
+
+  if (staticp)
+    flags |= CXXFLAGS_STATIC;
+  if (constp)
+    flags |= CXXFLAGS_CONST;
+  if (volatilep)
+    flags |= CXXFLAGS_VOLATILE;
+
+  nindx = info->type_stack->type.classdef->indx;
+
+  virtual = context || voffset > 0;
+
+  if (! ieee_change_buffer (info,
+                           &info->type_stack->type.classdef->pmiscbuf)
+      || ! ieee_write_asn (info, nindx, virtual ? 'v' : 'm')
+      || ! ieee_write_asn (info, nindx, flags)
+      || ! ieee_write_atn65 (info, nindx,
+                            info->type_stack->type.classdef->method)
+      || ! ieee_write_atn65 (info, nindx, physname))
+    return false;
+
+  if (virtual)
+    {
+      if (voffset > info->type_stack->type.classdef->voffset)
+       info->type_stack->type.classdef->voffset = voffset;
+      if (! ieee_write_asn (info, nindx, voffset))
+       return false;
+      ++info->type_stack->type.classdef->pmisccount;
+    }
+
+  if (! ieee_write_asn (info, nindx, 0))
+    return false;
+
+  info->type_stack->type.classdef->pmisccount += 5;
+
+  return true;
+}
+
+/* Define a new method variant.  */
+
+static boolean
+ieee_class_method_variant (p, physname, visibility, constp, volatilep,
+                          voffset, context)
+     PTR p;
+     const char *physname;
+     enum debug_visibility visibility;
+     boolean constp;
+     boolean volatilep;
+     bfd_vma voffset;
+     boolean context;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  return ieee_class_method_var (info, physname, visibility, false, constp,
+                               volatilep, voffset, context);
+}
+
+/* Define a new static method variant.  */
+
+static boolean
+ieee_class_static_method_variant (p, physname, visibility, constp, volatilep)
+     PTR p;
+     const char *physname;
+     enum debug_visibility visibility;
+     boolean constp;
+     boolean volatilep;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  return ieee_class_method_var (info, physname, visibility, true, constp,
+                               volatilep, 0, false);
+}
+
+/* Finish up a method.  */
+
+static boolean
+ieee_class_end_method (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  assert (info->type_stack != NULL
+         && info->type_stack->type.classdef != NULL
+         && info->type_stack->type.classdef->method != NULL);
+
+  info->type_stack->type.classdef->method = NULL;
+
+  return true;
+}
+
+/* Finish up a class.  */
+
+static boolean
+ieee_end_class_type (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int nindx;
+
+  assert (info->type_stack != NULL
+         && info->type_stack->type.classdef != NULL);
+
+  /* If we were ignoring this class definition because it was a
+     duplicate definition, just through away whatever bytes we have
+     accumulated.  Leave the type on the stack.  */
+  if (info->type_stack->type.ignorep)
+    return true;
+
+  nindx = info->type_stack->type.classdef->indx;
+
+  /* If we have a virtual table, we can write out the information now.  */
+  if (info->type_stack->type.classdef->vclass != NULL
+      || info->type_stack->type.classdef->ownvptr)
+    {
+      if (! ieee_change_buffer (info,
+                               &info->type_stack->type.classdef->pmiscbuf)
+         || ! ieee_write_asn (info, nindx, 'z')
+         || ! ieee_write_atn65 (info, nindx, "")
+         || ! ieee_write_asn (info, nindx,
+                              info->type_stack->type.classdef->voffset))
+       return false;
+      if (info->type_stack->type.classdef->ownvptr)
+       {
+         if (! ieee_write_atn65 (info, nindx, ""))
+           return false;
+       }
+      else
+       {
+         if (! ieee_write_atn65 (info, nindx,
+                                 info->type_stack->type.classdef->vclass))
+           return false;
+       }
+      if (! ieee_write_asn (info, nindx, 0))
+       return false;
+      info->type_stack->type.classdef->pmisccount += 5;
+    }
+
+  /* Now that we know the number of pmisc records, we can write out
+     the atn62 which starts the pmisc records, and append them to the
+     C++ buffers.  */
+
+  if (! ieee_change_buffer (info, &info->cxx)
+      || ! ieee_write_byte (info, (int) ieee_nn_record)
+      || ! ieee_write_number (info, nindx)
+      || ! ieee_write_id (info, "")
+      || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+      || ! ieee_write_number (info, nindx)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_number (info, 62)
+      || ! ieee_write_number (info, 80)
+      || ! ieee_write_number (info,
+                             info->type_stack->type.classdef->pmisccount))
+    return false;
+
+  if (! ieee_append_buffer (info, &info->cxx,
+                           &info->type_stack->type.classdef->pmiscbuf))
+    return false;
+  if (! ieee_buffer_emptyp (&info->type_stack->type.classdef->refs))
+    {
+      if (! ieee_append_buffer (info, &info->cxx,
+                               &info->type_stack->type.classdef->refs))
+       return false;
+    }
+
+  return ieee_end_struct_type (p);
+}
+
+/* Push a previously seen typedef onto the type stack.  */
+
+static boolean
+ieee_typedef_type (p, name)
+     PTR p;
+     const char *name;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  struct ieee_name_type_hash_entry *h;
+  struct ieee_name_type *nt;
+
+  h = ieee_name_type_hash_lookup (&info->typedefs, name, false, false);
+
+  /* h should never be NULL, since that would imply that the generic
+     debugging code has asked for a typedef which it has not yet
+     defined.  */
+  assert (h != NULL);
+
+  /* We always use the most recently defined type for this name, which
+     will be the first one on the list.  */
+
+  nt = h->types;
+  if (! ieee_push_type (info, nt->type.indx, nt->type.size,
+                       nt->type.unsignedp, nt->type.localp))
+    return false;
+
+  /* Copy over any other type information we may have.  */
+  info->type_stack->type = nt->type;
+
+  return true;
+}
+
+/* Push a tagged type onto the type stack.  */
+
+static boolean
+ieee_tag_type (p, name, id, kind)
+     PTR p;
+     const char *name;
+     unsigned int id;
+     enum debug_type_kind kind;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  boolean localp;
+  boolean copy;
+  char ab[20];
+  struct ieee_name_type_hash_entry *h;
+  struct ieee_name_type *nt;
+
+  if (kind == DEBUG_KIND_ENUM)
+    {
+      struct ieee_defined_enum *e;
+
+      if (name == NULL)
+       abort ();
+      for (e = info->enums; e != NULL; e = e->next)
+       if (e->tag != NULL && strcmp (e->tag, name) == 0)
+         return ieee_push_type (info, e->indx, 0, true, false);
+
+      e = (struct ieee_defined_enum *) xmalloc (sizeof *e);
+      memset (e, 0, sizeof *e);
+
+      e->indx = info->type_indx;
+      ++info->type_indx;
+      e->tag = name;
+      e->defined = false;
+
+      e->next = info->enums;
+      info->enums = e;
+
+      return ieee_push_type (info, e->indx, 0, true, false);
+    }
+
+  localp = false;
+
+  copy = false;
+  if (name == NULL)
+    {
+      sprintf (ab, "__anon%u", id);
+      name = ab;
+      copy = true;
+    }
+
+  h = ieee_name_type_hash_lookup (&info->tags, name, true, copy);
+  if (h == NULL)
+    return false;
+
+  for (nt = h->types; nt != NULL; nt = nt->next)
+    {
+      if (nt->id == id)
+       {
+         if (! ieee_push_type (info, nt->type.indx, nt->type.size,
+                               nt->type.unsignedp, nt->type.localp))
+           return false;
+         /* Copy over any other type information we may have.  */
+         info->type_stack->type = nt->type;
+         return true;
+       }
+
+      if (! nt->type.localp)
+       {
+         /* This is a duplicate of a global type, so it must be
+             local. */
+         localp = true;
+       }
+    }
+
+  nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+  memset (nt, 0, sizeof *nt);
+
+  nt->id = id;
+  nt->type.name = h->root.string;
+  nt->type.indx = info->type_indx;
+  nt->type.localp = localp;
+  ++info->type_indx;
+  nt->kind = kind;
+
+  nt->next = h->types;
+  h->types = nt;
+
+  if (! ieee_push_type (info, nt->type.indx, 0, false, localp))
+    return false;
+
+  info->type_stack->type.name = h->root.string;
+
+  return true;
+}
+
+/* Output a typedef.  */
+
+static boolean
+ieee_typdef (p, name)
+     PTR p;
+     const char *name;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  struct ieee_write_type type;
+  unsigned int indx;
+  boolean found;
+  boolean localp;
+  struct ieee_name_type_hash_entry *h;
+  struct ieee_name_type *nt;
+
+  type = info->type_stack->type;
+  indx = type.indx;
+
+  /* If this is a simple builtin type using a builtin name, we don't
+     want to output the typedef itself.  We also want to change the
+     type index to correspond to the name being used.  We recognize
+     names used in stabs debugging output even if they don't exactly
+     correspond to the names used for the IEEE builtin types.  */
+  found = false;
+  if (indx <= (unsigned int) builtin_bcd_float)
+    {
+      switch ((enum builtin_types) indx)
+       {
+       default:
+         break;
+
+       case builtin_void:
+         if (strcmp (name, "void") == 0)
+           found = true;
+         break;
+
+       case builtin_signed_char:
+       case builtin_char:
+         if (strcmp (name, "signed char") == 0)
+           {
+             indx = (unsigned int) builtin_signed_char;
+             found = true;
+           }
+         else if (strcmp (name, "char") == 0)
+           {
+             indx = (unsigned int) builtin_char;
+             found = true;
+           }
+         break;
+
+       case builtin_unsigned_char:
+         if (strcmp (name, "unsigned char") == 0)
+           found = true;
+         break;
+
+       case builtin_signed_short_int:
+       case builtin_short:
+       case builtin_short_int:
+       case builtin_signed_short:
+         if (strcmp (name, "signed short int") == 0)
+           {
+             indx = (unsigned int) builtin_signed_short_int;
+             found = true;
+           }
+         else if (strcmp (name, "short") == 0)
+           {
+             indx = (unsigned int) builtin_short;
+             found = true;
+           }
+         else if (strcmp (name, "short int") == 0)
+           {
+             indx = (unsigned int) builtin_short_int;
+             found = true;
+           }
+         else if (strcmp (name, "signed short") == 0)
+           {
+             indx = (unsigned int) builtin_signed_short;
+             found = true;
+           }
+         break;
+
+       case builtin_unsigned_short_int:
+       case builtin_unsigned_short:
+         if (strcmp (name, "unsigned short int") == 0
+             || strcmp (name, "short unsigned int") == 0)
+           {
+             indx = builtin_unsigned_short_int;
+             found = true;
+           }
+         else if (strcmp (name, "unsigned short") == 0)
+           {
+             indx = builtin_unsigned_short;
+             found = true;
+           }
+         break;
+
+       case builtin_signed_long:
+       case builtin_int: /* FIXME: Size depends upon architecture.  */
+       case builtin_long:
+         if (strcmp (name, "signed long") == 0)
+           {
+             indx = builtin_signed_long;
+             found = true;
+           }
+         else if (strcmp (name, "int") == 0)
+           {
+             indx = builtin_int;
+             found = true;
+           }
+         else if (strcmp (name, "long") == 0
+                  || strcmp (name, "long int") == 0)
+           {
+             indx = builtin_long;
+             found = true;
+           }
+         break;
+
+       case builtin_unsigned_long:
+       case builtin_unsigned: /* FIXME: Size depends upon architecture.  */
+       case builtin_unsigned_int: /* FIXME: Like builtin_unsigned.  */
+         if (strcmp (name, "unsigned long") == 0
+             || strcmp (name, "long unsigned int") == 0)
+           {
+             indx = builtin_unsigned_long;
+             found = true;
+           }
+         else if (strcmp (name, "unsigned") == 0)
+           {
+             indx = builtin_unsigned;
+             found = true;
+           }
+         else if (strcmp (name, "unsigned int") == 0)
+           {
+             indx = builtin_unsigned_int;
+             found = true;
+           }
+         break;
+
+       case builtin_signed_long_long:
+         if (strcmp (name, "signed long long") == 0
+             || strcmp (name, "long long int") == 0)
+           found = true;
+         break;
+
+       case builtin_unsigned_long_long:
+         if (strcmp (name, "unsigned long long") == 0
+             || strcmp (name, "long long unsigned int") == 0)
+           found = true;
+         break;
+
+       case builtin_float:
+         if (strcmp (name, "float") == 0)
+           found = true;
+         break;
+
+       case builtin_double:
+         if (strcmp (name, "double") == 0)
+           found = true;
+         break;
+
+       case builtin_long_double:
+         if (strcmp (name, "long double") == 0)
+           found = true;
+         break;
+
+       case builtin_long_long_double:
+         if (strcmp (name, "long long double") == 0)
+           found = true;
+         break;
+       }
+
+      if (found)
+       type.indx = indx;
+    }
+
+  h = ieee_name_type_hash_lookup (&info->typedefs, name, true, false);
+  if (h == NULL)
+    return false;
+
+  /* See if we have already defined this type with this name.  */
+  localp = type.localp;
+  for (nt = h->types; nt != NULL; nt = nt->next)
+    {
+      if (nt->id == indx)
+       {
+         /* If this is a global definition, then we don't need to
+            do anything here.  */
+         if (! nt->type.localp)
+           {
+             ieee_pop_unused_type (info);
+             return true;
+           }
+       }
+      else
+       {
+         /* This is a duplicate definition, so make this one local.  */
+         localp = true;
+       }
+    }
+
+  /* We need to add a new typedef for this type.  */
+
+  nt = (struct ieee_name_type *) xmalloc (sizeof *nt);
+  memset (nt, 0, sizeof *nt);
+  nt->id = indx;
+  nt->type = type;
+  nt->type.name = name;
+  nt->type.localp = localp;
+  nt->kind = DEBUG_KIND_ILLEGAL;
+
+  nt->next = h->types;
+  h->types = nt;
+
+  if (found)
+    {
+      /* This is one of the builtin typedefs, so we don't need to
+         actually define it.  */
+      ieee_pop_unused_type (info);
+      return true;
+    }
+
+  indx = ieee_pop_type (info);
+
+  if (! ieee_define_named_type (info, name, (unsigned int) -1, type.size,
+                               type.unsignedp, localp,
+                               (struct ieee_buflist *) NULL)
+      || ! ieee_write_number (info, 'T')
+      || ! ieee_write_number (info, indx))
+    return false;
+
+  /* Remove the type we just added to the type stack.  This should not
+     be ieee_pop_unused_type, since the type is used, we just don't
+     need it now.  */
+  (void) ieee_pop_type (info);
+
+  return true;
+}
+
+/* Output a tag for a type.  We don't have to do anything here.  */
+
+static boolean
+ieee_tag (p, name)
+     PTR p;
+     const char *name;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  /* This should not be ieee_pop_unused_type, since we want the type
+     to be defined.  */
+  (void) ieee_pop_type (info);
+  return true;
+}
+
+/* Output an integer constant.  */
+
+static boolean
+ieee_int_constant (p, name, val)
+     PTR p;
+     const char *name;
+     bfd_vma val;
+{
+  /* FIXME.  */
+  return true;
+}
+
+/* Output a floating point constant.  */
+
+static boolean
+ieee_float_constant (p, name, val)
+     PTR p;
+     const char *name;
+     double val;
+{
+  /* FIXME.  */
+  return true;
+}
+
+/* Output a typed constant.  */
+
+static boolean
+ieee_typed_constant (p, name, val)
+     PTR p;
+     const char *name;
+     bfd_vma val;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  /* FIXME.  */
+  ieee_pop_unused_type (info);
+  return true;
+}
+
+/* Output a variable.  */
+
+static boolean
+ieee_variable (p, name, kind, val)
+     PTR p;
+     const char *name;
+     enum debug_var_kind kind;
+     bfd_vma val;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  unsigned int name_indx;
+  unsigned int size;
+  boolean referencep;
+  unsigned int type_indx;
+  boolean asn;
+  int refflag;
+
+  size = info->type_stack->type.size;
+  referencep = info->type_stack->type.referencep;
+  type_indx = ieee_pop_type (info);
+
+  assert (! ieee_buffer_emptyp (&info->vars));
+  if (! ieee_change_buffer (info, &info->vars))
+    return false;
+
+  name_indx = info->name_indx;
+  ++info->name_indx;
+
+  /* Write out an NN and an ATN record for this variable.  */
+  if (! ieee_write_byte (info, (int) ieee_nn_record)
+      || ! ieee_write_number (info, name_indx)
+      || ! ieee_write_id (info, name)
+      || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+      || ! ieee_write_number (info, name_indx)
+      || ! ieee_write_number (info, type_indx))
+    return false;
+  switch (kind)
+    {
+    default:
+      abort ();
+      return false;
+    case DEBUG_GLOBAL:
+      if (! ieee_write_number (info, 8)
+         || ! ieee_add_range (info, false, val, val + size))
+       return false;
+      refflag = 0;
+      asn = true;
+      break;
+    case DEBUG_STATIC:
+      if (! ieee_write_number (info, 3)
+         || ! ieee_add_range (info, false, val, val + size))
+       return false;
+      refflag = 1;
+      asn = true;
+      break;
+    case DEBUG_LOCAL_STATIC:
+      if (! ieee_write_number (info, 3)
+         || ! ieee_add_range (info, false, val, val + size))
+       return false;
+      refflag = 2;
+      asn = true;
+      break;
+    case DEBUG_LOCAL:
+      if (! ieee_write_number (info, 1)
+         || ! ieee_write_number (info, val))
+       return false;
+      refflag = 2;
+      asn = false;
+      break;
+    case DEBUG_REGISTER:
+      if (! ieee_write_number (info, 2)
+         || ! ieee_write_number (info,
+                                 ieee_genreg_to_regno (info->abfd, val)))
+       return false;
+      refflag = 2;
+      asn = false;
+      break;
+    }
+
+  if (asn)
+    {
+      if (! ieee_write_asn (info, name_indx, val))
+       return false;
+    }
+
+  /* If this is really a reference type, then we just output it with
+     pointer type, and must now output a C++ record indicating that it
+     is really reference type.  */
+  if (referencep)
+    {
+      unsigned int nindx;
+
+      nindx = info->name_indx;
+      ++info->name_indx;
+
+      /* If this is a global variable, we want to output the misc
+         record in the C++ misc record block.  Otherwise, we want to
+         output it just after the variable definition, which is where
+         the current buffer is.  */
+      if (refflag != 2)
+       {
+         if (! ieee_change_buffer (info, &info->cxx))
+           return false;
+       }
+
+      if (! ieee_write_byte (info, (int) ieee_nn_record)
+         || ! ieee_write_number (info, nindx)
+         || ! ieee_write_id (info, "")
+         || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+         || ! ieee_write_number (info, nindx)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_number (info, 62)
+         || ! ieee_write_number (info, 80)
+         || ! ieee_write_number (info, 3)
+         || ! ieee_write_asn (info, nindx, 'R')
+         || ! ieee_write_asn (info, nindx, refflag)
+         || ! ieee_write_atn65 (info, nindx, name))
+       return false;
+    }
+
+  return true;
+}
+
+/* Start outputting information for a function.  */
+
+static boolean
+ieee_start_function (p, name, global)
+     PTR p;
+     const char *name;
+     boolean global;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  boolean referencep;
+  unsigned int retindx, typeindx;
+
+  referencep = info->type_stack->type.referencep;
+  retindx = ieee_pop_type (info);
+
+  /* Besides recording a BB4 or BB6 block, we record the type of the
+     function in the BB1 typedef block.  We can't write out the full
+     type until we have seen all the parameters, so we accumulate it
+     in info->fntype and info->fnargs.  */
+  if (! ieee_buffer_emptyp (&info->fntype))
+    {
+      /* FIXME: This might happen someday if we support nested
+         functions.  */
+      abort ();
+    }
+
+  info->fnname = name;
+
+  /* An attribute of 0x40 means that the push mask is unknown.  */
+  if (! ieee_define_named_type (info, name, (unsigned int) -1, 0, false, true,
+                               &info->fntype)
+      || ! ieee_write_number (info, 'x')
+      || ! ieee_write_number (info, 0x40)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_number (info, 0)
+      || ! ieee_write_number (info, retindx))
+    return false;
+
+  typeindx = ieee_pop_type (info);
+
+  if (! ieee_init_buffer (info, &info->fnargs))
+    return false;
+  info->fnargcount = 0;
+
+  /* If the function return value is actually a reference type, we
+     must add a record indicating that.  */
+  if (referencep)
+    {
+      unsigned int nindx;
+
+      nindx = info->name_indx;
+      ++info->name_indx;
+      if (! ieee_change_buffer (info, &info->cxx)
+         || ! ieee_write_byte (info, (int) ieee_nn_record)
+         || ! ieee_write_number (info, nindx)
+         || ! ieee_write_id (info, "")
+         || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+         || ! ieee_write_number (info, nindx)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_number (info, 62)
+         || ! ieee_write_number (info, 80)
+         || ! ieee_write_number (info, 3)
+         || ! ieee_write_asn (info, nindx, 'R')
+         || ! ieee_write_asn (info, nindx, global ? 0 : 1)
+         || ! ieee_write_atn65 (info, nindx, name))
+       return false;
+    }
+
+  assert (! ieee_buffer_emptyp (&info->vars));
+  if (! ieee_change_buffer (info, &info->vars))
+    return false;
+
+  /* The address is written out as the first block.  */
+
+  ++info->block_depth;
+
+  return (ieee_write_byte (info, (int) ieee_bb_record_enum)
+         && ieee_write_byte (info, global ? 4 : 6)
+         && ieee_write_number (info, 0)
+         && ieee_write_id (info, name)
+         && ieee_write_number (info, 0)
+         && ieee_write_number (info, typeindx));
+}
+
+/* Add a function parameter.  This will normally be called before the
+   first block, so we postpone them until we see the block.  */
+
+static boolean
+ieee_function_parameter (p, name, kind, val)
+     PTR p;
+     const char *name;
+     enum debug_parm_kind kind;
+     bfd_vma val;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+  struct ieee_pending_parm *m, **pm;
+
+  assert (info->block_depth == 1);
+
+  m = (struct ieee_pending_parm *) xmalloc (sizeof *m);
+  memset (m, 0, sizeof *m);
+
+  m->next = NULL;
+  m->name = name;
+  m->referencep = info->type_stack->type.referencep;
+  m->type = ieee_pop_type (info);
+  m->kind = kind;
+  m->val = val;
+
+  for (pm = &info->pending_parms; *pm != NULL; pm = &(*pm)->next)
+    ;
+  *pm = m;
+
+  /* Add the type to the fnargs list.  */
+  if (! ieee_change_buffer (info, &info->fnargs)
+      || ! ieee_write_number (info, m->type))
+    return false;
+  ++info->fnargcount;
+
+  return true;  
+}
+
+/* Output pending function parameters.  */
+
+static boolean
+ieee_output_pending_parms (info)
+     struct ieee_handle *info;
+{
+  struct ieee_pending_parm *m;
+  unsigned int refcount;
+
+  refcount = 0;
+  for (m = info->pending_parms; m != NULL; m = m->next)
+    {
+      enum debug_var_kind vkind;
+
+      switch (m->kind)
+       {
+       default:
+         abort ();
+         return false;
+       case DEBUG_PARM_STACK:
+       case DEBUG_PARM_REFERENCE:
+         vkind = DEBUG_LOCAL;
+         break;
+       case DEBUG_PARM_REG:
+       case DEBUG_PARM_REF_REG:
+         vkind = DEBUG_REGISTER;
+         break;
+       }
+
+      if (! ieee_push_type (info, m->type, 0, false, false))
+       return false;
+      info->type_stack->type.referencep = m->referencep;
+      if (m->referencep)
+       ++refcount;
+      if (! ieee_variable ((PTR) info, m->name, vkind, m->val))
+       return false;
+    }
+
+  /* If there are any reference parameters, we need to output a
+     miscellaneous record indicating them.  */
+  if (refcount > 0)
+    {
+      unsigned int nindx, varindx;
+
+      /* FIXME: The MRI compiler outputs the demangled function name
+         here, but we are outputting the mangled name.  */
+      nindx = info->name_indx;
+      ++info->name_indx;
+      if (! ieee_change_buffer (info, &info->vars)
+         || ! ieee_write_byte (info, (int) ieee_nn_record)
+         || ! ieee_write_number (info, nindx)
+         || ! ieee_write_id (info, "")
+         || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+         || ! ieee_write_number (info, nindx)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_number (info, 62)
+         || ! ieee_write_number (info, 80)
+         || ! ieee_write_number (info, refcount + 3)
+         || ! ieee_write_asn (info, nindx, 'B')
+         || ! ieee_write_atn65 (info, nindx, info->fnname)
+         || ! ieee_write_asn (info, nindx, 0))
+       return false;
+      for (m = info->pending_parms, varindx = 1;
+          m != NULL;
+          m = m->next, varindx++)
+       {
+         if (m->referencep)
+           {
+             if (! ieee_write_asn (info, nindx, varindx))
+               return false;
+           }
+       }
+    }
+
+  m = info->pending_parms;
+  while (m != NULL)
+    {
+      struct ieee_pending_parm *next;
+
+      next = m->next;
+      free (m);
+      m = next;
+    }
+
+  info->pending_parms = NULL;
+
+  return true;
+}
+
+/* Start a block.  If this is the first block, we output the address
+   to finish the BB4 or BB6, and then output the function parameters.  */
+
+static boolean
+ieee_start_block (p, addr)
+     PTR p;
+     bfd_vma addr;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  if (! ieee_change_buffer (info, &info->vars))
+    return false;
+
+  if (info->block_depth == 1)
+    {
+      if (! ieee_write_number (info, addr)
+         || ! ieee_output_pending_parms (info))
+       return false;
+    }
+  else
+    {
+      if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+         || ! ieee_write_byte (info, 6)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_id (info, "")
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_number (info, addr))
+       return false;
+    }
+
+  if (! ieee_start_range (info, addr))
+    return false;
+
+  ++info->block_depth;
+
+  return true;
+}
+
+/* End a block.  */
+
+static boolean
+ieee_end_block (p, addr)
+     PTR p;
+     bfd_vma addr;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  /* The address we are given is the end of the block, but IEEE seems
+     to want to the address of the last byte in the block, so we
+     subtract one.  */
+  if (! ieee_change_buffer (info, &info->vars)
+      || ! ieee_write_byte (info, (int) ieee_be_record_enum)
+      || ! ieee_write_number (info, addr - 1))
+    return false;
+
+  if (! ieee_end_range (info, addr))
+    return false;
+
+  --info->block_depth;
+
+  if (addr > info->highaddr)
+    info->highaddr = addr;
+
+  return true;
+}
+
+/* End a function.  */
+
+static boolean
+ieee_end_function (p)
+     PTR p;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  assert (info->block_depth == 1);
+
+  --info->block_depth;
+
+  /* Now we can finish up fntype, and add it to the typdef section.
+     At this point, fntype is the 'x' type up to the argument count,
+     and fnargs is the argument types.  We must add the argument
+     count, and we must add the level.  FIXME: We don't record varargs
+     functions correctly.  In fact, stabs debugging does not give us
+     enough information to do so.  */
+  if (! ieee_change_buffer (info, &info->fntype)
+      || ! ieee_write_number (info, info->fnargcount)
+      || ! ieee_change_buffer (info, &info->fnargs)
+      || ! ieee_write_number (info, 0))
+    return false;
+
+  /* Make sure the typdef block has been started.  */
+  if (ieee_buffer_emptyp (&info->types))
+    {
+      if (! ieee_change_buffer (info, &info->types)
+         || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+         || ! ieee_write_byte (info, 1)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_id (info, info->modname))
+       return false;
+    }
+
+  if (! ieee_append_buffer (info, &info->types, &info->fntype)
+      || ! ieee_append_buffer (info, &info->types, &info->fnargs))
+    return false;
+
+  info->fnname = NULL;
+  if (! ieee_init_buffer (info, &info->fntype)
+      || ! ieee_init_buffer (info, &info->fnargs))
+    return false;
+  info->fnargcount = 0;
+
+  return true;
+}
+
+/* Record line number information.  */
+
+static boolean
+ieee_lineno (p, filename, lineno, addr)
+     PTR p;
+     const char *filename;
+     unsigned long lineno;
+     bfd_vma addr;
+{
+  struct ieee_handle *info = (struct ieee_handle *) p;
+
+  assert (info->filename != NULL);
+
+  /* The HP simulator seems to get confused when more than one line is
+     listed for the same address, at least if they are in different
+     files.  We handle this by always listing the last line for a
+     given address, since that seems to be the one that gdb uses.  */
+  if (info->pending_lineno_filename != NULL
+      && addr != info->pending_lineno_addr)
+    {
+      /* Make sure we have a line number block.  */
+      if (! ieee_buffer_emptyp (&info->linenos))
+       {
+         if (! ieee_change_buffer (info, &info->linenos))
+           return false;
+       }
+      else
+       {
+         info->lineno_name_indx = info->name_indx;
+         ++info->name_indx;
+         if (! ieee_change_buffer (info, &info->linenos)
+             || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+             || ! ieee_write_byte (info, 5)
+             || ! ieee_write_number (info, 0)
+             || ! ieee_write_id (info, info->filename)
+             || ! ieee_write_byte (info, (int) ieee_nn_record)
+             || ! ieee_write_number (info, info->lineno_name_indx)
+             || ! ieee_write_id (info, ""))
+           return false;
+         info->lineno_filename = info->filename;
+       }
+
+      if (strcmp (info->pending_lineno_filename, info->lineno_filename) != 0)
+       {
+         if (strcmp (info->filename, info->lineno_filename) != 0)
+           {
+             /* We were not in the main file.  Close the block for the
+                included file.  */
+             if (! ieee_write_byte (info, (int) ieee_be_record_enum))
+               return false;
+             if (strcmp (info->filename, info->pending_lineno_filename) == 0)
+               {
+                 /* We need a new NN record, and we aren't about to
+                    output one.  */
+                 info->lineno_name_indx = info->name_indx;
+                 ++info->name_indx;
+                 if (! ieee_write_byte (info, (int) ieee_nn_record)
+                     || ! ieee_write_number (info, info->lineno_name_indx)
+                     || ! ieee_write_id (info, ""))
+                   return false;
+               }
+           }
+         if (strcmp (info->filename, info->pending_lineno_filename) != 0)
+           {
+             /* We are not changing to the main file.  Open a block for
+                the new included file.  */
+             info->lineno_name_indx = info->name_indx;
+             ++info->name_indx;
+             if (! ieee_write_byte (info, (int) ieee_bb_record_enum)
+                 || ! ieee_write_byte (info, 5)
+                 || ! ieee_write_number (info, 0)
+                 || ! ieee_write_id (info, info->pending_lineno_filename)
+                 || ! ieee_write_byte (info, (int) ieee_nn_record)
+                 || ! ieee_write_number (info, info->lineno_name_indx)
+                 || ! ieee_write_id (info, ""))
+               return false;
+           }
+         info->lineno_filename = info->pending_lineno_filename;
+       }
+
+      if (! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+         || ! ieee_write_number (info, info->lineno_name_indx)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_number (info, 7)
+         || ! ieee_write_number (info, info->pending_lineno)
+         || ! ieee_write_number (info, 0)
+         || ! ieee_write_asn (info, info->lineno_name_indx,
+                              info->pending_lineno_addr))
+       return false;
+    }
+
+  info->pending_lineno_filename = filename;
+  info->pending_lineno = lineno;
+  info->pending_lineno_addr = addr;
+
+  return true;
+}
diff --git a/binutils/is-ranlib.c b/binutils/is-ranlib.c
new file mode 100644 (file)
index 0000000..fde72a4
--- /dev/null
@@ -0,0 +1,3 @@
+/* Linked with ar.o to flag that this program is 'ranlib' (not 'ar'). */
+
+int is_ranlib = 1;
diff --git a/binutils/is-strip.c b/binutils/is-strip.c
new file mode 100644 (file)
index 0000000..215341a
--- /dev/null
@@ -0,0 +1,4 @@
+/* Linked with objcopy.o to flag that this program is 'strip' (not
+   'objcopy'). */
+
+int is_strip = 1;
diff --git a/binutils/mac-binutils.r b/binutils/mac-binutils.r
new file mode 100644 (file)
index 0000000..7b1a303
--- /dev/null
@@ -0,0 +1,42 @@
+/* Resources for GNU binutils. */
+
+#include "SysTypes.r"
+
+/* Version resources. */
+
+resource 'vers' (1)  {
+       0,
+       0,
+       0,
+       0,
+       verUs,
+       VERSION_STRING,
+       VERSION_STRING  " (C) 1986-95 FSF, Inc."
+};
+
+resource 'vers' (2, purgeable)  {
+       0,
+       0,
+       0,
+       0,
+       verUs,
+       VERSION_STRING,
+       "binutils " VERSION_STRING " for MPW"
+};
+
+#ifdef WANT_CFRG
+
+#include "CodeFragmentTypes.r"
+
+resource 'cfrg' (0) {
+       {
+               kPowerPC,
+               kFullLib,
+               kNoVersionNum, kNoVersionNum,
+               0,0,
+               kIsApp, kOnDiskFlat, kZeroOffset, kWholeFork,
+               PROG_NAME
+       }
+};
+
+#endif /* WANT_CFRG */
diff --git a/binutils/makefile.vms-in b/binutils/makefile.vms-in
new file mode 100644 (file)
index 0000000..a809d1b
--- /dev/null
@@ -0,0 +1,98 @@
+#
+# Makefile for binutils under openVMS (Alpha and Vax)
+#
+# For use with gnu-make for vms
+#
+# Created by Klaus K"ampf, kkaempf@rmi.de
+#
+#
+
+# Distribution version, filled in by configure.com
+VERSION=@VERSION@
+
+ifeq ($(ARCH),ALPHA)
+TARGET=""vms-alpha""
+else
+TARGET=""vms-vax""
+endif
+
+ifeq ($(CC),gcc)
+CFLAGS=/include=([],[-.include],[-.bfd])$(DEFS)
+DEFS=/define=("TARGET=$(TARGET)")
+LIBS=,gnu_cc_library:libgcc/lib,sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj
+else
+CFLAGS=/noopt/debug/include=([],[-.include],[-.bfd])$(DEFS)\
+/warnings=disable=(missingreturn,implicitfunc,longextern)
+DEFS=/define=("TARGET=$(TARGET)","const=","unlink=remove")
+LIBS=,sys$$library:vaxcrtl.olb/lib
+endif
+
+BFDLIB = [-.bfd]libbfd.olb/lib
+BFDLIB_DEP = [-.bfd]libbfd.olb
+LIBIBERTY_DEP = [-.libiberty]libiberty.olb
+LIBIBERTY = [-.libiberty]libiberty.olb/lib
+OPCODES_DEP = [-.opcodes]libopcodes.olb
+OPCODES = [-.opcodes]libopcodes.olb/lib
+
+DEBUG_OBJS = rddbg.obj,debug.obj,stabs.obj,ieee.obj,rdcoff.obj
+
+WRITE_DEBUG_OBJS = $(DEBUG_OBJS),wrstabs.obj
+
+BULIBS = []bucomm.obj,version.obj,filemode.obj
+
+ADDL_DEPS = $(BULIBS),$(BFDLIB_DEP),$(LIBIBERTY_DEP)
+ADDL_LIBS = $(BULIBS),$(BFDLIB),$(LIBIBERTY)
+
+SIZEOBJS = $(ADDL_DEPS),size.obj
+
+STRINGSOBJS = $(ADDL_DEPS),strings.obj
+
+NMOBJS = $(ADDL_DEPS),nm.obj
+
+OBJDUMPOBJS = $(ADDL_DEPS),objdump.obj,prdbg.obj,$(DEBUG_OBJS),$(OPCODES_DEP)
+
+all: config.h size.exe strings.exe objdump.exe nm.exe
+
+size.exe: $(SIZEOBJS)
+       link/exe=$@ size.obj,$(ADDL_LIBS)$(LIBS)
+
+strings.exe: $(STRINGSOBJS)
+       link/exe=$@ strings.obj,$(ADDL_LIBS)$(LIBS)
+
+nm.exe: $(NMOBJS)
+       link/exe=$@ nm.obj,$(ADDL_LIBS)$(LIBS)
+
+objdump.exe: $(OBJDUMPOBJS)
+       link/exe=$@ objdump.obj,prdbg.obj,$(DEBUG_OBJS),$(BFDLIB),$(OPCODES),$(ADDL_LIBS)$(LIBS)
+
+
+version.obj: version.c
+       $(CC) $(CFLAGS)/define=(VERSION="""$(VERSION)""") $<
+
+config.h:
+       $$ @configure
+       $(MAKE) -f makefile.vms "CC=$(CC)"
+
+[-.bfd]libbfd.olb:
+       $(CD) [-.bfd]
+       $(MAKE) -f makefile.vms "CC=$(CC)"
+       $(CD) [-.binutils]
+
+[-.libiberty]libiberty.olb:
+       $(CD) [-.libiberty]
+       $(MAKE) -f makefile.vms "CC=$(CC)"
+       $(CD) [-.binutils]
+
+[-.opcodes]libopcodes.olb:
+       $(CD) [-.opcodes]
+       $(MAKE) -f makefile.vms "CC=$(CC)"
+       $(CD) [-.binutils]
+
+clean:
+       $$ purge
+       $(RM) *.obj;
+       $(RM) *.exe;
+
+distclean: clean
+       $(RM) config.h;
+       $(RM) makefile.vms;
diff --git a/binutils/maybe-ranlib.c b/binutils/maybe-ranlib.c
new file mode 100644 (file)
index 0000000..f37bc0f
--- /dev/null
@@ -0,0 +1,4 @@
+/* Linked with ar.o to flag that this program decides at runtime
+   (using argv[0] if it is is 'ar' or 'ranlib'. */
+
+int is_ranlib = -1;
diff --git a/binutils/maybe-strip.c b/binutils/maybe-strip.c
new file mode 100644 (file)
index 0000000..6467c99
--- /dev/null
@@ -0,0 +1,4 @@
+/* Linked with objcopy.o to flag that this program decides at runtime
+   (using argv[0] if it is is 'strip' or 'objcopy'. */
+
+int is_strip = -1;
diff --git a/binutils/mpw-config.in b/binutils/mpw-config.in
new file mode 100644 (file)
index 0000000..21a067d
--- /dev/null
@@ -0,0 +1,27 @@
+# Configuration fragment for binutils.
+
+Set target_arch `echo {target_canonical} | sed -e 's/-.*-.*//'`
+
+# (should canonicalize arch name) */
+
+Set archname ARCH_{target_arch}
+
+Set underscore 0
+
+If "{target_canonical}" =~ /sh-hitachi-hms/
+       Set underscore 1
+End If
+
+Echo '# From mpw-config.in'                             > "{o}"mk.tmp
+Echo "ARCHDEFS = -d" {archname}                                >> "{o}"mk.tmp
+Echo "UNDERSCORE = " {underscore}                      >> "{o}"mk.tmp
+Echo "BUILD_NLMCONV = "                                        >> "{o}"mk.tmp
+Echo "BUILD_SRCONV = "                                 >> "{o}"mk.tmp
+Echo "SYSINFO_PROG = "                                 >> "{o}"mk.tmp
+Echo "BUILD_DLLTOOL = "                                        >> "{o}"mk.tmp
+Echo '# End from mpw-config.in'                                >> "{o}"mk.tmp
+
+Echo '/* config.h.  Generated by mpw-configure.  */'    > "{o}"config.new
+Echo '#include "mpw.h"'                                        >> "{o}"config.new
+
+MoveIfChange "{o}"config.new "{o}"config.h
diff --git a/binutils/mpw-make.sed b/binutils/mpw-make.sed
new file mode 100644 (file)
index 0000000..03abffe
--- /dev/null
@@ -0,0 +1,115 @@
+# Sed commands to finish translating the binutils Unix makefile into MPW syntax.
+
+# Add a rule.
+/^#### .*/a\
+\
+"{o}"underscore.c.o \\Option-f "{o}"underscore.c\
+
+# Comment out any alias settings.
+/^host_alias =/s/^/#/
+/^target_alias =/s/^/#/
+
+# Whack out unused host define bits.
+/HDEFINES/s/@HDEFINES@//
+
+# Don't build specialized tools.
+/BUILD_NLMCONV/s/@BUILD_NLMCONV@//
+/BUILD_SRCONV/s/@BUILD_SRCONV@//
+/BUILD_DLLTOOL/s/@BUILD_DLLTOOL@//
+
+/UNDERSCORE/s/@UNDERSCORE@/{UNDERSCORE}/
+
+# Don't need this.
+/@HLDFLAGS@/s/@HLDFLAGS@//
+
+# Point at the libraries directly.
+/@BFDLIB@/s/@BFDLIB@/::bfd:libbfd.o/
+/@OPCODES@/s/@OPCODES@/::opcodes:libopcodes.o/
+
+# Whack out target makefile fragment.
+/target_makefile_fragment/s/target_makefile_fragment@//
+
+# Fix and add to the include paths.
+/^INCLUDES = .*$/s/$/ -i "{INCDIR}":mpw: -i ::extra-include:/
+/BFDDIR/s/-i {BFDDIR} /-i "{BFDDIR}": /
+/INCDIR/s/-i {INCDIR} /-i "{INCDIR}": /
+
+# Use byacc instead of bison (for now anyway).
+/BISON/s/^BISON =.*$/BISON = byacc/
+#/BISONFLAGS/s/^BISONFLAGS =.*$/BISONFLAGS = /
+
+# Embed the version in symbolic doublequotes that will expand to
+# the right thing for each compiler.
+/VERSION/s/'"{VERSION}"'/{dq}{VERSION}{dq}/
+
+# '+' is a special char to MPW, don't use it ever.
+/c++filt/s/c++filt/cplusfilt/
+
+# All of the binutils use the same Rez file, change names to refer to it.
+/^{[A-Z]*_PROG}/s/$/ "{s}"mac-binutils.r/
+/{[A-Z]*_PROG}\.r/s/{[A-Z]*_PROG}\.r/mac-binutils.r/
+
+# There are auto-generated references to BFD .h files that are not
+# in the objdir (like bfd.h) but are in the source dir.
+/::bfd:lib/s/::bfd:lib\([a-z]*\)\.h/{BFDDIR}:lib\1.h/g
+
+# Fix the locations of generated files.
+/config/s/"{s}"config\.h/"{o}"config.h/g
+/config/s/^config\.h/"{o}"config\.h/
+/underscore/s/"{s}"underscore\.c/"{o}"underscore.c/g
+/underscore/s/^underscore\.c/"{o}"underscore\.c/
+
+# Fix paths to generated source files.
+/lex.yy.c/s/"{s}"lex\.yy\.c/"{o}"lex.yy.c/g
+/lex.yy.c/s/^lex\.yy\.c/"{o}"lex.yy.c/
+/arlex.c/s/"{s}"arlex\.c/"{o}"arlex.c/g
+/arlex.c/s/^arlex\.c/"{o}"arlex.c/
+/y.tab.c/s/"{s}"y\.tab\.c/"{o}"y.tab.c/g
+/y.tab.c/s/^y\.tab\.c/"{o}"y.tab.c/
+/arparse.c/s/"{s}"arparse\.c/"{o}"arparse.c/g
+/arparse.c/s/^arparse\.c/"{o}"arparse.c/
+/y.tab.h/s/"{s}"y\.tab\.h/"{o}"y.tab.h/g
+/y.tab.h/s/^y\.tab\.h/"{o}"y.tab.h/
+/arparse.h/s/"{s}"arparse\.h/"{o}"arparse.h/g
+/arparse.h/s/^arparse\.h/"{o}"arparse.h/
+
+/"{s}"{INCDIR}/s/"{s}"{INCDIR}/"{INCDIR}"/g
+
+# The generated lexer may include an ifdef for older Mac compilers that
+# needs to work with newer compilers also.
+/lex.yy.c/s/Rename -y \([^ ]*\) \([^ ]*\)$/sed -e 's,ifdef macintosh,if defined(macintosh) || defined(__MWERKS__),' \1 > \2/
+
+# Fix an over-eagerness.
+/echo.*WARNING.*This file/s/'.*'/' '/
+
+# Add a "stamps" target.
+$a\
+stamps \\Option-f stamp-under\
+
+/^install \\Option-f /,/^$/c\
+install \\Option-f  all install-only\
+\
+install-only \\Option-f\
+       NewFolderRecursive "{bindir}"\
+       # Need to copy all the tools\
+       For prog in {PROGS}\
+               Set progname `echo {prog} | sed -e 's/.new//'`\
+               Duplicate -y :{prog} "{bindir}"{progname}\
+       End For\
+
+
+/true/s/ ; @true$//
+
+# dot files are trouble, remove them and their actions.
+/^\.dep/,/^$/d
+
+# Remove un-useful targets.
+/^Makefile \\Option-f/,/^$/d
+/^"{o}"config.h \\Option-f/,/^$/d
+/^config.status \\Option-f/,/^$/d
+
+# Don't try to make the demangler's man page, it's useless.
+/^{DEMANGLER_PROG}\.1 \\Option-f/,/^$/d
+# Don't depend on it either.
+/{DEMANGLER_PROG}/s/ {DEMANGLER_PROG}\.1//
+
diff --git a/binutils/nlmconv.1 b/binutils/nlmconv.1
new file mode 100644 (file)
index 0000000..cbc3aed
--- /dev/null
@@ -0,0 +1,110 @@
+.\" Copyright (c) 1991, 1996  Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH nlmconv 1 "March 1996" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+nlmconv \- converts object code into an NLM
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B nlmconv
+.RB "[\|" \-I\ \fIbfdname\fB\ |\ \-\-input\-target=\fIbfdname\fR "\|]" 
+.RB "[\|" \-O\ \fIbfdname\fB\ |\ \-\-output\-target=\fIbfdname\fR "\|]" 
+.RB "[\|" \-T\ \fIheaderfile\fB\ |\ \-\-header\-file=\fIheaderfile\fR "\|]" 
+.RB "[\|" \-V\ |\ \-\-version\fR "\|]" 
+.RB "[\|" \-\-help\fR "\|]" 
+.B infile
+.B outfile
+.SH DESCRIPTION
+.B nlmconv
+converts the relocatable object file 
+.B infile
+into the NetWare Loadable Module 
+.BR outfile ,
+optionally reading 
+.I headerfile
+for NLM header information.  For instructions on writing the NLM
+command file language used in header files, see 
+.IR "The NetWare Tool Maker Specification Manual" ,
+available from Novell, Inc.
+.B nlmconv
+currently works with i386 object files in 
+.BR COFF ,
+.BR ELF ,
+or
+.B a.out
+format, and with SPARC object files in
+.B ELF
+or
+.B a.out
+format.
+.br
+.B nlmconv
+uses the GNU Binary File Descriptor library to read 
+.IR infile .
+.SH OPTIONS
+.TP
+.B \-I \fIbfdname\fR, \fB\-\-input\-target=\fIbfdname
+Consider the source file's object format to be 
+.IR bfdname ,
+rather than attempting to deduce it.
+.TP
+.B \-O \fIbfdname\fR, \fB\-\-output\-target=\fIbfdname
+Write the output file using the object format 
+.IR bfdname .
+.B nlmconv
+infers the output format based on the input format, e.g. for an i386
+input file the output format is
+.IR nlm32\-i386 .
+.TP
+.B \-T \fIheaderfile\fR, \fB\-\-header\-file=\fIheaderfile
+Reads 
+.I headerfile
+for NLM header information.  For instructions on writing the NLM
+command file language used in header files, see 
+.IR "The NetWare Tool Maker Specification Manual" ,
+available from Novell, Inc.
+.TP
+.B \-V\fR, \fB\-\-version
+Show the version number of
+.B nlmconv
+and exit.
+.TP
+.B \-h\fR, \fB\-\-help
+Show a summary of the options to
+.B nlmconv
+and exit.
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'" 
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (June 1993).
+
+.SH COPYING
+Copyright (c) 1993 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/nlmconv.c b/binutils/nlmconv.c
new file mode 100644 (file)
index 0000000..f1c8b6c
--- /dev/null
@@ -0,0 +1,2212 @@
+/* nlmconv.c -- NLM conversion program
+   Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This program can be used to convert any appropriate object file
+   into a NetWare Loadable Module (an NLM).  It will accept a linker
+   specification file which is identical to that accepted by the
+   NetWare linker, NLMLINK.  */
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# ifdef _AIX
+ #pragma alloca
+#endif
+#endif
+
+#include "bfd.h"
+#include "libiberty.h"
+#include "bucomm.h"
+
+#include <ansidecl.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <assert.h>
+#include <getopt.h>
+
+/* Internal BFD NLM header.  */
+#include "libnlm.h"
+#include "nlmconv.h"
+
+#ifdef NLMCONV_ALPHA
+#include "coff/sym.h"
+#include "coff/ecoff.h"
+#endif
+
+/* If strerror is just a macro, we want to use the one from libiberty
+   since it will handle undefined values.  */
+#undef strerror
+extern char *strerror ();
+
+#ifndef localtime
+extern struct tm *localtime ();
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#endif
+\f
+/* Global variables.  */
+
+/* The name used to invoke the program.  */
+char *program_name;
+
+/* Local variables.  */
+
+/* Whether to print out debugging information (currently just controls
+   whether it prints the linker command if there is one).  */
+static int debug;
+
+/* The symbol table.  */
+static asymbol **symbols;
+
+/* A section we create in the output file to hold pointers to where
+   the sections of the input file end up.  We will put a pointer to
+   this section in the NLM header.  These is an entry for each input
+   section.  The format is
+       null terminated section name
+       zeroes to adjust to 4 byte boundary
+       4 byte section data file pointer
+       4 byte section size
+   We don't need a version number.  The way we find this information
+   is by finding a stamp in the NLM header information.  If we need to
+   change the format of this information, we can simply change the
+   stamp.  */
+static asection *secsec;
+
+/* A temporary file name to be unlinked on exit.  Actually, for most
+   errors, we leave it around.  It's not clear whether that is helpful
+   or not.  */
+static char *unlink_on_exit;
+
+/* The list of long options.  */
+static struct option long_options[] =
+{
+  { "debug", no_argument, 0, 'd' },
+  { "header-file", required_argument, 0, 'T' },
+  { "help", no_argument, 0, 'h' },
+  { "input-target", required_argument, 0, 'I' },
+  { "input-format", required_argument, 0, 'I' }, /* Obsolete */
+  { "linker", required_argument, 0, 'l' },
+  { "output-target", required_argument, 0, 'O' },
+  { "output-format", required_argument, 0, 'O' }, /* Obsolete */
+  { "version", no_argument, 0, 'V' },
+  { NULL, no_argument, 0, 0 }
+};
+
+/* Local routines.  */
+
+static void show_help PARAMS ((void));
+static void show_usage PARAMS ((FILE *, int));
+static const char *select_output_format PARAMS ((enum bfd_architecture,
+                                                unsigned long, boolean));
+static void setup_sections PARAMS ((bfd *, asection *, PTR));
+static void copy_sections PARAMS ((bfd *, asection *, PTR));
+static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
+                                  long *, char *,
+                                  bfd_size_type));
+static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
+                                          long *, char *,
+                                          bfd_size_type));
+static char *link_inputs PARAMS ((struct string_list *, char *));
+
+#ifdef NLMCONV_I386
+static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
+                                       long *, char *,
+                                       bfd_size_type));
+#endif
+
+#ifdef NLMCONV_ALPHA
+static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
+                                        long *, char *,
+                                        bfd_size_type));
+#endif
+
+#ifdef NLMCONV_POWERPC
+static void powerpc_build_stubs PARAMS ((bfd *, bfd *, asymbol ***, long *));
+static void powerpc_resolve_stubs PARAMS ((bfd *, bfd *));
+static void powerpc_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
+                                          long *, char *,
+                                          bfd_size_type));
+#endif
+\f
+/* The main routine.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int opt;
+  char *input_file = NULL;
+  const char *input_format = NULL;
+  const char *output_format = NULL;
+  const char *header_file = NULL;
+  char *ld_arg = NULL;
+  Nlm_Internal_Fixed_Header fixed_hdr_struct;
+  Nlm_Internal_Variable_Header var_hdr_struct;
+  Nlm_Internal_Version_Header version_hdr_struct;
+  Nlm_Internal_Copyright_Header copyright_hdr_struct;
+  Nlm_Internal_Extended_Header extended_hdr_struct;
+  bfd *inbfd;
+  bfd *outbfd;
+  asymbol **newsyms, **outsyms;
+  long symcount, newsymalloc, newsymcount;
+  long symsize;
+  asection *text_sec, *bss_sec, *data_sec;
+  bfd_vma vma;
+  bfd_size_type align;
+  asymbol *endsym;
+  long i;
+  char inlead, outlead;
+  boolean gotstart, gotexit, gotcheck;
+  struct stat st;
+  FILE *custom_data = NULL;
+  FILE *help_data = NULL;
+  FILE *message_data = NULL;
+  FILE *rpc_data = NULL;
+  FILE *shared_data = NULL;
+  size_t custom_size = 0;
+  size_t help_size = 0;
+  size_t message_size = 0;
+  size_t module_size = 0;
+  size_t rpc_size = 0;
+  asection *custom_section = NULL;
+  asection *help_section = NULL;
+  asection *message_section = NULL;
+  asection *module_section = NULL;
+  asection *rpc_section = NULL;
+  asection *shared_section = NULL;
+  bfd *sharedbfd;
+  size_t shared_offset = 0;
+  size_t shared_size = 0;
+  Nlm_Internal_Fixed_Header sharedhdr;
+  int len;
+  char *modname;
+  char **matching;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = argv[0];
+  xmalloc_set_program_name (program_name);
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options,
+                            (int *) NULL))
+        != EOF)
+    {
+      switch (opt)
+       {
+       case 'd':
+         debug = 1;
+         break;
+       case 'h':
+         show_help ();
+         /*NOTREACHED*/
+       case 'I':
+         input_format = optarg;
+         break;
+       case 'l':
+         ld_arg = optarg;
+         break;
+       case 'O':
+         output_format = optarg;
+         break;
+       case 'T':
+         header_file = optarg;
+         break;
+       case 'V':
+         print_version ("nlmconv");
+         /*NOTREACHED*/
+       case 0:
+         break;
+       default:
+         show_usage (stderr, 1);
+         /*NOTREACHED*/
+       }
+    }
+
+  /* The input and output files may be named on the command line.  */
+  output_file = NULL;
+  if (optind < argc)
+    {
+      input_file = argv[optind];
+      ++optind;
+      if (optind < argc)
+       {
+         output_file = argv[optind];
+         ++optind;
+         if (optind < argc)
+           show_usage (stderr, 1);
+         if (strcmp (input_file, output_file) == 0)
+           {
+             fprintf (stderr,
+                      _("%s: input and output files must be different\n"),
+                      program_name);
+             exit (1);
+           }
+       }
+    }
+
+  /* Initialize the header information to default values.  */
+  fixed_hdr = &fixed_hdr_struct;
+  memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct);
+  var_hdr = &var_hdr_struct;
+  memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct);
+  version_hdr = &version_hdr_struct;
+  memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct);
+  copyright_hdr = &copyright_hdr_struct;
+  memset ((PTR) &copyright_hdr_struct, 0, sizeof copyright_hdr_struct);
+  extended_hdr = &extended_hdr_struct;
+  memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct);
+  check_procedure = NULL;
+  custom_file = NULL;
+  debug_info = false;
+  exit_procedure = "_Stop";
+  export_symbols = NULL;
+  map_file = NULL;
+  full_map = false;
+  help_file = NULL;
+  import_symbols = NULL;
+  message_file = NULL;
+  modules = NULL;
+  sharelib_file = NULL;
+  start_procedure = "_Prelude";
+  verbose = false;
+  rpc_file = NULL;
+
+  parse_errors = 0;
+
+  /* Parse the header file (if there is one).  */
+  if (header_file != NULL)
+    {
+      if (! nlmlex_file (header_file)
+         || yyparse () != 0
+         || parse_errors != 0)
+       exit (1);
+    }
+
+  if (input_files != NULL)
+    {
+      if (input_file != NULL)
+       {
+         fprintf (stderr,
+                  _("%s: input file named both on command line and with INPUT\n"),
+                  program_name);
+         exit (1);
+       }
+      if (input_files->next == NULL)
+       input_file = input_files->string;
+      else
+       input_file = link_inputs (input_files, ld_arg);
+    }
+  else if (input_file == NULL)
+    {
+      fprintf (stderr, _("%s: no input file\n"), program_name);
+      show_usage (stderr, 1);
+    }
+
+  inbfd = bfd_openr (input_file, input_format);
+  if (inbfd == NULL)
+    bfd_fatal (input_file);
+
+  if (! bfd_check_format_matches (inbfd, bfd_object, &matching))
+    {
+      bfd_nonfatal (input_file);
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      exit (1);
+    }
+
+  if (output_format == NULL)
+    output_format = select_output_format (bfd_get_arch (inbfd),
+                                         bfd_get_mach (inbfd),
+                                         bfd_big_endian (inbfd));
+
+  assert (output_format != NULL);
+
+  /* Use the output file named on the command line if it exists.
+     Otherwise use the file named in the OUTPUT statement.  */
+  if (output_file == NULL)
+    {
+      fprintf (stderr, _("%s: no name for output file\n"),
+              program_name);
+      show_usage (stderr, 1);
+    }
+
+  outbfd = bfd_openw (output_file, output_format);
+  if (outbfd == NULL)
+    bfd_fatal (output_file);
+  if (! bfd_set_format (outbfd, bfd_object))
+    bfd_fatal (output_file);
+
+  assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour);
+
+  if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
+    fprintf (stderr,
+            _("%s: warning:input and output formats are not compatible\n"),
+            program_name);
+
+  /* Move the values read from the command file into outbfd.  */
+  *nlm_fixed_header (outbfd) = fixed_hdr_struct;
+  *nlm_variable_header (outbfd) = var_hdr_struct;
+  *nlm_version_header (outbfd) = version_hdr_struct;
+  *nlm_copyright_header (outbfd) = copyright_hdr_struct;
+  *nlm_extended_header (outbfd) = extended_hdr_struct;
+
+  /* Start copying the input BFD to the output BFD.  */
+  if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd)))
+    bfd_fatal (bfd_get_filename (outbfd));
+
+  symsize = bfd_get_symtab_upper_bound (inbfd);
+  if (symsize < 0)
+    bfd_fatal (input_file);
+  symbols = (asymbol **) xmalloc (symsize);
+  symcount = bfd_canonicalize_symtab (inbfd, symbols);
+  if (symcount < 0)
+    bfd_fatal (input_file);
+
+  /* Make sure we have a .bss section.  */
+  bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
+  if (bss_sec == NULL)
+    {
+      bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
+      if (bss_sec == NULL
+         || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
+         || ! bfd_set_section_alignment (outbfd, bss_sec, 1))
+       bfd_fatal (_("make .bss section"));
+    }
+
+  /* We store the original section names in the .nlmsections section,
+     so that programs which understand it can resurrect the original
+     sections from the NLM.  We will put a pointer to .nlmsections in
+     the NLM header area.  */
+  secsec = bfd_make_section (outbfd, ".nlmsections");
+  if (secsec == NULL)
+    bfd_fatal (_("make .nlmsections section"));
+  if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS))
+    bfd_fatal (_("set .nlmsections flags"));
+
+#ifdef NLMCONV_POWERPC
+  /* For PowerPC NetWare we need to build stubs for calls to undefined
+     symbols.  Because each stub requires an entry in the TOC section
+     which must be at the same location as other entries in the TOC
+     section, we must do this before determining where the TOC section
+     goes in setup_sections.  */
+  if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
+    powerpc_build_stubs (inbfd, outbfd, &symbols, &symcount);
+#endif
+
+  /* Set up the sections.  */
+  bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
+
+  text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME);
+
+  /* The .bss section immediately follows the .data section.  */
+  data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME);
+  if (data_sec != NULL)
+    {
+      bfd_size_type add;
+
+      vma = bfd_get_section_size_before_reloc (data_sec);
+      align = 1 << bss_sec->alignment_power;
+      add = ((vma + align - 1) &~ (align - 1)) - vma;
+      vma += add;
+      if (! bfd_set_section_vma (outbfd, bss_sec, vma))
+       bfd_fatal (_("set .bss vma"));
+      if (add != 0)
+       {
+         bfd_size_type data_size;
+
+         data_size = bfd_get_section_size_before_reloc (data_sec);
+         if (! bfd_set_section_size (outbfd, data_sec, data_size + add))
+           bfd_fatal (_("set .data size"));
+       }
+    }
+
+  /* Adjust symbol information.  */
+  inlead = bfd_get_symbol_leading_char (inbfd);
+  outlead = bfd_get_symbol_leading_char (outbfd);
+  gotstart = false;
+  gotexit = false;
+  gotcheck = false;
+  newsymalloc = 10;
+  newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
+  newsymcount = 0;
+  endsym = NULL;
+  for (i = 0; i < symcount; i++)
+    {
+      register asymbol *sym;
+
+      sym = symbols[i];
+
+      /* Add or remove a leading underscore.  */
+      if (inlead != outlead)
+       {
+         if (inlead != '\0')
+           {
+             if (bfd_asymbol_name (sym)[0] == inlead)
+               {
+                 if (outlead == '\0')
+                   ++sym->name;
+                 else
+                   {
+                     char *new;
+
+                     new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
+                     new[0] = outlead;
+                     strcpy (new + 1, bfd_asymbol_name (sym) + 1);
+                     sym->name = new;
+                   }
+               }
+           }
+         else
+           {
+             char *new;
+
+             new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
+             new[0] = outlead;
+             strcpy (new + 1, bfd_asymbol_name (sym));
+             sym->name = new;
+           }
+       }
+
+      /* NLM's have an uninitialized data section, but they do not
+        have a common section in the Unix sense.  Move all common
+        symbols into the .bss section, and mark them as exported.  */
+      if (bfd_is_com_section (bfd_get_section (sym)))
+       {
+         bfd_vma size;
+
+         sym->section = bss_sec;
+         size = sym->value;
+         sym->value = bss_sec->_raw_size;
+         bss_sec->_raw_size += size;
+         align = 1 << bss_sec->alignment_power;
+         bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1);
+         sym->flags |= BSF_EXPORT | BSF_GLOBAL;
+       }
+      else if (bfd_get_section (sym)->output_section != NULL)
+       {
+         /* Move the symbol into the output section.  */
+         sym->value += bfd_get_section (sym)->output_offset;
+         sym->section = bfd_get_section (sym)->output_section;
+         /* This is no longer a section symbol.  */
+         sym->flags &=~ BSF_SECTION_SYM;
+       }
+
+      /* Force _edata and _end to be defined.  This would normally be
+        done by the linker, but the manipulation of the common
+        symbols will confuse it.  */
+      if ((sym->flags & BSF_DEBUGGING) == 0
+         && bfd_asymbol_name (sym)[0] == '_'
+         && bfd_is_und_section (bfd_get_section (sym)))
+       {
+         if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
+           {
+             sym->section = bss_sec;
+             sym->value = 0;
+           }
+         if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
+           {
+             sym->section = bss_sec;
+             endsym = sym;
+           }
+
+#ifdef NLMCONV_POWERPC
+         /* For PowerPC NetWare, we define __GOT0.  This is the start
+            of the .got section.  */
+         if (bfd_get_arch (inbfd) == bfd_arch_powerpc
+             && strcmp (bfd_asymbol_name (sym), "__GOT0") == 0)
+           {
+             asection *got_sec;
+
+             got_sec = bfd_get_section_by_name (inbfd, ".got");
+             assert (got_sec != (asection *) NULL);
+             sym->value = got_sec->output_offset;
+             sym->section = got_sec->output_section;
+           }
+#endif
+       }
+
+      /* If this is a global symbol, check the export list.  */
+      if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
+       {
+         register struct string_list *l;
+         int found_simple;
+
+         /* Unfortunately, a symbol can appear multiple times on the
+            export list, with and without prefixes.  */
+         found_simple = 0;
+         for (l = export_symbols; l != NULL; l = l->next)
+           {
+             if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
+               found_simple = 1;
+             else
+               {
+                 char *zbase;
+
+                 zbase = strchr (l->string, '@');
+                 if (zbase != NULL
+                     && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
+                   {
+                     /* We must add a symbol with this prefix.  */
+                     if (newsymcount >= newsymalloc)
+                       {
+                         newsymalloc += 10;
+                         newsyms = ((asymbol **)
+                                    xrealloc ((PTR) newsyms,
+                                              (newsymalloc
+                                               * sizeof (asymbol *))));
+                       }
+                     newsyms[newsymcount] =
+                       (asymbol *) xmalloc (sizeof (asymbol));
+                     *newsyms[newsymcount] = *sym;
+                     newsyms[newsymcount]->name = l->string;
+                     ++newsymcount;
+                   }
+               }
+           }
+         if (! found_simple)
+           {
+             /* The unmodified symbol is actually not exported at
+                all.  */
+             sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
+             sym->flags |= BSF_LOCAL;
+           }
+       }
+
+      /* If it's an undefined symbol, see if it's on the import list.
+        Change the prefix if necessary.  */
+      if (bfd_is_und_section (bfd_get_section (sym)))
+       {
+         register struct string_list *l;
+
+         for (l = import_symbols; l != NULL; l = l->next)
+           {
+             if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
+               break;
+             else
+               {
+                 char *zbase;
+
+                 zbase = strchr (l->string, '@');
+                 if (zbase != NULL
+                     && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
+                   {
+                     sym->name = l->string;
+                     break;
+                   }
+               }
+           }
+         if (l == NULL)
+           fprintf (stderr,
+                    _("%s: warning: symbol %s imported but not in import list\n"),
+                    program_name, bfd_asymbol_name (sym));
+       }
+       
+      /* See if it's one of the special named symbols.  */
+      if ((sym->flags & BSF_DEBUGGING) == 0)
+       {
+         bfd_vma val;
+
+         /* FIXME: If these symbols are not in the .text section, we
+            add the .text section size to the value.  This may not be
+            correct for all targets.  I'm not sure how this should
+            really be handled.  */
+         if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
+           {
+             val = bfd_asymbol_value (sym);
+             if (bfd_get_section (sym) == data_sec
+                 && text_sec != (asection *) NULL)
+               val += bfd_section_size (outbfd, text_sec);
+             if (! bfd_set_start_address (outbfd, val))
+               bfd_fatal (_("set start address"));
+             gotstart = true;
+           }
+         if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
+           {
+             val = bfd_asymbol_value (sym);
+             if (bfd_get_section (sym) == data_sec
+                 && text_sec != (asection *) NULL)
+               val += bfd_section_size (outbfd, text_sec);
+             nlm_fixed_header (outbfd)->exitProcedureOffset = val;
+             gotexit = true;
+           }
+         if (check_procedure != NULL
+             && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
+           {
+             val = bfd_asymbol_value (sym);
+             if (bfd_get_section (sym) == data_sec
+                 && text_sec != (asection *) NULL)
+               val += bfd_section_size (outbfd, text_sec);
+             nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val;
+             gotcheck = true;
+           }
+       }
+    }
+
+  if (endsym != NULL)
+    {
+      endsym->value = bfd_get_section_size_before_reloc (bss_sec);
+
+      /* FIXME: If any relocs referring to _end use inplace addends,
+        then I think they need to be updated.  This is handled by
+        i386_mangle_relocs.  Is it needed for any other object
+        formats?  */
+    }
+
+  if (newsymcount == 0)
+    outsyms = symbols;
+  else
+    {
+      outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1)
+                                     * sizeof (asymbol *));
+      memcpy (outsyms, symbols, symcount * sizeof (asymbol *));
+      memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *));
+      outsyms[symcount + newsymcount] = NULL;
+    }
+
+  bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
+    
+  if (! gotstart)
+    fprintf (stderr, _("%s: warning: START procedure %s not defined\n"),
+            program_name, start_procedure);
+  if (! gotexit)
+    fprintf (stderr, _("%s: warning: EXIT procedure %s not defined\n"),
+            program_name, exit_procedure);
+  if (check_procedure != NULL
+      && ! gotcheck)
+    fprintf (stderr, _("%s: warning: CHECK procedure %s not defined\n"),
+            program_name, check_procedure);
+
+  /* Add additional sections required for the header information.  */
+  if (custom_file != NULL)
+    {
+      custom_data = fopen (custom_file, "r");
+      if (custom_data == NULL
+         || fstat (fileno (custom_data), &st) < 0)
+       {
+         fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
+                  strerror (errno));
+         custom_file = NULL;
+       }
+      else
+       {
+         custom_size = st.st_size;
+         custom_section = bfd_make_section (outbfd, ".nlmcustom");
+         if (custom_section == NULL
+             || ! bfd_set_section_size (outbfd, custom_section, custom_size)
+             || ! bfd_set_section_flags (outbfd, custom_section,
+                                         SEC_HAS_CONTENTS))
+           bfd_fatal (_("custom section"));
+       }
+    }
+  if (help_file != NULL)
+    {
+      help_data = fopen (help_file, "r");
+      if (help_data == NULL
+         || fstat (fileno (help_data), &st) < 0)
+       {
+         fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
+                  strerror (errno));
+         help_file = NULL;
+       }
+      else
+       {
+         help_size = st.st_size;
+         help_section = bfd_make_section (outbfd, ".nlmhelp");
+         if (help_section == NULL
+             || ! bfd_set_section_size (outbfd, help_section, help_size)
+             || ! bfd_set_section_flags (outbfd, help_section,
+                                         SEC_HAS_CONTENTS))
+           bfd_fatal (_("help section"));
+         strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+       }
+    }
+  if (message_file != NULL)
+    {
+      message_data = fopen (message_file, "r");
+      if (message_data == NULL
+         || fstat (fileno (message_data), &st) < 0)
+       {
+         fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
+                  strerror (errno));
+         message_file = NULL;
+       }
+      else
+       {
+         message_size = st.st_size;
+         message_section = bfd_make_section (outbfd, ".nlmmessages");
+         if (message_section == NULL
+             || ! bfd_set_section_size (outbfd, message_section, message_size)
+             || ! bfd_set_section_flags (outbfd, message_section,
+                                         SEC_HAS_CONTENTS))
+           bfd_fatal (_("message section"));
+         strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+       }
+    }
+  if (modules != NULL)
+    {
+      struct string_list *l;
+
+      module_size = 0;
+      for (l = modules; l != NULL; l = l->next)
+       module_size += strlen (l->string) + 1;
+      module_section = bfd_make_section (outbfd, ".nlmmodules");
+      if (module_section == NULL
+         || ! bfd_set_section_size (outbfd, module_section, module_size)
+         || ! bfd_set_section_flags (outbfd, module_section,
+                                     SEC_HAS_CONTENTS))
+       bfd_fatal (_("module section"));
+    }
+  if (rpc_file != NULL)
+    {
+      rpc_data = fopen (rpc_file, "r");
+      if (rpc_data == NULL
+         || fstat (fileno (rpc_data), &st) < 0)
+       {
+         fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
+                  strerror (errno));
+         rpc_file = NULL;
+       }
+      else
+       {
+         rpc_size = st.st_size;
+         rpc_section = bfd_make_section (outbfd, ".nlmrpc");
+         if (rpc_section == NULL
+             || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
+             || ! bfd_set_section_flags (outbfd, rpc_section,
+                                         SEC_HAS_CONTENTS))
+           bfd_fatal (_("rpc section"));
+         strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+       }
+    }
+  if (sharelib_file != NULL)
+    {
+      sharedbfd = bfd_openr (sharelib_file, output_format);
+      if (sharedbfd == NULL
+         || ! bfd_check_format (sharedbfd, bfd_object))
+       {
+         fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
+                  bfd_errmsg (bfd_get_error ()));
+         sharelib_file = NULL;
+       }
+      else
+       {
+         sharedhdr = *nlm_fixed_header (sharedbfd);
+         bfd_close (sharedbfd);
+         shared_data = fopen (sharelib_file, "r");
+         if (shared_data == NULL
+             || (fstat (fileno (shared_data), &st) < 0))
+           {
+             fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
+                      strerror (errno));
+             sharelib_file = NULL;
+           }
+         else
+           {
+             /* If we were clever, we could just copy out the
+                sections of the shared library which we actually
+                need.  However, we would have to figure out the sizes
+                of the external and public information, and that can
+                not be done without reading through them.  */
+             if (sharedhdr.uninitializedDataSize > 0)
+               {
+                 /* There is no place to record this information.  */
+                 fprintf (stderr,
+                          _("%s:%s: warning: shared libraries can not have uninitialized data\n"),
+                          program_name, sharelib_file);
+               }
+             shared_offset = st.st_size;
+             if (shared_offset > (size_t) sharedhdr.codeImageOffset)
+               shared_offset = sharedhdr.codeImageOffset;
+             if (shared_offset > (size_t) sharedhdr.dataImageOffset)
+               shared_offset = sharedhdr.dataImageOffset;
+             if (shared_offset > (size_t) sharedhdr.relocationFixupOffset)
+               shared_offset = sharedhdr.relocationFixupOffset;
+             if (shared_offset > (size_t) sharedhdr.externalReferencesOffset)
+               shared_offset = sharedhdr.externalReferencesOffset;
+             if (shared_offset > (size_t) sharedhdr.publicsOffset)
+               shared_offset = sharedhdr.publicsOffset;
+             shared_size = st.st_size - shared_offset;
+             shared_section = bfd_make_section (outbfd, ".nlmshared");
+             if (shared_section == NULL
+                 || ! bfd_set_section_size (outbfd, shared_section,
+                                            shared_size)
+                 || ! bfd_set_section_flags (outbfd, shared_section,
+                                             SEC_HAS_CONTENTS))
+               bfd_fatal (_("shared section"));
+             strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+           }
+       }
+    }
+
+  /* Check whether a version was given.  */
+  if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0)
+    fprintf (stderr, _("%s: warning: No version number given\n"),
+            program_name);
+
+  /* At least for now, always create an extended header, because that
+     is what NLMLINK does.  */
+  strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
+
+  strncpy (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx", 8);
+
+  /* If the date was not given, force it in.  */
+  if (nlm_version_header (outbfd)->month == 0
+      && nlm_version_header (outbfd)->day == 0
+      && nlm_version_header (outbfd)->year == 0)
+    {
+      time_t now;
+      struct tm *ptm;
+
+      time (&now);
+      ptm = localtime (&now);
+      nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
+      nlm_version_header (outbfd)->day = ptm->tm_mday;
+      nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
+      strncpy (version_hdr->stamp, "VeRsIoN#", 8);
+    }
+
+#ifdef NLMCONV_POWERPC
+  /* Resolve the stubs we build for PowerPC NetWare.  */
+  if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
+    powerpc_resolve_stubs (inbfd, outbfd);
+#endif
+
+  /* Copy over the sections.  */
+  bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
+
+  /* Finish up the header information.  */
+  if (custom_file != NULL)
+    {
+      PTR data;
+
+      data = xmalloc (custom_size);
+      if (fread (data, 1, custom_size, custom_data) != custom_size)
+       fprintf (stderr, _("%s:%s: read: %s\n"), program_name, custom_file,
+                strerror (errno));
+      else
+       {
+         if (! bfd_set_section_contents (outbfd, custom_section, data,
+                                         (file_ptr) 0, custom_size))
+           bfd_fatal (_("custom section"));
+         nlm_fixed_header (outbfd)->customDataOffset =
+           custom_section->filepos;
+         nlm_fixed_header (outbfd)->customDataSize = custom_size;
+       }
+      free (data);
+    }
+  if (! debug_info)
+    {
+      /* As a special hack, the backend recognizes a debugInfoOffset
+        of -1 to mean that it should not output any debugging
+        information.  This can not be handling by fiddling with the
+        symbol table because exported symbols appear in both the
+        export information and the debugging information.  */
+      nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
+    }
+  if (map_file != NULL)
+    fprintf (stderr,
+            _("%s: warning: MAP and FULLMAP are not supported; try ld -M\n"),
+            program_name);
+  if (help_file != NULL)
+    {
+      PTR data;
+
+      data = xmalloc (help_size);
+      if (fread (data, 1, help_size, help_data) != help_size)
+       fprintf (stderr, _("%s:%s: read: %s\n"), program_name, help_file,
+                strerror (errno));
+      else
+       {
+         if (! bfd_set_section_contents (outbfd, help_section, data,
+                                         (file_ptr) 0, help_size))
+           bfd_fatal (_("help section"));
+         nlm_extended_header (outbfd)->helpFileOffset =
+           help_section->filepos;
+         nlm_extended_header (outbfd)->helpFileLength = help_size;
+       }
+      free (data);
+    }
+  if (message_file != NULL)
+    {
+      PTR data;
+
+      data = xmalloc (message_size);
+      if (fread (data, 1, message_size, message_data) != message_size)
+       fprintf (stderr, _("%s:%s: read: %s\n"), program_name, message_file,
+                strerror (errno));
+      else
+       {
+         if (! bfd_set_section_contents (outbfd, message_section, data,
+                                         (file_ptr) 0, message_size))
+           bfd_fatal (_("message section"));
+         nlm_extended_header (outbfd)->messageFileOffset =
+           message_section->filepos;
+         nlm_extended_header (outbfd)->messageFileLength = message_size;
+
+         /* FIXME: Are these offsets correct on all platforms?  Are
+            they 32 bits on all platforms?  What endianness?  */
+         nlm_extended_header (outbfd)->languageID =
+           bfd_h_get_32 (outbfd, (bfd_byte *) data + 106);
+         nlm_extended_header (outbfd)->messageCount =
+           bfd_h_get_32 (outbfd, (bfd_byte *) data + 110);
+       }
+      free (data);
+    }
+  if (modules != NULL)
+    {
+      PTR data;
+      unsigned char *set;
+      struct string_list *l;
+      bfd_size_type c;
+
+      data = xmalloc (module_size);
+      c = 0;
+      set = (unsigned char *) data;
+      for (l = modules; l != NULL; l = l->next)
+       {
+         *set = strlen (l->string);
+         strncpy (set + 1, l->string, *set);
+         set += *set + 1;
+         ++c;
+       }
+      if (! bfd_set_section_contents (outbfd, module_section, data,
+                                     (file_ptr) 0, module_size))
+       bfd_fatal (_("module section"));
+      nlm_fixed_header (outbfd)->moduleDependencyOffset =
+       module_section->filepos;
+      nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
+    }
+  if (rpc_file != NULL)
+    {
+      PTR data;
+
+      data = xmalloc (rpc_size);
+      if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
+       fprintf (stderr, _("%s:%s: read: %s\n"), program_name, rpc_file,
+                strerror (errno));
+      else
+       {
+         if (! bfd_set_section_contents (outbfd, rpc_section, data,
+                                         (file_ptr) 0, rpc_size))
+           bfd_fatal (_("rpc section"));
+         nlm_extended_header (outbfd)->RPCDataOffset =
+           rpc_section->filepos;
+         nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
+       }
+      free (data);
+    }
+  if (sharelib_file != NULL)
+    {
+      PTR data;
+
+      data = xmalloc (shared_size);
+      if (fseek (shared_data, shared_offset, SEEK_SET) != 0
+         || fread (data, 1, shared_size, shared_data) != shared_size)
+       fprintf (stderr, _("%s:%s: read: %s\n"), program_name, sharelib_file,
+                strerror (errno));
+      else
+       {
+         if (! bfd_set_section_contents (outbfd, shared_section, data,
+                                         (file_ptr) 0, shared_size))
+           bfd_fatal (_("shared section"));
+       }
+      nlm_extended_header (outbfd)->sharedCodeOffset =
+       sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
+      nlm_extended_header (outbfd)->sharedCodeLength =
+       sharedhdr.codeImageSize;
+      nlm_extended_header (outbfd)->sharedDataOffset =
+       sharedhdr.dataImageOffset - shared_offset + shared_section->filepos;
+      nlm_extended_header (outbfd)->sharedDataLength =
+       sharedhdr.dataImageSize;
+      nlm_extended_header (outbfd)->sharedRelocationFixupOffset =
+       (sharedhdr.relocationFixupOffset
+        - shared_offset
+        + shared_section->filepos);
+      nlm_extended_header (outbfd)->sharedRelocationFixupCount =
+       sharedhdr.numberOfRelocationFixups;
+      nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
+       (sharedhdr.externalReferencesOffset
+        - shared_offset
+        + shared_section->filepos);
+      nlm_extended_header (outbfd)->sharedExternalReferenceCount =
+       sharedhdr.numberOfExternalReferences;
+      nlm_extended_header (outbfd)->sharedPublicsOffset =
+       sharedhdr.publicsOffset - shared_offset + shared_section->filepos;
+      nlm_extended_header (outbfd)->sharedPublicsCount =
+       sharedhdr.numberOfPublics;
+      nlm_extended_header (outbfd)->sharedDebugRecordOffset =
+       sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
+      nlm_extended_header (outbfd)->sharedDebugRecordCount =
+       sharedhdr.numberOfDebugRecords;
+      nlm_extended_header (outbfd)->SharedInitializationOffset =
+       sharedhdr.codeStartOffset;
+      nlm_extended_header (outbfd)->SharedExitProcedureOffset =
+       sharedhdr.exitProcedureOffset;
+      free (data);
+    }
+  len = strlen (output_file);
+  if (len > NLM_MODULE_NAME_SIZE - 2)
+    len = NLM_MODULE_NAME_SIZE - 2;
+  nlm_fixed_header (outbfd)->moduleName[0] = len;
+
+  strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file,
+          NLM_MODULE_NAME_SIZE - 2);
+  nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
+  for (modname = nlm_fixed_header (outbfd)->moduleName;
+       *modname != '\0';
+       modname++)
+    if (islower ((unsigned char) *modname))
+      *modname = toupper (*modname);
+
+  strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
+          NLM_OLD_THREAD_NAME_LENGTH);
+
+  nlm_cygnus_ext_header (outbfd)->offset = secsec->filepos;
+  nlm_cygnus_ext_header (outbfd)->length = bfd_section_size (outbfd, secsec);
+
+  if (! bfd_close (outbfd))
+    bfd_fatal (output_file);
+  if (! bfd_close (inbfd))
+    bfd_fatal (input_file);
+
+  if (unlink_on_exit != NULL)
+    unlink (unlink_on_exit);
+
+  return 0;
+}
+\f
+/* Display a help message and exit.  */
+
+static void
+show_help ()
+{
+  printf (_("%s: Convert an object file into a NetWare Loadable Module\n"),
+         program_name);
+  show_usage (stdout, 0);
+}
+
+/* Show a usage message and exit.  */
+
+static void
+show_usage (file, status)
+     FILE *file;
+     int status;
+{
+  fprintf (file, _("\
+Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n\
+       [--input-target=bfdname] [--output-target=bfdname]\n\
+       [--header-file=file] [--linker=linker] [--debug]\n\
+       [--help] [--version]\n\
+       [in-file [out-file]]\n"),
+          program_name);
+  if (status == 0)
+    fprintf (file, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (status);
+}
+\f
+/* Select the output format based on the input architecture, machine,
+   and endianness.  This chooses the appropriate NLM target.  */
+
+static const char *
+select_output_format (arch, mach, bigendian)
+     enum bfd_architecture arch;
+     unsigned long mach;
+     boolean bigendian;
+{
+  switch (arch)
+    {
+#ifdef NLMCONV_I386
+    case bfd_arch_i386:
+      return "nlm32-i386";
+#endif
+#ifdef NLMCONV_SPARC
+    case bfd_arch_sparc:
+      return "nlm32-sparc";
+#endif
+#ifdef NLMCONV_ALPHA
+    case bfd_arch_alpha:
+      return "nlm32-alpha";
+#endif
+#ifdef NLMCONV_POWERPC
+    case bfd_arch_powerpc:
+      return "nlm32-powerpc";
+#endif
+    default:
+      fprintf (stderr, _("%s: support not compiled in for %s\n"),
+              program_name, bfd_printable_arch_mach (arch, mach));
+      exit (1);
+      /* Avoid warning.  */
+      return NULL;
+    }
+  /*NOTREACHED*/
+}
+\f
+/* The BFD sections are copied in two passes.  This function selects
+   the output section for each input section, and sets up the section
+   name, size, etc.  */
+
+static void
+setup_sections (inbfd, insec, data_ptr)
+     bfd *inbfd;
+     asection *insec;
+     PTR data_ptr;
+{
+  bfd *outbfd = (bfd *) data_ptr;
+  flagword f;
+  const char *outname;
+  asection *outsec;
+  bfd_vma offset;
+  bfd_size_type align;
+  bfd_size_type add;
+  bfd_size_type secsecsize;
+
+  f = bfd_get_section_flags (inbfd, insec);
+  if (f & SEC_CODE)
+    outname = NLM_CODE_NAME;
+  else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
+    outname = NLM_INITIALIZED_DATA_NAME;
+  else if (f & SEC_ALLOC)
+    outname = NLM_UNINITIALIZED_DATA_NAME;
+  else
+    outname = bfd_section_name (inbfd, insec);
+
+  outsec = bfd_get_section_by_name (outbfd, outname);
+  if (outsec == NULL)
+    {
+      outsec = bfd_make_section (outbfd, outname);
+      if (outsec == NULL)
+       bfd_fatal (_("make section"));
+    }
+
+  insec->output_section = outsec;
+
+  offset = bfd_section_size (outbfd, outsec);
+  align = 1 << bfd_section_alignment (inbfd, insec);
+  add = ((offset + align - 1) &~ (align - 1)) - offset;
+  insec->output_offset = offset + add;
+
+  if (! bfd_set_section_size (outbfd, outsec,
+                             (bfd_section_size (outbfd, outsec)
+                              + bfd_section_size (inbfd, insec)
+                              + add)))
+    bfd_fatal (_("set section size"));
+
+  if ((bfd_section_alignment (inbfd, insec)
+       > bfd_section_alignment (outbfd, outsec))
+      && ! bfd_set_section_alignment (outbfd, outsec,
+                                     bfd_section_alignment (inbfd, insec)))
+    bfd_fatal (_("set section alignment"));
+
+  if (! bfd_set_section_flags (outbfd, outsec,
+                              f | bfd_get_section_flags (outbfd, outsec)))
+    bfd_fatal (_("set section flags"));
+
+  bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
+
+  /* For each input section we allocate space for an entry in
+     .nlmsections.  */
+  secsecsize = bfd_section_size (outbfd, secsec);
+  secsecsize += strlen (bfd_section_name (inbfd, insec)) + 1;
+  secsecsize = (secsecsize + 3) &~ 3;
+  secsecsize += 8;
+  if (! bfd_set_section_size (outbfd, secsec, secsecsize))
+    bfd_fatal (_("set .nlmsections size"));
+}
+
+/* Copy the section contents.  */
+
+static void
+copy_sections (inbfd, insec, data_ptr)
+     bfd *inbfd;
+     asection *insec;
+     PTR data_ptr;
+{
+  static bfd_size_type secsecoff = 0;
+  bfd *outbfd = (bfd *) data_ptr;
+  const char *inname;
+  asection *outsec;
+  bfd_size_type size;
+  PTR contents;
+  long reloc_size;
+  bfd_byte buf[4];
+  bfd_size_type add;
+
+  inname = bfd_section_name (inbfd, insec);
+
+  outsec = insec->output_section;
+  assert (outsec != NULL);
+
+  size = bfd_get_section_size_before_reloc (insec);
+
+  /* FIXME: Why are these necessary?  */
+  insec->_cooked_size = insec->_raw_size;
+  insec->reloc_done = true;
+
+  if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
+    contents = NULL;
+  else
+    {
+      contents = xmalloc (size);
+      if (! bfd_get_section_contents (inbfd, insec, contents,
+                                     (file_ptr) 0, size))
+       bfd_fatal (bfd_get_filename (inbfd));
+    }
+
+  reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
+  if (reloc_size < 0)
+    bfd_fatal (bfd_get_filename (inbfd));
+  if (reloc_size != 0)
+    {
+      arelent **relocs;
+      long reloc_count;
+
+      relocs = (arelent **) xmalloc (reloc_size);
+      reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
+      if (reloc_count < 0)
+       bfd_fatal (bfd_get_filename (inbfd));
+      mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents,
+                    size);
+
+      /* FIXME: refers to internal BFD fields.  */
+      if (outsec->orelocation != (arelent **) NULL)
+       {
+         bfd_size_type total_count;
+         arelent **combined;
+
+         total_count = reloc_count + outsec->reloc_count;
+         combined = (arelent **) xmalloc (total_count * sizeof (arelent *));
+         memcpy (combined, outsec->orelocation,
+                 outsec->reloc_count * sizeof (arelent *));
+         memcpy (combined + outsec->reloc_count, relocs,
+                 (size_t) (reloc_count * sizeof (arelent *)));
+         free (outsec->orelocation);
+         reloc_count = total_count;
+         relocs = combined;
+       }
+
+      bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
+    }
+
+  if (contents != NULL)
+    {
+      if (! bfd_set_section_contents (outbfd, outsec, contents,
+                                     insec->output_offset, size))
+       bfd_fatal (bfd_get_filename (outbfd));
+      free (contents);
+    }
+
+  /* Add this section to .nlmsections.  */
+  if (! bfd_set_section_contents (outbfd, secsec, (PTR) inname, secsecoff,
+                                 strlen (inname) + 1))
+    bfd_fatal (_("set .nlmsection contents"));
+  secsecoff += strlen (inname) + 1;
+
+  add = ((secsecoff + 3) &~ 3) - secsecoff;
+  if (add != 0)
+    {
+      bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
+      if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, add))
+       bfd_fatal (_("set .nlmsection contents"));
+      secsecoff += add;
+    }
+
+  if (contents != NULL)
+    bfd_h_put_32 (outbfd, (bfd_vma) outsec->filepos, buf);
+  else
+    bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
+  if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
+    bfd_fatal (_("set .nlmsection contents"));
+  secsecoff += 4;
+
+  bfd_h_put_32 (outbfd, (bfd_vma) size, buf);
+  if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
+    bfd_fatal (_("set .nlmsection contents"));
+  secsecoff += 4;
+}
+
+/* Some, perhaps all, NetWare targets require changing the relocs used
+   by the input formats.  */
+
+static void
+mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
+              contents_size)
+     bfd *outbfd;
+     asection *insec;
+     arelent ***relocs_ptr;
+     long *reloc_count_ptr;
+     char *contents;
+     bfd_size_type contents_size;
+{
+  switch (bfd_get_arch (outbfd))
+    {
+#ifdef NLMCONV_I386
+    case bfd_arch_i386:
+      i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
+                         contents, contents_size);
+      break;
+#endif
+#ifdef NLMCONV_ALPHA
+    case bfd_arch_alpha:
+      alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
+                          contents, contents_size);
+      break;
+#endif
+#ifdef NLMCONV_POWERPC
+    case bfd_arch_powerpc:
+      powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
+                            contents, contents_size);
+      break;
+#endif
+    default:
+      default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
+                            contents, contents_size);
+      break;
+    }
+}
+
+/* By default all we need to do for relocs is change the address by
+   the output_offset.  */
+
+/*ARGSUSED*/
+static void
+default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
+                      contents_size)
+     bfd *outbfd;
+     asection *insec;
+     arelent ***relocs_ptr;
+     long *reloc_count_ptr;
+     char *contents;
+     bfd_size_type contents_size;
+{
+  if (insec->output_offset != 0)
+    {
+      long reloc_count;
+      register arelent **relocs;
+      register long i;
+
+      reloc_count = *reloc_count_ptr;
+      relocs = *relocs_ptr;
+      for (i = 0; i < reloc_count; i++, relocs++)
+       (*relocs)->address += insec->output_offset;
+    }
+}
+\f
+#ifdef NLMCONV_I386
+
+/* NetWare on the i386 supports a restricted set of relocs, which are
+   different from those used on other i386 targets.  This routine
+   converts the relocs.  It is, obviously, very target dependent.  At
+   the moment, the nlm32-i386 backend performs similar translations;
+   however, it is more reliable and efficient to do them here.  */
+
+static reloc_howto_type nlm_i386_pcrel_howto =
+  HOWTO (1,                    /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        0,                     /* special_function */
+        "DISP32",              /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        true);                 /* pcrel_offset */
+
+static void
+i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
+                   contents_size)
+     bfd *outbfd;
+     asection *insec;
+     arelent ***relocs_ptr;
+     long *reloc_count_ptr;
+     char *contents;
+     bfd_size_type contents_size;
+{
+  long reloc_count, i;
+  arelent **relocs;
+
+  reloc_count = *reloc_count_ptr;
+  relocs = *relocs_ptr;
+  for (i = 0; i < reloc_count; i++)
+    {
+      arelent *rel;
+      asymbol *sym;
+      bfd_size_type address;
+      bfd_vma addend;
+
+      rel = *relocs++;
+      sym = *rel->sym_ptr_ptr;
+
+      /* We're moving the relocs from the input section to the output
+        section, so we must adjust the address accordingly.  */
+      address = rel->address;
+      rel->address += insec->output_offset;
+
+      /* Note that no serious harm will ensue if we fail to change a
+        reloc.  The backend will fail when writing out the reloc.  */
+
+      /* Make sure this reloc is within the data we have.  We use only
+        4 byte relocs here, so we insist on having 4 bytes.  */
+      if (address + 4 > contents_size)
+       continue;
+
+      /* A PC relative reloc entirely within a single section is
+        completely unnecessary.  This can be generated by ld -r.  */
+      if (sym == insec->symbol
+         && rel->howto != NULL
+         && rel->howto->pc_relative
+         && ! rel->howto->pcrel_offset)
+       {
+         --*reloc_count_ptr;
+         --relocs;
+         memmove (relocs, relocs + 1,
+                  (size_t) ((reloc_count - i) * sizeof (arelent *)));
+         continue;
+       }
+
+      /* Get the amount the relocation will add in.  */
+      addend = rel->addend + sym->value;
+
+      /* NetWare doesn't support PC relative relocs against defined
+        symbols, so we have to eliminate them by doing the relocation
+        now.  We can only do this if the reloc is within a single
+        section.  */
+      if (rel->howto != NULL
+         && rel->howto->pc_relative
+         && bfd_get_section (sym) == insec->output_section)
+       {
+         bfd_vma val;
+
+         if (rel->howto->pcrel_offset)
+           addend -= address;
+
+         val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
+         val += addend;
+         bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
+
+         --*reloc_count_ptr;
+         --relocs;
+         memmove (relocs, relocs + 1,
+                  (size_t) ((reloc_count - i) * sizeof (arelent *)));
+         continue;
+       }
+
+      /* NetWare doesn't support reloc addends, so we get rid of them
+        here by simply adding them into the object data.  We handle
+        the symbol value, if any, the same way.  */
+      if (addend != 0
+         && rel->howto != NULL
+         && rel->howto->rightshift == 0
+         && rel->howto->size == 2
+         && rel->howto->bitsize == 32
+         && rel->howto->bitpos == 0
+         && rel->howto->src_mask == 0xffffffff
+         && rel->howto->dst_mask == 0xffffffff)
+       {
+         bfd_vma val;
+
+         val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
+         val += addend;
+         bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
+
+         /* Adjust the reloc for the changes we just made.  */
+         rel->addend = 0;
+         if (! bfd_is_und_section (bfd_get_section (sym)))
+           rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
+       }
+
+      /* NetWare uses a reloc with pcrel_offset set.  We adjust
+        pc_relative relocs accordingly.  We are going to change the
+        howto field, so we can only do this if the current one is
+        compatible.  We should check that special_function is NULL
+        here, but at the moment coff-i386 uses a special_function
+        which does not affect what we are doing here.  */
+      if (rel->howto != NULL
+         && rel->howto->pc_relative
+         && ! rel->howto->pcrel_offset
+         && rel->howto->rightshift == 0
+         && rel->howto->size == 2
+         && rel->howto->bitsize == 32
+         && rel->howto->bitpos == 0
+         && rel->howto->src_mask == 0xffffffff
+         && rel->howto->dst_mask == 0xffffffff)
+       {
+         bfd_vma val;
+
+         /* When pcrel_offset is not set, it means that the negative
+            of the address of the memory location is stored in the
+            memory location.  We must add it back in.  */
+         val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
+         val += address;
+         bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
+
+         /* We must change to a new howto.  */
+         rel->howto = &nlm_i386_pcrel_howto;
+       }
+    }
+}
+
+#endif /* NLMCONV_I386 */
+\f
+#ifdef NLMCONV_ALPHA
+
+/* On the Alpha the first reloc for every section must be a special
+   relocs which hold the GP address.  Also, the first reloc in the
+   file must be a special reloc which holds the address of the .lita
+   section.  */
+
+static reloc_howto_type nlm32_alpha_nw_howto =
+  HOWTO (ALPHA_R_NW_RELOC,     /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        0,                     /* special_function */
+        "NW_RELOC",            /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false);                /* pcrel_offset */
+
+/*ARGSUSED*/
+static void
+alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
+                    contents_size)
+     bfd *outbfd;
+     asection *insec;
+     register arelent ***relocs_ptr;
+     long *reloc_count_ptr;
+     char *contents;
+     bfd_size_type contents_size;
+{
+  long old_reloc_count;
+  arelent **old_relocs;
+  register arelent **relocs;
+
+  old_reloc_count = *reloc_count_ptr;
+  old_relocs = *relocs_ptr;
+  relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *));
+  *relocs_ptr = relocs;
+
+  if (nlm_alpha_backend_data (outbfd)->lita_address == 0)
+    {
+      bfd *inbfd;
+      asection *lita_section;
+
+      inbfd = insec->owner;
+      lita_section = bfd_get_section_by_name (inbfd, _LITA);
+      if (lita_section != (asection *) NULL)
+       {
+         nlm_alpha_backend_data (outbfd)->lita_address =
+           bfd_get_section_vma (inbfd, lita_section);
+         nlm_alpha_backend_data (outbfd)->lita_size =
+           bfd_section_size (inbfd, lita_section);
+       }
+      else
+       {
+         /* Avoid outputting this reloc again.  */
+         nlm_alpha_backend_data (outbfd)->lita_address = 4;
+       }
+
+      *relocs = (arelent *) xmalloc (sizeof (arelent));
+      (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+      (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address;
+      (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1;
+      (*relocs)->howto = &nlm32_alpha_nw_howto;
+      ++relocs;
+      ++(*reloc_count_ptr);
+    }
+
+  /* Get the GP value from bfd.  */
+  if (nlm_alpha_backend_data (outbfd)->gp == 0)
+    nlm_alpha_backend_data (outbfd)->gp =
+      bfd_ecoff_get_gp_value (insec->owner);
+
+  *relocs = (arelent *) xmalloc (sizeof (arelent));
+  (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+  (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp;
+  (*relocs)->addend = 0;
+  (*relocs)->howto = &nlm32_alpha_nw_howto;
+  ++relocs;
+  ++(*reloc_count_ptr);
+
+  memcpy ((PTR) relocs, (PTR) old_relocs,
+         (size_t) old_reloc_count * sizeof (arelent *));
+  relocs[old_reloc_count] = (arelent *) NULL;
+
+  free (old_relocs);
+
+  if (insec->output_offset != 0)
+    {
+      register bfd_size_type i;
+
+      for (i = 0; i < (bfd_size_type) old_reloc_count; i++, relocs++)
+       (*relocs)->address += insec->output_offset;
+    }
+}
+
+#endif /* NLMCONV_ALPHA */
+\f
+#ifdef NLMCONV_POWERPC
+
+/* We keep a linked list of stubs which we must build.  Because BFD
+   requires us to know the sizes of all sections before we can set the
+   contents of any, we must figure out which stubs we want to build
+   before we can actually build any of them.  */
+
+struct powerpc_stub
+{
+  /* Next stub in linked list.  */
+  struct powerpc_stub *next;
+
+  /* Symbol whose value is the start of the stub.  This is a symbol
+     whose name begins with `.'.  */
+  asymbol *start;
+
+  /* Symbol we are going to create a reloc against.  This is a symbol
+     with the same name as START but without the leading `.'.  */
+  asymbol *reloc;
+
+  /* The TOC index for this stub.  This is the index into the TOC
+     section at which the reloc is created.  */
+  unsigned int toc_index;
+};
+
+/* The linked list of stubs.  */
+
+static struct powerpc_stub *powerpc_stubs;
+
+/* This is what a stub looks like.  The first instruction will get
+   adjusted with the correct TOC index.  */
+
+static unsigned long powerpc_stub_insns[] =
+{
+  0x81820000,          /* lwz   r12,0(r2) */
+  0x90410014,          /* stw   r2,20(r1) */
+  0x800c0000,          /* lwz   r0,0(r12) */
+  0x804c0004,          /* lwz   r2,r(r12) */
+  0x7c0903a6,          /* mtctr r0 */
+  0x4e800420,          /* bctr */
+  0,                   /* Traceback table.  */
+  0xc8000,
+  0
+};
+
+#define POWERPC_STUB_INSN_COUNT \
+  (sizeof powerpc_stub_insns / sizeof powerpc_stub_insns[0])
+
+#define POWERPC_STUB_SIZE (4 * POWERPC_STUB_INSN_COUNT)
+
+/* Each stub uses a four byte TOC entry.  */
+#define POWERPC_STUB_TOC_ENTRY_SIZE (4)
+
+/* The original size of the .got section.  */
+static bfd_size_type powerpc_initial_got_size;
+
+/* Look for all undefined symbols beginning with `.', and prepare to
+   build a stub for each one.  */
+
+static void
+powerpc_build_stubs (inbfd, outbfd, symbols_ptr, symcount_ptr)
+     bfd *inbfd;
+     bfd *outbfd;
+     asymbol ***symbols_ptr;
+     long *symcount_ptr;
+{
+  asection *stub_sec;
+  asection *got_sec;
+  unsigned int got_base;
+  long i;
+  long symcount;
+  long stubcount;
+
+  /* Make a section to hold stubs.  We don't set SEC_HAS_CONTENTS for
+     the section to prevent copy_sections from reading from it.  */
+  stub_sec = bfd_make_section (inbfd, ".stubs");
+  if (stub_sec == (asection *) NULL
+      || ! bfd_set_section_flags (inbfd, stub_sec,
+                                 (SEC_CODE
+                                  | SEC_RELOC
+                                  | SEC_ALLOC
+                                  | SEC_LOAD))
+      || ! bfd_set_section_alignment (inbfd, stub_sec, 2))
+    bfd_fatal (".stubs");
+
+  /* Get the TOC section, which is named .got.  */
+  got_sec = bfd_get_section_by_name (inbfd, ".got");
+  if (got_sec == (asection *) NULL)
+    {
+      got_sec = bfd_make_section (inbfd, ".got");
+      if (got_sec == (asection *) NULL
+         || ! bfd_set_section_flags (inbfd, got_sec,
+                                     (SEC_DATA
+                                      | SEC_RELOC
+                                      | SEC_ALLOC
+                                      | SEC_LOAD
+                                      | SEC_HAS_CONTENTS))
+         || ! bfd_set_section_alignment (inbfd, got_sec, 2))
+       bfd_fatal (".got");
+    }
+
+  powerpc_initial_got_size = bfd_section_size (inbfd, got_sec);
+  got_base = powerpc_initial_got_size;
+  got_base = (got_base + 3) &~ 3;
+
+  stubcount = 0;
+
+  symcount = *symcount_ptr;
+  for (i = 0; i < symcount; i++)
+    {
+      asymbol *sym;
+      asymbol *newsym;
+      char *newname;
+      struct powerpc_stub *item;
+
+      sym = (*symbols_ptr)[i];
+
+      /* We must make a stub for every undefined symbol whose name
+        starts with '.'.  */
+      if (bfd_asymbol_name (sym)[0] != '.'
+         || ! bfd_is_und_section (bfd_get_section (sym)))
+       continue;
+
+      /* Make a new undefined symbol with the same name but without
+        the leading `.'.  */
+      newsym = (asymbol *) xmalloc (sizeof (asymbol));
+      *newsym = *sym;
+      newname = (char *) xmalloc (strlen (bfd_asymbol_name (sym)));
+      strcpy (newname, bfd_asymbol_name (sym) + 1);
+      newsym->name = newname;
+
+      /* Define the `.' symbol to be in the stub section.  */
+      sym->section = stub_sec;
+      sym->value = stubcount * POWERPC_STUB_SIZE;
+      /* We set the BSF_DYNAMIC flag here so that we can check it when
+        we are mangling relocs.  FIXME: This is a hack.  */
+      sym->flags = BSF_LOCAL | BSF_DYNAMIC;
+
+      /* Add this stub to the linked list.  */
+      item = (struct powerpc_stub *) xmalloc (sizeof (struct powerpc_stub));
+      item->start = sym;
+      item->reloc = newsym;
+      item->toc_index = got_base + stubcount * POWERPC_STUB_TOC_ENTRY_SIZE;
+
+      item->next = powerpc_stubs;
+      powerpc_stubs = item;
+      
+      ++stubcount;
+    }
+
+  if (stubcount > 0)
+    {
+      asymbol **s;
+      struct powerpc_stub *l;
+
+      /* Add the new symbols we just created to the symbol table.  */
+      *symbols_ptr = (asymbol **) xrealloc ((char *) *symbols_ptr,
+                                           ((symcount + stubcount)
+                                            * sizeof (asymbol)));
+      *symcount_ptr += stubcount;
+      s = &(*symbols_ptr)[symcount];
+      for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
+       *s++ = l->reloc;
+
+      /* Set the size of the .stubs section and increase the size of
+        the .got section.  */
+      if (! bfd_set_section_size (inbfd, stub_sec,
+                                 stubcount * POWERPC_STUB_SIZE)
+         || ! bfd_set_section_size (inbfd, got_sec,
+                                    (got_base
+                                     + (stubcount
+                                        * POWERPC_STUB_TOC_ENTRY_SIZE))))
+       bfd_fatal (_("stub section sizes"));
+    }
+}
+
+/* Resolve all the stubs for PowerPC NetWare.  We fill in the contents
+   of the output section, and create new relocs in the TOC.  */
+
+static void
+powerpc_resolve_stubs (inbfd, outbfd)
+     bfd *inbfd;
+     bfd *outbfd;
+{
+  bfd_byte buf[POWERPC_STUB_SIZE];
+  unsigned int i;
+  unsigned int stubcount;
+  arelent **relocs;
+  asection *got_sec;
+  arelent **r;
+  struct powerpc_stub *l;
+
+  if (powerpc_stubs == (struct powerpc_stub *) NULL)
+    return;
+
+  for (i = 0; i < POWERPC_STUB_INSN_COUNT; i++)
+    bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[i], buf + i * 4);
+
+  got_sec = bfd_get_section_by_name (inbfd, ".got");
+  assert (got_sec != (asection *) NULL);
+  assert (got_sec->output_section->orelocation == (arelent **) NULL);
+
+  stubcount = 0;
+  for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
+    ++stubcount;
+  relocs = (arelent **) xmalloc (stubcount * sizeof (arelent *));
+
+  r = relocs;
+  for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
+    {
+      arelent *reloc;
+
+      /* Adjust the first instruction to use the right TOC index.  */
+      bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[0] + l->toc_index, buf);
+
+      /* Write this stub out.  */
+      if (! bfd_set_section_contents (outbfd,
+                                     bfd_get_section (l->start),
+                                     buf,
+                                     l->start->value,
+                                     POWERPC_STUB_SIZE))
+       bfd_fatal (_("writing stub"));
+
+      /* Create a new reloc for the TOC entry.  */
+      reloc = (arelent *) xmalloc (sizeof (arelent));
+      reloc->sym_ptr_ptr = &l->reloc;
+      reloc->address = l->toc_index + got_sec->output_offset;
+      reloc->addend = 0;
+      reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32);
+                                     
+      *r++ = reloc;
+    }
+
+  bfd_set_reloc (outbfd, got_sec->output_section, relocs, stubcount);
+}
+
+/* Adjust relocation entries for PowerPC NetWare.  We do not output
+   TOC relocations.  The object code already contains the offset from
+   the TOC pointer.  When the function is called, the TOC register,
+   r2, will be set to the correct TOC value, so there is no need for
+   any further reloc.  */
+
+/*ARGSUSED*/
+static void
+powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
+                      contents_size)
+     bfd *outbfd;
+     asection *insec;
+     register arelent ***relocs_ptr;
+     long *reloc_count_ptr;
+     char *contents;
+     bfd_size_type contents_size;
+{
+  reloc_howto_type *toc_howto;
+  long reloc_count;
+  register arelent **relocs;
+  register long i;
+
+  toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16);
+  if (toc_howto == (reloc_howto_type *) NULL)
+    abort ();
+
+  /* If this is the .got section, clear out all the contents beyond
+     the initial size.  We must do this here because copy_sections is
+     going to write out whatever we return in the contents field.  */
+  if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0)
+    memset (contents + powerpc_initial_got_size, 0,
+           (size_t) (bfd_get_section_size_after_reloc (insec)
+                     - powerpc_initial_got_size));
+
+  reloc_count = *reloc_count_ptr;
+  relocs = *relocs_ptr;
+  for (i = 0; i < reloc_count; i++)
+    {
+      arelent *rel;
+      asymbol *sym;
+      bfd_vma sym_value;
+
+      rel = *relocs++;
+      sym = *rel->sym_ptr_ptr;
+
+      /* Convert any relocs against the .bss section into relocs
+         against the .data section.  */
+      if (strcmp (bfd_get_section_name (outbfd, bfd_get_section (sym)),
+                 NLM_UNINITIALIZED_DATA_NAME) == 0)
+       {
+         asection *datasec;
+
+         datasec = bfd_get_section_by_name (outbfd,
+                                            NLM_INITIALIZED_DATA_NAME);
+         if (datasec != NULL)
+           {
+             rel->addend += (bfd_get_section_vma (outbfd,
+                                                  bfd_get_section (sym))
+                             + sym->value);
+             rel->sym_ptr_ptr = datasec->symbol_ptr_ptr;
+             sym = *rel->sym_ptr_ptr;
+           }
+       }
+
+      /* We must be able to resolve all PC relative relocs at this
+        point.  If we get a branch to an undefined symbol we build a
+        stub, since NetWare will resolve undefined symbols into a
+        pointer to a function descriptor.  */
+      if (rel->howto->pc_relative)
+       {
+         /* This check for whether a symbol is in the same section as
+            the reloc will be wrong if there is a PC relative reloc
+            between two sections both of which were placed in the
+            same output section.  This should not happen.  */
+         if (bfd_get_section (sym) != insec->output_section)
+           fprintf (stderr, _("%s: unresolved PC relative reloc against %s\n"),
+                    program_name, bfd_asymbol_name (sym));
+         else
+           {
+             bfd_vma val;
+
+             assert (rel->howto->size == 2 && rel->howto->pcrel_offset);
+             val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);
+             val = ((val &~ rel->howto->dst_mask)
+                    | (((val & rel->howto->src_mask)
+                        + (sym->value - rel->address)
+                        + rel->addend)
+                       & rel->howto->dst_mask));
+             bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
+
+             /* If this reloc is against an stubbed symbol and the
+                next instruction is
+                    cror 31,31,31
+                then we replace the next instruction with
+                    lwz  r2,20(r1)
+                This reloads the TOC pointer after a stub call.  */
+             if (bfd_asymbol_name (sym)[0] == '.'
+                 && (sym->flags & BSF_DYNAMIC) != 0
+                 && (bfd_get_32 (outbfd,
+                                 (bfd_byte *) contents + rel->address + 4)
+                     == 0x4ffffb82)) /* cror 31,31,31 */
+               bfd_put_32 (outbfd, (bfd_vma) 0x80410014, /* lwz r2,20(r1) */
+                           (bfd_byte *) contents + rel->address + 4);
+
+             --*reloc_count_ptr;
+             --relocs;
+             memmove (relocs, relocs + 1,
+                      (size_t) ((reloc_count - 1) * sizeof (arelent *)));
+             continue;
+           }
+       }
+
+      /* When considering a TOC reloc, we do not want to include the
+        symbol value.  The symbol will be start of the TOC section
+        (which is named .got).  We do want to include the addend.  */
+      if (rel->howto == toc_howto)
+       sym_value = 0;
+      else
+       sym_value = sym->value;
+
+      /* If this is a relocation against a symbol with a value, or
+        there is a reloc addend, we need to update the addend in the
+        object file.  */
+      if (sym_value + rel->addend != 0)
+       {
+         bfd_vma val;
+
+         switch (rel->howto->size)
+           {
+           case 1:
+             val = bfd_get_16 (outbfd,
+                               (bfd_byte *) contents + rel->address);
+             val = ((val &~ rel->howto->dst_mask)
+                    | (((val & rel->howto->src_mask)
+                        + sym_value
+                        + rel->addend)
+                       & rel->howto->dst_mask));
+             if ((bfd_signed_vma) val < - 0x8000
+                 || (bfd_signed_vma) val >= 0x8000)
+               fprintf (stderr,
+                        _("%s: overflow when adjusting relocation against %s\n"),
+                        program_name, bfd_asymbol_name (sym));
+             bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address);
+             break;
+
+           case 2:
+             val = bfd_get_32 (outbfd,
+                               (bfd_byte *) contents + rel->address);
+             val = ((val &~ rel->howto->dst_mask)
+                    | (((val & rel->howto->src_mask)
+                        + sym_value
+                        + rel->addend)
+                       & rel->howto->dst_mask));
+             bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
+             break;
+
+           default:
+             abort ();
+           }
+
+         if (! bfd_is_und_section (bfd_get_section (sym)))
+           rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
+         rel->addend = 0;
+       }
+
+      /* Now that we have incorporated the addend, remove any TOC
+        relocs.  */
+      if (rel->howto == toc_howto)
+       {
+         --*reloc_count_ptr;
+         --relocs;
+         memmove (relocs, relocs + 1,
+                  (size_t) ((reloc_count - i) * sizeof (arelent *)));
+         continue;
+       }
+
+      rel->address += insec->output_offset;
+    }
+}
+
+#endif /* NLMCONV_POWERPC */
+\f
+/* Name of linker.  */
+#ifndef LD_NAME
+#define LD_NAME "ld"
+#endif
+
+/* Temporary file name base.  */
+static char *temp_filename;
+
+/* The user has specified several input files.  Invoke the linker to
+   link them all together, and convert and delete the resulting output
+   file.  */
+
+static char *
+link_inputs (inputs, ld)
+     struct string_list *inputs;
+     char *ld;
+{
+  size_t c;
+  struct string_list *q;
+  char **argv;
+  size_t i;
+  int pid;
+  int status;
+  char *errfmt;
+  char *errarg;
+
+  c = 0;
+  for (q = inputs; q != NULL; q = q->next)
+    ++c;
+
+  argv = (char **) alloca ((c + 5) * sizeof(char *));
+
+#ifndef __MSDOS__
+  if (ld == NULL)
+    {
+      char *p;
+
+      /* Find the linker to invoke based on how nlmconv was run.  */
+      p = program_name + strlen (program_name);
+      while (p != program_name)
+       {
+         if (p[-1] == '/')
+           {
+             ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1);
+             memcpy (ld, program_name, p - program_name);
+             strcpy (ld + (p - program_name), LD_NAME);
+             break;
+           }
+         --p;
+       }
+    }
+#endif
+
+  if (ld == NULL)
+    ld = (char *) LD_NAME;
+
+  temp_filename = choose_temp_base ();
+
+  unlink_on_exit = xmalloc (strlen (temp_filename) + 3);
+  sprintf (unlink_on_exit, "%s.O", temp_filename);
+
+  argv[0] = ld;
+  argv[1] = (char *) "-Ur";
+  argv[2] = (char *) "-o";
+  argv[3] = unlink_on_exit;
+  i = 4;
+  for (q = inputs; q != NULL; q = q->next, i++)
+    argv[i] = q->string;
+  argv[i] = NULL;
+
+  if (debug)
+    {
+      for (i = 0; argv[i] != NULL; i++)
+       fprintf (stderr, " %s", argv[i]);
+      fprintf (stderr, "\n");
+    }
+
+  pid = pexecute (ld, argv, program_name, (char *) NULL, &errfmt, &errarg,
+                 PEXECUTE_SEARCH | PEXECUTE_ONE);
+  if (pid == -1)
+    {
+      fprintf (stderr, _("%s: execution of %s failed: "), program_name, ld);
+      fprintf (stderr, errfmt, errarg);
+      unlink (unlink_on_exit);
+      exit (1);
+    }
+
+  if (pwait (pid, &status, 0) < 0)
+    {
+      perror ("pwait");
+      unlink (unlink_on_exit);
+      exit (1);
+    }
+
+  if (status != 0)
+    {
+      fprintf (stderr, _("%s: Execution of %s failed\n"), program_name, ld);
+      unlink (unlink_on_exit);
+      exit (1);
+    }
+
+  return unlink_on_exit;
+}
diff --git a/binutils/nlmconv.h b/binutils/nlmconv.h
new file mode 100644 (file)
index 0000000..c92a557
--- /dev/null
@@ -0,0 +1,84 @@
+/* nlmconv.h -- header file for NLM conversion program
+   Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   bfd.h, nlm/common.h and nlm/internal.h must be included before this
+   file.  */
+
+/* A linked list of strings.  */
+
+struct string_list
+{
+  struct string_list *next;
+  char *string;
+};
+
+/* The NLM header parser in nlmheader.y stores information in the
+   following variables.  */
+
+extern Nlm_Internal_Fixed_Header *fixed_hdr;
+extern Nlm_Internal_Variable_Header *var_hdr;
+extern Nlm_Internal_Version_Header *version_hdr;
+extern Nlm_Internal_Copyright_Header *copyright_hdr;
+extern Nlm_Internal_Extended_Header *extended_hdr;
+
+/* Procedure named by CHECK.  */
+extern char *check_procedure;
+/* File named by CUSTOM.  */
+extern char *custom_file;
+/* Whether to generate debugging information (DEBUG).  */
+extern boolean debug_info;
+/* Procedure named by EXIT.  */
+extern char *exit_procedure;
+/* Exported symbols (EXPORT).  */
+extern struct string_list *export_symbols;
+/* List of files from INPUT.  */
+extern struct string_list *input_files;
+/* Map file name (MAP, FULLMAP).  */
+extern char *map_file;
+/* Whether a full map has been requested (FULLMAP).  */
+extern boolean full_map;
+/* File named by HELP.  */
+extern char *help_file;
+/* Imported symbols (IMPORT).  */
+extern struct string_list *import_symbols;
+/* File named by MESSAGES.  */
+extern char *message_file;
+/* Autoload module list (MODULE).  */
+extern struct string_list *modules;
+/* File named by OUTPUT.  */
+extern char *output_file;
+/* File named by SHARELIB.  */
+extern char *sharelib_file;
+/* Start procedure name (START).  */
+extern char *start_procedure;
+/* VERBOSE.  */
+extern boolean verbose;
+/* RPC description file (XDCDATA).  */
+extern char *rpc_file;
+
+/* The number of serious parse errors.  */
+extern int parse_errors;
+
+/* The parser.  */
+extern int yyparse PARAMS ((void));
+
+/* Tell the lexer what file to read.  */
+extern boolean nlmlex_file PARAMS ((const char *));
diff --git a/binutils/nlmheader.y b/binutils/nlmheader.y
new file mode 100644 (file)
index 0000000..0f1e22a
--- /dev/null
@@ -0,0 +1,978 @@
+%{/* nlmheader.y - parse NLM header specification keywords.
+     Copyright (C) 1993, 94, 95, 97, 1998 Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This bison file parses the commands recognized by the NetWare NLM
+   linker, except for lists of object files.  It stores the
+   information in global variables.
+
+   This implementation is based on the description in the NetWare Tool
+   Maker Specification manual, edition 1.0.  */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "bfd.h"
+#include "bucomm.h"
+#include "nlm/common.h"
+#include "nlm/internal.h"
+#include "nlmconv.h"
+
+/* Information is stored in the structures pointed to by these
+   variables.  */
+
+Nlm_Internal_Fixed_Header *fixed_hdr;
+Nlm_Internal_Variable_Header *var_hdr;
+Nlm_Internal_Version_Header *version_hdr;
+Nlm_Internal_Copyright_Header *copyright_hdr;
+Nlm_Internal_Extended_Header *extended_hdr;
+
+/* Procedure named by CHECK.  */
+char *check_procedure;
+/* File named by CUSTOM.  */
+char *custom_file;
+/* Whether to generate debugging information (DEBUG).  */
+boolean debug_info;
+/* Procedure named by EXIT.  */
+char *exit_procedure;
+/* Exported symbols (EXPORT).  */
+struct string_list *export_symbols;
+/* List of files from INPUT.  */
+struct string_list *input_files;
+/* Map file name (MAP, FULLMAP).  */
+char *map_file;
+/* Whether a full map has been requested (FULLMAP).  */
+boolean full_map;
+/* File named by HELP.  */
+char *help_file;
+/* Imported symbols (IMPORT).  */
+struct string_list *import_symbols;
+/* File named by MESSAGES.  */
+char *message_file;
+/* Autoload module list (MODULE).  */
+struct string_list *modules;
+/* File named by OUTPUT.  */
+char *output_file;
+/* File named by SHARELIB.  */
+char *sharelib_file;
+/* Start procedure name (START).  */
+char *start_procedure;
+/* VERBOSE.  */
+boolean verbose;
+/* RPC description file (XDCDATA).  */
+char *rpc_file;
+
+/* The number of serious errors that have occurred.  */
+int parse_errors;
+
+/* The current symbol prefix when reading a list of import or export
+   symbols.  */
+static char *symbol_prefix;
+
+/* Parser error message handler.  */
+#define yyerror(msg) nlmheader_error (msg);
+
+/* Local functions.  */
+static int yylex PARAMS ((void));
+static void nlmlex_file_push PARAMS ((const char *));
+static boolean nlmlex_file_open PARAMS ((const char *));
+static int nlmlex_buf_init PARAMS ((void));
+static char nlmlex_buf_add PARAMS ((int));
+static long nlmlex_get_number PARAMS ((const char *));
+static void nlmheader_identify PARAMS ((void));
+static void nlmheader_warn PARAMS ((const char *, int));
+static void nlmheader_error PARAMS ((const char *));
+static struct string_list * string_list_cons PARAMS ((char *,
+                                                     struct string_list *));
+static struct string_list * string_list_append PARAMS ((struct string_list *,
+                                                       struct string_list *));
+static struct string_list * string_list_append1 PARAMS ((struct string_list *,
+                                                        char *));
+static char *xstrdup PARAMS ((const char *));
+
+%}
+
+%union
+{
+  char *string;
+  struct string_list *list;
+};
+
+/* The reserved words.  */
+
+%token CHECK CODESTART COPYRIGHT CUSTOM DATE DEBUG DESCRIPTION EXIT
+%token EXPORT FLAG_ON FLAG_OFF FULLMAP HELP IMPORT INPUT MAP MESSAGES
+%token MODULE MULTIPLE OS_DOMAIN OUTPUT PSEUDOPREEMPTION REENTRANT
+%token SCREENNAME SHARELIB STACK START SYNCHRONIZE
+%token THREADNAME TYPE VERBOSE VERSIONK XDCDATA
+
+/* Arguments.  */
+
+%token <string> STRING
+%token <string> QUOTED_STRING
+
+/* Typed non-terminals.  */
+%type <list> symbol_list_opt symbol_list string_list
+%type <string> symbol
+
+%%
+
+/* Keywords must start in the leftmost column of the file.  Arguments
+   may appear anywhere else.  The lexer uses this to determine what
+   token to return, so we don't have to worry about it here.  */
+
+/* The entire file is just a list of commands.  */
+
+file:  
+         commands
+       ;
+
+/* A possibly empty list of commands.  */
+
+commands:
+         /* May be empty.  */
+       | command commands
+       ;
+
+/* A single command.  There is where most of the work takes place.  */
+
+command:
+         CHECK STRING
+         {
+           check_procedure = $2;
+         }
+       | CODESTART STRING
+         {
+           nlmheader_warn (_("CODESTART is not implemented; sorry"), -1);
+           free ($2);
+         }
+       | COPYRIGHT QUOTED_STRING
+         {
+           int len;
+
+           strncpy (copyright_hdr->stamp, "CoPyRiGhT=", 10);
+           len = strlen ($2);
+           if (len >= NLM_MAX_COPYRIGHT_MESSAGE_LENGTH)
+             {
+               nlmheader_warn (_("copyright string is too long"),
+                               NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1);
+               len = NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1;
+             }
+           copyright_hdr->copyrightMessageLength = len;
+           strncpy (copyright_hdr->copyrightMessage, $2, len);
+           copyright_hdr->copyrightMessage[len] = '\0';
+           free ($2);
+         }
+       | CUSTOM STRING
+         {
+           custom_file = $2;
+         }
+       | DATE STRING STRING STRING
+         {
+           /* We don't set the version stamp here, because we use the
+              version stamp to detect whether the required VERSION
+              keyword was given.  */
+           version_hdr->month = nlmlex_get_number ($2);
+           version_hdr->day = nlmlex_get_number ($3);
+           version_hdr->year = nlmlex_get_number ($4);
+           free ($2);
+           free ($3);
+           free ($4);
+           if (version_hdr->month < 1 || version_hdr->month > 12)
+             nlmheader_warn (_("illegal month"), -1);
+           if (version_hdr->day < 1 || version_hdr->day > 31)
+             nlmheader_warn (_("illegal day"), -1);
+           if (version_hdr->year < 1900 || version_hdr->year > 3000)
+             nlmheader_warn (_("illegal year"), -1);
+         }
+       | DEBUG
+         {
+           debug_info = true;
+         }
+       | DESCRIPTION QUOTED_STRING
+         {
+           int len;
+
+           len = strlen ($2);
+           if (len > NLM_MAX_DESCRIPTION_LENGTH)
+             {
+               nlmheader_warn (_("description string is too long"),
+                               NLM_MAX_DESCRIPTION_LENGTH);
+               len = NLM_MAX_DESCRIPTION_LENGTH;
+             }
+           var_hdr->descriptionLength = len;
+           strncpy (var_hdr->descriptionText, $2, len);
+           var_hdr->descriptionText[len] = '\0';
+           free ($2);
+         }
+       | EXIT STRING
+         {
+           exit_procedure = $2;
+         }
+       | EXPORT
+         {
+           symbol_prefix = NULL;
+         }
+         symbol_list_opt
+         {
+           export_symbols = string_list_append (export_symbols, $3);
+         }
+       | FLAG_ON STRING
+         {
+           fixed_hdr->flags |= nlmlex_get_number ($2);
+           free ($2);
+         }
+       | FLAG_OFF STRING
+         {
+           fixed_hdr->flags &=~ nlmlex_get_number ($2);
+           free ($2);
+         }
+       | FULLMAP
+         {
+           map_file = "";
+           full_map = true;
+         }
+       | FULLMAP STRING
+         {
+           map_file = $2;
+           full_map = true;
+         }
+       | HELP STRING
+         {
+           help_file = $2;
+         }
+       | IMPORT
+         {
+           symbol_prefix = NULL;
+         }
+         symbol_list_opt
+         {
+           import_symbols = string_list_append (import_symbols, $3);
+         }
+       | INPUT string_list
+         {
+           input_files = string_list_append (input_files, $2);
+         }
+       | MAP
+         {
+           map_file = "";
+         }
+       | MAP STRING
+         {
+           map_file = $2;
+         }
+       | MESSAGES STRING
+         {
+           message_file = $2;
+         }
+       | MODULE string_list
+         {
+           modules = string_list_append (modules, $2);
+         }
+       | MULTIPLE
+         {
+           fixed_hdr->flags |= 0x2;
+         }
+       | OS_DOMAIN
+         {
+           fixed_hdr->flags |= 0x10;
+         }
+       | OUTPUT STRING
+         {
+           if (output_file == NULL)
+             output_file = $2;
+           else
+             nlmheader_warn (_("ignoring duplicate OUTPUT statement"), -1);
+         }
+       | PSEUDOPREEMPTION
+         {
+           fixed_hdr->flags |= 0x8;
+         }
+       | REENTRANT
+         {
+           fixed_hdr->flags |= 0x1;
+         }
+       | SCREENNAME QUOTED_STRING
+         {
+           int len;
+
+           len = strlen ($2);
+           if (len >= NLM_MAX_SCREEN_NAME_LENGTH)
+             {
+               nlmheader_warn (_("screen name is too long"),
+                               NLM_MAX_SCREEN_NAME_LENGTH);
+               len = NLM_MAX_SCREEN_NAME_LENGTH;
+             }
+           var_hdr->screenNameLength = len;
+           strncpy (var_hdr->screenName, $2, len);
+           var_hdr->screenName[NLM_MAX_SCREEN_NAME_LENGTH] = '\0';
+           free ($2);
+         }
+       | SHARELIB STRING
+         {
+           sharelib_file = $2;
+         }
+       | STACK STRING
+         {
+           var_hdr->stackSize = nlmlex_get_number ($2);
+           free ($2);
+         }
+       | START STRING
+         {
+           start_procedure = $2;
+         }
+       | SYNCHRONIZE
+         {
+           fixed_hdr->flags |= 0x4;
+         }
+       | THREADNAME QUOTED_STRING
+         {
+           int len;
+
+           len = strlen ($2);
+           if (len >= NLM_MAX_THREAD_NAME_LENGTH)
+             {
+               nlmheader_warn (_("thread name is too long"),
+                               NLM_MAX_THREAD_NAME_LENGTH);
+               len = NLM_MAX_THREAD_NAME_LENGTH;
+             }
+           var_hdr->threadNameLength = len;
+           strncpy (var_hdr->threadName, $2, len);
+           var_hdr->threadName[len] = '\0';
+           free ($2);
+         }
+       | TYPE STRING
+         {
+           fixed_hdr->moduleType = nlmlex_get_number ($2);
+           free ($2);
+         }
+       | VERBOSE
+         {
+           verbose = true;
+         }
+       | VERSIONK STRING STRING STRING
+         {
+           long val;
+
+           strncpy (version_hdr->stamp, "VeRsIoN#", 8);
+           version_hdr->majorVersion = nlmlex_get_number ($2);
+           val = nlmlex_get_number ($3);
+           if (val < 0 || val > 99)
+             nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"),
+                             -1);
+           else
+             version_hdr->minorVersion = val;
+           val = nlmlex_get_number ($4);
+           if (val < 0)
+             nlmheader_warn (_("illegal revision number (must be between 0 and 26)"),
+                             -1);
+           else if (val > 26)
+             version_hdr->revision = 0;
+           else
+             version_hdr->revision = val;
+           free ($2);
+           free ($3);
+           free ($4);
+         }
+       | VERSIONK STRING STRING
+         {
+           long val;
+
+           strncpy (version_hdr->stamp, "VeRsIoN#", 8);
+           version_hdr->majorVersion = nlmlex_get_number ($2);
+           val = nlmlex_get_number ($3);
+           if (val < 0 || val > 99)
+             nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"),
+                             -1);
+           else
+             version_hdr->minorVersion = val;
+           version_hdr->revision = 0;
+           free ($2);
+           free ($3);
+         }
+       | XDCDATA STRING
+         {
+           rpc_file = $2;
+         }
+       ;
+
+/* A possibly empty list of symbols.  */
+
+symbol_list_opt:
+         /* Empty.  */
+         {
+           $$ = NULL;
+         }
+       | symbol_list
+         {
+           $$ = $1;
+         }
+       ;
+
+/* A list of symbols in an import or export list.  Prefixes may appear
+   in parentheses.  We need to use left recursion here to avoid
+   building up a large import list on the parser stack.  */
+
+symbol_list:
+         symbol
+         {
+           $$ = string_list_cons ($1, NULL);
+         }
+       | symbol_prefix
+         {
+           $$ = NULL;
+         }
+       | symbol_list symbol
+         {
+           $$ = string_list_append1 ($1, $2);
+         }
+       | symbol_list symbol_prefix
+         {
+           $$ = $1;
+         }
+       ;
+
+/* A prefix for subsequent symbols.  */
+
+symbol_prefix:
+         '(' STRING ')'
+         {
+           if (symbol_prefix != NULL)
+             free (symbol_prefix);
+           symbol_prefix = $2;
+         }
+       ;
+
+/* A single symbol.  */
+
+symbol:
+         STRING
+         {
+           if (symbol_prefix == NULL)
+             $$ = $1;
+           else
+             {
+               $$ = xmalloc (strlen (symbol_prefix) + strlen ($1) + 2);
+               sprintf ($$, "%s@%s", symbol_prefix, $1);
+               free ($1);
+             }
+         }
+       ;
+
+/* A list of strings.  */
+
+string_list:
+         /* May be empty.  */
+         {
+           $$ = NULL;
+         }
+       | STRING string_list
+         {
+           $$ = string_list_cons ($1, $2);
+         }
+       ;
+
+%%
+
+/* If strerror is just a macro, we want to use the one from libiberty
+   since it will handle undefined values.  */
+#undef strerror
+extern char *strerror ();
+
+/* The lexer is simple, too simple for flex.  Keywords are only
+   recognized at the start of lines.  Everything else must be an
+   argument.  A comma is treated as whitespace.  */
+
+/* The states the lexer can be in.  */
+
+enum lex_state
+{
+  /* At the beginning of a line.  */
+  BEGINNING_OF_LINE,
+  /* In the middle of a line.  */
+  IN_LINE
+};
+
+/* We need to keep a stack of files to handle file inclusion.  */
+
+struct input
+{
+  /* The file to read from.  */
+  FILE *file;
+  /* The name of the file.  */
+  char *name;
+  /* The current line number.  */
+  int lineno;
+  /* The current state.  */
+  enum lex_state state;
+  /* The next file on the stack.  */
+  struct input *next;
+};
+
+/* The current input file.  */
+
+static struct input current;
+
+/* The character which introduces comments.  */
+#define COMMENT_CHAR '#'
+\f
+/* Start the lexer going on the main input file.  */
+
+boolean
+nlmlex_file (name)
+     const char *name;
+{
+  current.next = NULL;
+  return nlmlex_file_open (name);
+}
+
+/* Start the lexer going on a subsidiary input file.  */
+
+static void
+nlmlex_file_push (name)
+     const char *name;
+{
+  struct input *push;
+
+  push = (struct input *) xmalloc (sizeof (struct input));
+  *push = current;
+  if (nlmlex_file_open (name))
+    current.next = push;
+  else
+    {
+      current = *push;
+      free (push);
+    }
+}
+
+/* Start lexing from a file.  */
+
+static boolean
+nlmlex_file_open (name)
+     const char *name;
+{
+  current.file = fopen (name, "r");
+  if (current.file == NULL)
+    {
+      fprintf (stderr, "%s:%s: %s\n", program_name, name, strerror (errno));
+      ++parse_errors;
+      return false;
+    }
+  current.name = xstrdup (name);
+  current.lineno = 1;
+  current.state = BEGINNING_OF_LINE;
+  return true;
+}
+\f
+/* Table used to turn keywords into tokens.  */
+
+struct keyword_tokens_struct
+{
+  const char *keyword;
+  int token;
+};
+
+struct keyword_tokens_struct keyword_tokens[] =
+{
+  { "CHECK", CHECK },
+  { "CODESTART", CODESTART },
+  { "COPYRIGHT", COPYRIGHT },
+  { "CUSTOM", CUSTOM },
+  { "DATE", DATE },
+  { "DEBUG", DEBUG },
+  { "DESCRIPTION", DESCRIPTION },
+  { "EXIT", EXIT },
+  { "EXPORT", EXPORT },
+  { "FLAG_ON", FLAG_ON },
+  { "FLAG_OFF", FLAG_OFF },
+  { "FULLMAP", FULLMAP },
+  { "HELP", HELP },
+  { "IMPORT", IMPORT },
+  { "INPUT", INPUT },
+  { "MAP", MAP },
+  { "MESSAGES", MESSAGES },
+  { "MODULE", MODULE },
+  { "MULTIPLE", MULTIPLE },
+  { "OS_DOMAIN", OS_DOMAIN },
+  { "OUTPUT", OUTPUT },
+  { "PSEUDOPREEMPTION", PSEUDOPREEMPTION },
+  { "REENTRANT", REENTRANT },
+  { "SCREENNAME", SCREENNAME },
+  { "SHARELIB", SHARELIB },
+  { "STACK", STACK },
+  { "STACKSIZE", STACK },
+  { "START", START },
+  { "SYNCHRONIZE", SYNCHRONIZE },
+  { "THREADNAME", THREADNAME },
+  { "TYPE", TYPE },
+  { "VERBOSE", VERBOSE },
+  { "VERSION", VERSIONK },
+  { "XDCDATA", XDCDATA }
+};
+
+#define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0]))
+\f
+/* The lexer accumulates strings in these variables.  */
+static char *lex_buf;
+static int lex_size;
+static int lex_pos;
+
+/* Start accumulating strings into the buffer.  */
+#define BUF_INIT() \
+  ((void) (lex_buf != NULL ? lex_pos = 0 : nlmlex_buf_init ()))
+
+static int
+nlmlex_buf_init ()
+{
+  lex_size = 10;
+  lex_buf = xmalloc (lex_size + 1);
+  lex_pos = 0;
+  return 0;
+}
+
+/* Finish a string in the buffer.  */
+#define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0'))
+
+/* Accumulate a character into the buffer.  */
+#define BUF_ADD(c) \
+  ((void) (lex_pos < lex_size \
+          ? lex_buf[lex_pos++] = (c) \
+          : nlmlex_buf_add (c)))
+
+static char
+nlmlex_buf_add (c)
+     int c;
+{
+  if (lex_pos >= lex_size)
+    {
+      lex_size *= 2;
+      lex_buf = xrealloc (lex_buf, lex_size + 1);
+    }
+
+  return lex_buf[lex_pos++] = c;
+}
+\f
+/* The lexer proper.  This is called by the bison generated parsing
+   code.  */
+
+static int
+yylex ()
+{
+  int c;
+
+tail_recurse:
+
+  c = getc (current.file);
+
+  /* Commas are treated as whitespace characters.  */
+  while (isspace ((unsigned char) c) || c == ',')
+    {
+      current.state = IN_LINE;
+      if (c == '\n')
+       {
+         ++current.lineno;
+         current.state = BEGINNING_OF_LINE;
+       }
+      c = getc (current.file);
+    }
+
+  /* At the end of the file we either pop to the previous file or
+     finish up.  */
+  if (c == EOF)
+    {
+      fclose (current.file);
+      free (current.name);
+      if (current.next == NULL)
+       return 0;
+      else
+       {
+         struct input *next;
+
+         next = current.next;
+         current = *next;
+         free (next);
+         goto tail_recurse;
+       }
+    }
+
+  /* A comment character always means to drop everything until the
+     next newline.  */
+  if (c == COMMENT_CHAR)
+    {
+      do
+       {
+         c = getc (current.file);
+       }
+      while (c != '\n');
+      ++current.lineno;
+      current.state = BEGINNING_OF_LINE;
+      goto tail_recurse;
+    }
+
+  /* An '@' introduces an include file.  */
+  if (c == '@')
+    {
+      do
+       {
+         c = getc (current.file);
+         if (c == '\n')
+           ++current.lineno;
+       }
+      while (isspace ((unsigned char) c));
+      BUF_INIT ();
+      while (! isspace ((unsigned char) c) && c != EOF)
+       {
+         BUF_ADD (c);
+         c = getc (current.file);
+       }
+      BUF_FINISH ();
+
+      ungetc (c, current.file);
+      
+      nlmlex_file_push (lex_buf);
+      goto tail_recurse;
+    }
+
+  /* A non-space character at the start of a line must be the start of
+     a keyword.  */
+  if (current.state == BEGINNING_OF_LINE)
+    {
+      BUF_INIT ();
+      while (isalnum ((unsigned char) c) || c == '_')
+       {
+         if (islower ((unsigned char) c))
+           BUF_ADD (toupper ((unsigned char) c));
+         else
+           BUF_ADD (c);
+         c = getc (current.file);
+       }
+      BUF_FINISH ();
+
+      if (c != EOF && ! isspace ((unsigned char) c) && c != ',')
+       {
+         nlmheader_identify ();
+         fprintf (stderr, _("%s:%d: illegal character in keyword: %c\n"),
+                  current.name, current.lineno, c);
+       }
+      else
+       {
+         unsigned int i;
+
+         for (i = 0; i < KEYWORD_COUNT; i++)
+           {
+             if (lex_buf[0] == keyword_tokens[i].keyword[0]
+                 && strcmp (lex_buf, keyword_tokens[i].keyword) == 0)
+               {
+                 /* Pushing back the final whitespace avoids worrying
+                    about \n here.  */
+                 ungetc (c, current.file);
+                 current.state = IN_LINE;
+                 return keyword_tokens[i].token;
+               }
+           }
+         
+         nlmheader_identify ();
+         fprintf (stderr, _("%s:%d: unrecognized keyword: %s\n"),
+                  current.name, current.lineno, lex_buf);
+       }
+
+      ++parse_errors;
+      /* Treat the rest of this line as a comment.  */
+      ungetc (COMMENT_CHAR, current.file);
+      goto tail_recurse;
+    }
+
+  /* Parentheses just represent themselves.  */
+  if (c == '(' || c == ')')
+    return c;
+
+  /* Handle quoted strings.  */
+  if (c == '"' || c == '\'')
+    {
+      int quote;
+      int start_lineno;
+
+      quote = c;
+      start_lineno = current.lineno;
+
+      c = getc (current.file);
+      BUF_INIT ();
+      while (c != quote && c != EOF)
+       {
+         BUF_ADD (c);
+         if (c == '\n')
+           ++current.lineno;
+         c = getc (current.file);
+       }
+      BUF_FINISH ();
+
+      if (c == EOF)
+       {
+         nlmheader_identify ();
+         fprintf (stderr, _("%s:%d: end of file in quoted string\n"),
+                  current.name, start_lineno);
+         ++parse_errors;
+       }
+
+      /* FIXME: Possible memory leak.  */
+      yylval.string = xstrdup (lex_buf);
+      return QUOTED_STRING;
+    }
+
+  /* Gather a generic argument.  */
+  BUF_INIT ();
+  while (! isspace (c)
+        && c != ','
+        && c != COMMENT_CHAR
+        && c != '('
+        && c != ')')
+    {
+      BUF_ADD (c);
+      c = getc (current.file);
+    }
+  BUF_FINISH ();
+
+  ungetc (c, current.file);
+
+  /* FIXME: Possible memory leak.  */
+  yylval.string = xstrdup (lex_buf);
+  return STRING;
+}
+\f
+/* Get a number from a string.  */
+
+static long
+nlmlex_get_number (s)
+     const char *s;
+{
+  long ret;
+  char *send;
+
+  ret = strtol (s, &send, 10);
+  if (*send != '\0')
+    nlmheader_warn (_("bad number"), -1);
+  return ret;
+}
+
+/* Prefix the nlmconv warnings with a note as to where they come from.
+   We don't use program_name on every warning, because then some
+   versions of the emacs next-error function can't recognize the line
+   number.  */
+
+static void
+nlmheader_identify ()
+{
+  static int done;
+
+  if (! done)
+    {
+      fprintf (stderr, _("%s: problems in NLM command language input:\n"),
+              program_name);
+      done = 1;
+    }
+}
+
+/* Issue a warning.  */
+
+static void
+nlmheader_warn (s, imax)
+     const char *s;
+     int imax;
+{
+  nlmheader_identify ();
+  fprintf (stderr, "%s:%d: %s", current.name, current.lineno, s);
+  if (imax != -1)
+    fprintf (stderr, " (max %d)", imax);
+  fprintf (stderr, "\n");
+}
+
+/* Report an error.  */
+
+static void
+nlmheader_error (s)
+     const char *s;
+{
+  nlmheader_warn (s, -1);
+  ++parse_errors;
+}
+
+/* Add a string to a string list.  */
+
+static struct string_list *
+string_list_cons (s, l)
+     char *s;
+     struct string_list *l;
+{
+  struct string_list *ret;
+
+  ret = (struct string_list *) xmalloc (sizeof (struct string_list));
+  ret->next = l;
+  ret->string = s;
+  return ret;
+}
+
+/* Append a string list to another string list.  */
+
+static struct string_list *
+string_list_append (l1, l2)
+     struct string_list *l1;
+     struct string_list *l2;
+{
+  register struct string_list **pp;
+
+  for (pp = &l1; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = l2;
+  return l1;
+}
+
+/* Append a string to a string list.  */
+
+static struct string_list *
+string_list_append1 (l, s)
+     struct string_list *l;
+     char *s;
+{
+  struct string_list *n;
+  register struct string_list **pp;
+
+  n = (struct string_list *) xmalloc (sizeof (struct string_list));
+  n->next = NULL;
+  n->string = s;
+  for (pp = &l; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = n;
+  return l;
+}
+
+/* Duplicate a string in memory.  */
+
+static char *
+xstrdup (s)
+     const char *s;
+{
+  unsigned long len;
+  char *ret;
+
+  len = strlen (s);
+  ret = xmalloc (len + 1);
+  strcpy (ret, s);
+  return ret;
+}
diff --git a/binutils/nm.1 b/binutils/nm.1
new file mode 100644 (file)
index 0000000..c2ad99e
--- /dev/null
@@ -0,0 +1,230 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH nm 1 "5 November 1991" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+nm \- list symbols from object files.
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B nm
+.RB "[\|" \-a | \-\-debug\-syms "\|]" 
+.RB "[\|" \-g | \-\-extern\-only "\|]"
+.RB "[\|" \-B "\|]"  
+.RB "[\|" \-C | \-\-demangle "\|]" 
+.RB "[\|" \-D | \-\-dynamic "\|]" 
+.RB "[\|" \-s | \-\-print\-armap "\|]" 
+.RB "[\|" \-o | \-\-print\-file\-name "\|]"  
+.RB "[\|" \-n | \-\-numeric\-sort "\|]" 
+.RB "[\|" \-p | \-\-no\-sort "\|]"
+.RB "[\|" \-r | \-\-reverse\-sort "\|]" 
+.RB "[\|" \-\-size\-sort "\|]" 
+.RB "[\|" \-u | \-\-undefined\-only "\|]"  
+.RB "[\|" \-l | \-\-line\-numbers "\|]"
+.RB "[\|" \-\-help "\|]"  
+.RB "[\|" \-\-version "\|]"  
+.RB "[\|" "\-t \fIradix" | \-\-radix=\fIradix "\|]"
+.RB "[\|" \-P | --portability "\|]"
+.RB "[\|" "\-f \fIformat" | \-\-format=\fIformat "\|]"
+.RB "[\|" "\-\-target=\fIbfdname" "\|]"
+.RB "[\|" \c
+.I objfile\c
+\&.\|.\|.\|]
+.ad b
+.hy 1
+.SH DESCRIPTION
+GNU \c
+.B nm\c
+\& lists the symbols from object files \c
+.I objfile\c
+\&.  If no object files are given as arguments, \c
+.B nm\c
+\& assumes `\|\c
+.B a.out\c
+\|'.
+
+.SH OPTIONS
+The long and short forms of options, shown here as alternatives, are
+equivalent.
+
+.TP
+.B \-A
+.TP
+.B \-o
+.TP
+.B \-\-print\-file\-name 
+Precede each symbol by the name of the input file where it was found,
+rather than identifying the input file once only before all of its
+symbols. 
+
+.TP
+.B \-a
+.TP
+.B \-\-debug\-syms 
+Display debugger-only symbols; normally these are not listed.
+
+.TP
+.B \-B
+The same as
+.B \-\-format=bsd
+(for compatibility with the MIPS \fBnm\fP).
+
+.TP
+.B \-C
+.TP
+.B \-\-demangle
+Decode (\fIdemangle\fP) low-level symbol names into user-level names.
+Besides removing any initial underscore prepended by the system, this
+makes C++ function names readable.
+
+.TP
+.B \-D
+.TP
+.B \-\-dynamic
+Display the dynamic symbols rather than the normal symbols.  This is
+only meaningful for dynamic objects, such as certain types of shared
+libraries.
+
+.TP
+.B "\-f \fIformat"
+Use the output format \fIformat\fP, which can be ``bsd'',
+``sysv'', or ``posix''.  The default is ``bsd''.
+Only the first character of \fIformat\fP is significant; it can be
+either upper or lower case.
+
+.TP
+.B \-g
+.TP
+.B \-\-extern\-only 
+Display only external symbols.
+
+.TP
+.B \-n
+.TP
+.B \-v
+.TP
+.B \-\-numeric\-sort 
+Sort symbols numerically by their addresses, not alphabetically by their
+names. 
+
+.TP
+.B \-p
+.TP
+.B \-\-no\-sort 
+Don't bother to sort the symbols in any order; just print them in the
+order encountered.
+
+.TP
+.B \-P
+.TP
+.B \-\-portability
+Use the POSIX.2 standard output format instead of the default format.
+Equivalent to ``\-f posix''.
+
+.TP
+.B \-s
+.TP
+.B \-\-print\-armap
+When listing symbols from archive members, include the index: a mapping
+(stored in the archive by \c
+.B ar\c
+\& or \c
+.B ranlib\c
+\&) of what modules
+contain definitions for what names.
+
+.TP
+.B \-r
+.TP
+.B \-\-reverse\-sort 
+Reverse the sense of the sort (whether numeric or alphabetic); let the
+last come first.
+
+.TP
+.B \-\-size\-sort 
+Sort symbols by size.  The size is computed as the difference between
+the value of the symbol and the value of the symbol with the next higher
+value.  The size of the symbol is printed, rather than the value.
+
+.TP
+.B "\-t \fIradix"
+.TP
+.B "\-\-radix=\fIradix"
+Use \fIradix\fP as the radix for printing the symbol values.  It must be
+``d'' for decimal, ``o'' for octal, or ``x'' for hexadecimal.
+
+.TP
+.BI "\-\-target=" "bfdname"
+Specify an object code format other than your system's default format.
+See 
+.BR objdump ( 1 ),
+for information on listing available formats.
+
+.TP
+.B \-u
+.TP
+.B \-\-undefined\-only 
+Display only undefined symbols (those external to each object file).
+
+.TP
+.B \-l
+.TP
+.B \-\-line\-numbers
+For each symbol, use debugging information to try to find a filename and
+line number.  For a defined symbol, look for the line number of the
+address of the symbol.  For an undefined symbol, look for the line
+number of a relocation entry which refers to the symbol.  If line number
+information can be found, print it after the other symbol information.
+
+.TP
+.B \-V
+.TP
+.B \-\-version
+Show the version number of
+.B nm
+and exit.
+
+.TP
+.B \-\-help
+Show a summary of the options to
+.B nm
+and exit.
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'"
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (October 1991);
+.BR ar "(" 1 "),"
+.BR objdump ( 1 ),
+.BR ranlib "(" 1 ")."
+
+
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/nm.c b/binutils/nm.c
new file mode 100644 (file)
index 0000000..c51b7fb
--- /dev/null
@@ -0,0 +1,1558 @@
+/* nm.c -- Describe symbol table of a rel file.
+   Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#include "bfd.h"
+#include "progress.h"
+#include "bucomm.h"
+#include "getopt.h"
+#include "aout/stab_gnu.h"
+#include "aout/ranlib.h"
+#include "demangle.h"
+#include "libiberty.h"
+
+/* When sorting by size, we use this structure to hold the size and a
+   pointer to the minisymbol.  */
+
+struct size_sym
+{
+  const PTR minisym;
+  bfd_vma size;
+};
+
+/* When fetching relocs, we use this structure to pass information to
+   get_relocs.  */
+
+struct get_relocs_info
+{
+  asection **secs;
+  arelent ***relocs;
+  long *relcount;
+  asymbol **syms;
+};
+
+static void
+usage PARAMS ((FILE *, int));
+
+static void
+set_print_radix PARAMS ((char *));
+
+static void
+set_output_format PARAMS ((char *));
+
+static void
+display_archive PARAMS ((bfd *));
+
+static boolean
+display_file PARAMS ((char *filename));
+
+static void
+display_rel_file PARAMS ((bfd * file, bfd * archive));
+
+static long
+filter_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int));
+
+static long
+sort_symbols_by_size PARAMS ((bfd *, boolean, PTR, long, unsigned int,
+                             struct size_sym **));
+
+static void
+print_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int, bfd *));
+
+static void
+print_size_symbols PARAMS ((bfd *, boolean, struct size_sym *, long, bfd *));
+
+static void
+print_symname PARAMS ((const char *, const char *, bfd *));
+
+static void
+print_symbol PARAMS ((bfd *, asymbol *, bfd *));
+
+static void
+print_symdef_entry PARAMS ((bfd * abfd));
+
+/* The sorting functions.  */
+
+static int
+numeric_forward PARAMS ((const PTR, const PTR));
+
+static int
+numeric_reverse PARAMS ((const PTR, const PTR));
+
+static int
+non_numeric_forward PARAMS ((const PTR, const PTR));
+
+static int
+non_numeric_reverse PARAMS ((const PTR, const PTR));
+
+static int
+size_forward1 PARAMS ((const PTR, const PTR));
+
+static int
+size_forward2 PARAMS ((const PTR, const PTR));
+
+/* The output formatting functions.  */
+
+static void
+print_object_filename_bsd PARAMS ((char *filename));
+
+static void
+print_object_filename_sysv PARAMS ((char *filename));
+
+static void
+print_object_filename_posix PARAMS ((char *filename));
+
+
+static void
+print_archive_filename_bsd PARAMS ((char *filename));
+
+static void
+print_archive_filename_sysv PARAMS ((char *filename));
+
+static void
+print_archive_filename_posix PARAMS ((char *filename));
+
+
+static void
+print_archive_member_bsd PARAMS ((char *archive, CONST char *filename));
+
+static void
+print_archive_member_sysv PARAMS ((char *archive, CONST char *filename));
+
+static void
+print_archive_member_posix PARAMS ((char *archive, CONST char *filename));
+
+
+static void
+print_symbol_filename_bsd PARAMS ((bfd * archive_bfd, bfd * abfd));
+
+static void
+print_symbol_filename_sysv PARAMS ((bfd * archive_bfd, bfd * abfd));
+
+static void
+print_symbol_filename_posix PARAMS ((bfd * archive_bfd, bfd * abfd));
+
+
+static void
+print_value PARAMS ((bfd_vma));
+
+static void
+print_symbol_info_bsd PARAMS ((symbol_info * info, bfd * abfd));
+
+static void
+print_symbol_info_sysv PARAMS ((symbol_info * info, bfd * abfd));
+
+static void
+print_symbol_info_posix PARAMS ((symbol_info * info, bfd * abfd));
+
+static void
+get_relocs PARAMS ((bfd *, asection *, PTR));
+
+/* Support for different output formats.  */
+struct output_fns
+  {
+    /* Print the name of an object file given on the command line.  */
+    void (*print_object_filename) PARAMS ((char *filename));
+
+    /* Print the name of an archive file given on the command line.  */
+    void (*print_archive_filename) PARAMS ((char *filename));
+
+    /* Print the name of an archive member file.  */
+    void (*print_archive_member) PARAMS ((char *archive, CONST char *filename));
+
+    /* Print the name of the file (and archive, if there is one)
+       containing a symbol.  */
+    void (*print_symbol_filename) PARAMS ((bfd * archive_bfd, bfd * abfd));
+
+    /* Print a line of information about a symbol.  */
+    void (*print_symbol_info) PARAMS ((symbol_info * info, bfd * abfd));
+  };
+static struct output_fns formats[] =
+{
+  {print_object_filename_bsd,
+   print_archive_filename_bsd,
+   print_archive_member_bsd,
+   print_symbol_filename_bsd,
+   print_symbol_info_bsd},
+  {print_object_filename_sysv,
+   print_archive_filename_sysv,
+   print_archive_member_sysv,
+   print_symbol_filename_sysv,
+   print_symbol_info_sysv},
+  {print_object_filename_posix,
+   print_archive_filename_posix,
+   print_archive_member_posix,
+   print_symbol_filename_posix,
+   print_symbol_info_posix}
+};
+
+/* Indices in `formats'.  */
+#define FORMAT_BSD 0
+#define FORMAT_SYSV 1
+#define FORMAT_POSIX 2
+#define FORMAT_DEFAULT FORMAT_BSD
+
+/* The output format to use.  */
+static struct output_fns *format = &formats[FORMAT_DEFAULT];
+
+
+/* Command options.  */
+
+static int do_demangle = 0;    /* Pretty print C++ symbol names.  */
+static int external_only = 0;  /* print external symbols only */
+static int defined_only = 0;   /* Print defined symbols only */
+static int no_sort = 0;                /* don't sort; print syms in order found */
+static int print_debug_syms = 0;       /* print debugger-only symbols too */
+static int print_armap = 0;    /* describe __.SYMDEF data in archive files.  */
+static int reverse_sort = 0;   /* sort in downward(alpha or numeric) order */
+static int sort_numerically = 0;       /* sort in numeric rather than alpha order */
+static int sort_by_size = 0;   /* sort by size of symbol */
+static int undefined_only = 0; /* print undefined symbols only */
+static int dynamic = 0;                /* print dynamic symbols.  */
+static int show_version = 0;   /* show the version number */
+static int show_stats = 0;     /* show statistics */
+static int line_numbers = 0;   /* print line numbers for symbols */
+
+/* When to print the names of files.  Not mutually exclusive in SYSV format.  */
+static int filename_per_file = 0;      /* Once per file, on its own line.  */
+static int filename_per_symbol = 0;    /* Once per symbol, at start of line.  */
+
+/* Print formats for printing a symbol value.  */
+#ifndef BFD64
+static char value_format[] = "%08lx";
+#else
+#if BFD_HOST_64BIT_LONG
+static char value_format[] = "%016lx";
+#else
+/* We don't use value_format for this case.  */
+#endif
+#endif
+static int print_radix = 16;
+/* Print formats for printing stab info.  */
+static char other_format[] = "%02x";
+static char desc_format[] = "%04x";
+
+static char *target = NULL;
+
+/* Used to cache the line numbers for a BFD.  */
+static bfd *lineno_cache_bfd;
+static bfd *lineno_cache_rel_bfd;
+
+static struct option long_options[] =
+{
+  {"debug-syms", no_argument, &print_debug_syms, 1},
+  {"demangle", no_argument, &do_demangle, 1},
+  {"dynamic", no_argument, &dynamic, 1},
+  {"extern-only", no_argument, &external_only, 1},
+  {"format", required_argument, 0, 'f'},
+  {"help", no_argument, 0, 'h'},
+  {"line-numbers", no_argument, 0, 'l'},
+  {"no-cplus", no_argument, &do_demangle, 0},  /* Linux compatibility.  */
+  {"no-demangle", no_argument, &do_demangle, 0},
+  {"no-sort", no_argument, &no_sort, 1},
+  {"numeric-sort", no_argument, &sort_numerically, 1},
+  {"portability", no_argument, 0, 'P'},
+  {"print-armap", no_argument, &print_armap, 1},
+  {"print-file-name", no_argument, 0, 'o'},
+  {"radix", required_argument, 0, 't'},
+  {"reverse-sort", no_argument, &reverse_sort, 1},
+  {"size-sort", no_argument, &sort_by_size, 1},
+  {"stats", no_argument, &show_stats, 1},
+  {"target", required_argument, 0, 200},
+  {"defined-only", no_argument, &defined_only, 1},
+  {"undefined-only", no_argument, &undefined_only, 1},
+  {"version", no_argument, &show_version, 1},
+  {0, no_argument, 0, 0}
+};
+\f
+/* Some error-reporting functions */
+
+static void
+usage (stream, status)
+     FILE *stream;
+     int status;
+{
+  fprintf (stream, _("\
+Usage: %s [-aABCDglnopPrsuvV] [-t radix] [--radix=radix] [--target=bfdname]\n\
+       [--debug-syms] [--extern-only] [--print-armap] [--print-file-name]\n\
+       [--numeric-sort] [--no-sort] [--reverse-sort] [--size-sort]\n\
+       [--undefined-only] [--portability] [-f {bsd,sysv,posix}]\n\
+       [--format={bsd,sysv,posix}] [--demangle] [--no-demangle] [--dynamic]\n\
+       [--defined-only] [--line-numbers]\n\
+       [--version] [--help]\n\
+       [file...]\n"),
+          program_name);
+  list_supported_targets (program_name, stream);
+  if (status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (status);
+}
+
+/* Set the radix for the symbol value and size according to RADIX.  */
+
+static void
+set_print_radix (radix)
+     char *radix;
+{
+  switch (*radix)
+    {
+    case 'x':
+      break;
+    case 'd':
+    case 'o':
+      if (*radix == 'd')
+       print_radix = 10;
+      else
+       print_radix = 8;
+#ifndef BFD64
+      value_format[4] = *radix;
+#else
+#if BFD_HOST_64BIT_LONG
+      value_format[5] = *radix;
+#else
+      /* This case requires special handling for octal and decimal
+         printing.  */
+#endif
+#endif
+      other_format[3] = desc_format[3] = *radix;
+      break;
+    default:
+      fprintf (stderr, _("%s: %s: invalid radix\n"), program_name, radix);
+      exit (1);
+    }
+}
+
+static void
+set_output_format (f)
+     char *f;
+{
+  int i;
+
+  switch (*f)
+    {
+    case 'b':
+    case 'B':
+      i = FORMAT_BSD;
+      break;
+    case 'p':
+    case 'P':
+      i = FORMAT_POSIX;
+      break;
+    case 's':
+    case 'S':
+      i = FORMAT_SYSV;
+      break;
+    default:
+      fprintf (stderr, _("%s: %s: invalid output format\n"), program_name, f);
+      exit (1);
+    }
+  format = &formats[i];
+}
+\f
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int retval;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = *argv;
+  xmalloc_set_program_name (program_name);
+
+  START_PROGRESS (program_name, 0);
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  while ((c = getopt_long (argc, argv, "aABCDef:glnopPrst:uvV", long_options, (int *) 0)) != EOF)
+    {
+      switch (c)
+       {
+       case 'a':
+         print_debug_syms = 1;
+         break;
+       case 'A':
+       case 'o':
+         filename_per_symbol = 1;
+         break;
+       case 'B':               /* For MIPS compatibility.  */
+         set_output_format ("bsd");
+         break;
+       case 'C':
+         do_demangle = 1;
+         break;
+       case 'D':
+         dynamic = 1;
+         break;
+       case 'e':
+         /* Ignored for HP/UX compatibility.  */
+         break;
+       case 'f':
+         set_output_format (optarg);
+         break;
+       case 'g':
+         external_only = 1;
+         break;
+       case 'h':
+         usage (stdout, 0);
+       case 'l':
+         line_numbers = 1;
+         break;
+       case 'n':
+       case 'v':
+         sort_numerically = 1;
+         break;
+       case 'p':
+         no_sort = 1;
+         break;
+       case 'P':
+         set_output_format ("posix");
+         break;
+       case 'r':
+         reverse_sort = 1;
+         break;
+       case 's':
+         print_armap = 1;
+         break;
+       case 't':
+         set_print_radix (optarg);
+         break;
+       case 'u':
+         undefined_only = 1;
+         break;
+       case 'V':
+         show_version = 1;
+         break;
+
+       case 200:               /* --target */
+         target = optarg;
+         break;
+
+       case 0:         /* A long option that just sets a flag.  */
+         break;
+
+       default:
+         usage (stderr, 1);
+       }
+    }
+
+  if (show_version)
+    print_version ("nm");
+
+  /* OK, all options now parsed.  If no filename specified, do a.out.  */
+  if (optind == argc)
+    return !display_file ("a.out");
+
+  retval = 0;
+
+  if (argc - optind > 1)
+    filename_per_file = 1;
+
+  /* We were given several filenames to do.  */
+  while (optind < argc)
+    {
+      PROGRESS (1);
+      if (!display_file (argv[optind++]))
+       retval++;
+    }
+
+  END_PROGRESS (program_name);
+
+#ifdef HAVE_SBRK
+  if (show_stats)
+    {
+      char *lim = (char *) sbrk (0);
+
+      fprintf (stderr, _("%s: data size %ld\n"), program_name,
+              (long) (lim - (char *) &environ));
+    }
+#endif
+
+  exit (retval);
+  return retval;
+}
+\f
+static void
+display_archive (file)
+     bfd *file;
+{
+  bfd *arfile = NULL;
+  bfd *last_arfile = NULL;
+  char **matching;
+
+  (*format->print_archive_filename) (bfd_get_filename (file));
+
+  if (print_armap)
+    print_symdef_entry (file);
+
+  for (;;)
+    {
+      PROGRESS (1);
+
+      arfile = bfd_openr_next_archived_file (file, arfile);
+
+      if (arfile == NULL)
+       {
+         if (bfd_get_error () != bfd_error_no_more_archived_files)
+           bfd_fatal (bfd_get_filename (file));
+         break;
+       }
+
+      if (bfd_check_format_matches (arfile, bfd_object, &matching))
+       {
+         (*format->print_archive_member) (bfd_get_filename (file),
+                                          bfd_get_filename (arfile));
+         display_rel_file (arfile, file);
+       }
+      else
+       {
+         bfd_nonfatal (bfd_get_filename (arfile));
+         if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+           {
+             list_matching_formats (matching);
+             free (matching);
+           }
+       }
+
+      if (last_arfile != NULL)
+       {
+         bfd_close (last_arfile);
+         lineno_cache_bfd = NULL;
+         lineno_cache_rel_bfd = NULL;
+       }
+      last_arfile = arfile;
+    }
+
+  if (last_arfile != NULL)
+    {
+      bfd_close (last_arfile);
+      lineno_cache_bfd = NULL;
+      lineno_cache_rel_bfd = NULL;
+    }
+}
+
+static boolean
+display_file (filename)
+     char *filename;
+{
+  boolean retval = true;
+  bfd *file;
+  char **matching;
+
+  file = bfd_openr (filename, target);
+  if (file == NULL)
+    {
+      bfd_nonfatal (filename);
+      return false;
+    }
+
+  if (bfd_check_format (file, bfd_archive))
+    {
+      display_archive (file);
+    }
+  else if (bfd_check_format_matches (file, bfd_object, &matching))
+    {
+      (*format->print_object_filename) (filename);
+      display_rel_file (file, NULL);
+    }
+  else
+    {
+      bfd_nonfatal (filename);
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      retval = false;
+    }
+
+  if (bfd_close (file) == false)
+    bfd_fatal (filename);
+
+  lineno_cache_bfd = NULL;
+  lineno_cache_rel_bfd = NULL;
+
+  return retval;
+}
+\f
+/* These globals are used to pass information into the sorting
+   routines.  */
+static bfd *sort_bfd;
+static boolean sort_dynamic;
+static asymbol *sort_x;
+static asymbol *sort_y;
+
+/* Symbol-sorting predicates */
+#define valueof(x) ((x)->section->vma + (x)->value)
+
+/* Numeric sorts.  Undefined symbols are always considered "less than"
+   defined symbols with zero values.  Common symbols are not treated
+   specially -- i.e., their sizes are used as their "values".  */
+
+static int
+numeric_forward (P_x, P_y)
+     const PTR P_x;
+     const PTR P_y;
+{
+  asymbol *x, *y;
+  asection *xs, *ys;
+
+  x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
+  y =  bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
+  if (x == NULL || y == NULL)
+    bfd_fatal (bfd_get_filename (sort_bfd));
+
+  xs = bfd_get_section (x);
+  ys = bfd_get_section (y);
+
+  if (bfd_is_und_section (xs))
+    {
+      if (! bfd_is_und_section (ys))
+       return -1;
+    }
+  else if (bfd_is_und_section (ys))
+    return 1;
+  else if (valueof (x) != valueof (y))
+    return valueof (x) < valueof (y) ? -1 : 1;
+
+  return non_numeric_forward (P_x, P_y);
+}
+
+static int
+numeric_reverse (x, y)
+     const PTR x;
+     const PTR y;
+{
+  return - numeric_forward (x, y);
+}
+
+static int
+non_numeric_forward (P_x, P_y)
+     const PTR P_x;
+     const PTR P_y;
+{
+  asymbol *x, *y;
+  const char *xn, *yn;
+
+  x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
+  y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
+  if (x == NULL || y == NULL)
+    bfd_fatal (bfd_get_filename (sort_bfd));
+
+  xn = bfd_asymbol_name (x);
+  yn = bfd_asymbol_name (y);
+
+  return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
+         ((yn == NULL) ? 1 : strcmp (xn, yn)));
+}
+
+static int
+non_numeric_reverse (x, y)
+     const PTR x;
+     const PTR y;
+{
+  return - non_numeric_forward (x, y);
+}
+
+static int (*(sorters[2][2])) PARAMS ((const PTR, const PTR)) =
+{
+  { non_numeric_forward, non_numeric_reverse },
+  { numeric_forward, numeric_reverse }
+};
+
+/* This sort routine is used by sort_symbols_by_size.  It is similar
+   to numeric_forward, but when symbols have the same value it sorts
+   by section VMA.  This simplifies the sort_symbols_by_size code
+   which handles symbols at the end of sections.  Also, this routine
+   tries to sort file names before other symbols with the same value.
+   That will make the file name have a zero size, which will make
+   sort_symbols_by_size choose the non file name symbol, leading to
+   more meaningful output.  For similar reasons, this code sorts
+   gnu_compiled_* and gcc2_compiled before other symbols with the same
+   value.  */
+
+static int
+size_forward1 (P_x, P_y)
+     const PTR P_x;
+     const PTR P_y;
+{
+  asymbol *x, *y;
+  asection *xs, *ys;
+  const char *xn, *yn;
+  size_t xnl, ynl;
+  int xf, yf;
+
+  x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x);
+  y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y);
+  if (x == NULL || y == NULL)
+    bfd_fatal (bfd_get_filename (sort_bfd));
+
+  xs = bfd_get_section (x);
+  ys = bfd_get_section (y);
+
+  if (bfd_is_und_section (xs))
+    abort ();
+  if (bfd_is_und_section (ys))
+    abort ();
+
+  if (valueof (x) != valueof (y))
+    return valueof (x) < valueof (y) ? -1 : 1;
+
+  if (xs->vma != ys->vma)
+    return xs->vma < ys->vma ? -1 : 1;
+
+  xn = bfd_asymbol_name (x);
+  yn = bfd_asymbol_name (y);
+  xnl = strlen (xn);
+  ynl = strlen (yn);
+
+  /* The symbols gnu_compiled and gcc2_compiled convey even less
+     information than the file name, so sort them out first.  */
+
+  xf = (strstr (xn, "gnu_compiled") != NULL
+       || strstr (xn, "gcc2_compiled") != NULL);
+  yf = (strstr (yn, "gnu_compiled") != NULL
+       || strstr (yn, "gcc2_compiled") != NULL);
+
+  if (xf && ! yf)
+    return -1;
+  if (! xf && yf)
+    return 1;
+
+  /* We use a heuristic for the file name.  It may not work on non
+     Unix systems, but it doesn't really matter; the only difference
+     is precisely which symbol names get printed.  */
+
+#define file_symbol(s, sn, snl)                        \
+  (((s)->flags & BSF_FILE) != 0                        \
+   || ((sn)[(snl) - 2] == '.'                  \
+       && ((sn)[(snl) - 1] == 'o'              \
+          || (sn)[(snl) - 1] == 'a')))
+
+  xf = file_symbol (x, xn, xnl);
+  yf = file_symbol (y, yn, ynl);
+
+  if (xf && ! yf)
+    return -1;
+  if (! xf && yf)
+    return 1;
+
+  return non_numeric_forward (P_x, P_y);
+}
+
+/* This sort routine is used by sort_symbols_by_size.  It is sorting
+   an array of size_sym structures into size order.  */
+
+static int
+size_forward2 (P_x, P_y)
+     const PTR P_x;
+     const PTR P_y;
+{
+  const struct size_sym *x = (const struct size_sym *) P_x;
+  const struct size_sym *y = (const struct size_sym *) P_y;
+
+  if (x->size < y->size)
+    return reverse_sort ? 1 : -1;
+  else if (x->size > y->size)
+    return reverse_sort ? -1 : 1;
+  else
+    return sorters[0][reverse_sort] (x->minisym, y->minisym);
+}
+
+/* Sort the symbols by size.  We guess the size by assuming that the
+   difference between the address of a symbol and the address of the
+   next higher symbol is the size.  FIXME: ELF actually stores a size
+   with each symbol.  We should use it.  */
+
+static long
+sort_symbols_by_size (abfd, dynamic, minisyms, symcount, size, symsizesp)
+     bfd *abfd;
+     boolean dynamic;
+     PTR minisyms;
+     long symcount;
+     unsigned int size;
+     struct size_sym **symsizesp;
+{
+  struct size_sym *symsizes;
+  bfd_byte *from, *fromend;
+  asymbol *sym = NULL;
+  asymbol *store_sym, *store_next;
+
+  qsort (minisyms, symcount, size, size_forward1);
+
+  /* We are going to return a special set of symbols and sizes to
+     print.  */
+  symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym));
+  *symsizesp = symsizes;
+
+  /* Note that filter_symbols has already removed all absolute and
+     undefined symbols.  Here we remove all symbols whose size winds
+     up as zero.  */
+
+  from = (bfd_byte *) minisyms;
+  fromend = from + symcount * size;
+
+  store_sym = sort_x;
+  store_next = sort_y;
+
+  if (from < fromend)
+    {
+      sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from,
+                                     store_sym);
+      if (sym == NULL)
+       bfd_fatal (bfd_get_filename (abfd));
+    }
+
+  for (; from < fromend; from += size)
+    {
+      asymbol *next;
+      asection *sec;
+      bfd_vma sz;
+      asymbol *temp;
+
+      if (from + size < fromend)
+       {
+         next = bfd_minisymbol_to_symbol (abfd,
+                                          dynamic,
+                                          (const PTR) (from + size),
+                                          store_next);
+         if (next == NULL)
+           bfd_fatal (bfd_get_filename (abfd));
+       }
+      else
+       next = NULL;
+
+      sec = bfd_get_section (sym);
+
+      if (bfd_is_com_section (sec))
+       sz = sym->value;
+      else
+       {
+         if (from + size < fromend
+             && sec == bfd_get_section (next))
+           sz = valueof (next) - valueof (sym);
+         else
+           sz = (bfd_get_section_vma (abfd, sec)
+                 + bfd_section_size (abfd, sec)
+                 - valueof (sym));
+       }
+
+      if (sz != 0)
+       {
+         symsizes->minisym = (const PTR) from;
+         symsizes->size = sz;
+         ++symsizes;
+       }
+
+      sym = next;
+
+      temp = store_sym;
+      store_sym = store_next;
+      store_next = temp;
+    }
+
+  symcount = symsizes - *symsizesp;
+
+  /* We must now sort again by size.  */
+  qsort ((PTR) *symsizesp, symcount, sizeof (struct size_sym), size_forward2);
+
+  return symcount;
+}
+\f
+/* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.  */
+
+static void
+display_rel_file (abfd, archive_bfd)
+     bfd *abfd;
+     bfd *archive_bfd;
+{
+  long symcount;
+  PTR minisyms;
+  unsigned int size;
+  struct size_sym *symsizes;
+
+  if (! dynamic)
+    {
+      if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
+       {
+         fprintf (stderr, _("%s: no symbols\n"), bfd_get_filename (abfd));
+         return;
+       }
+    }
+
+  symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size);
+  if (symcount < 0)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  if (symcount == 0)
+    {
+      fprintf (stderr, _("%s: no symbols\n"), bfd_get_filename (abfd));
+      return;
+    }
+
+  /* Discard the symbols we don't want to print.
+     It's OK to do this in place; we'll free the storage anyway
+     (after printing).  */
+
+  symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size);
+
+  symsizes = NULL;
+  if (! no_sort)
+    {
+      sort_bfd = abfd;
+      sort_dynamic = dynamic;
+      sort_x = bfd_make_empty_symbol (abfd);
+      sort_y = bfd_make_empty_symbol (abfd);
+      if (sort_x == NULL || sort_y == NULL)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      if (! sort_by_size)
+       qsort (minisyms, symcount, size,
+              sorters[sort_numerically][reverse_sort]);
+      else
+       symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount,
+                                        size, &symsizes);
+    }
+
+  if (! sort_by_size)
+    print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
+  else
+    print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
+
+  free (minisyms);
+}
+\f
+/* Choose which symbol entries to print;
+   compact them downward to get rid of the rest.
+   Return the number of symbols to be printed.  */
+
+static long
+filter_symbols (abfd, dynamic, minisyms, symcount, size)
+     bfd *abfd;
+     boolean dynamic;
+     PTR minisyms;
+     long symcount;
+     unsigned int size;
+{
+  bfd_byte *from, *fromend, *to;
+  asymbol *store;
+
+  store = bfd_make_empty_symbol (abfd);
+  if (store == NULL)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  from = (bfd_byte *) minisyms;
+  fromend = from + symcount * size;
+  to = (bfd_byte *) minisyms;
+
+  for (; from < fromend; from += size)
+    {
+      int keep = 0;
+      asymbol *sym;
+
+      PROGRESS (1);
+      
+      sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from, store);
+      if (sym == NULL)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      if (undefined_only)
+       keep = bfd_is_und_section (sym->section);
+      else if (external_only)
+       keep = ((sym->flags & BSF_GLOBAL) != 0
+               || (sym->flags & BSF_WEAK) != 0
+               || bfd_is_und_section (sym->section)
+               || bfd_is_com_section (sym->section));
+      else
+       keep = 1;
+
+      if (keep
+         && ! print_debug_syms
+         && (sym->flags & BSF_DEBUGGING) != 0)
+       keep = 0;
+
+      if (keep
+         && sort_by_size
+         && (bfd_is_abs_section (sym->section)
+             || bfd_is_und_section (sym->section)))
+       keep = 0;
+
+      if (keep
+         && defined_only)
+       {
+         if (bfd_is_und_section (sym->section))
+           keep = 0;
+       }
+
+      if (keep)
+       {
+         memcpy (to, from, size);
+         to += size;
+       }
+    }
+
+  return (to - (bfd_byte *) minisyms) / size;
+}
+\f
+/* Print symbol name NAME, read from ABFD, with printf format FORMAT,
+   demangling it if requested.  */
+
+static void
+print_symname (format, name, abfd)
+     const char *format;
+     const char *name;
+     bfd *abfd;
+{
+  if (do_demangle && *name)
+    {
+      char *res;
+
+      /* In this mode, give a user-level view of the symbol name
+        even if it's not mangled; strip off any leading
+        underscore.  */
+      if (bfd_get_symbol_leading_char (abfd) == name[0])
+       name++;
+
+      res = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+      if (res)
+       {
+         printf (format, res);
+         free (res);
+         return;
+       }
+    }
+
+  printf (format, name);
+}
+
+/* Print the symbols.  If ARCHIVE_BFD is non-NULL, it is the archive
+   containing ABFD.  */
+
+static void
+print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd)
+     bfd *abfd;
+     boolean dynamic;
+     PTR minisyms;
+     long symcount;
+     unsigned int size;
+     bfd *archive_bfd;
+{
+  asymbol *store;
+  bfd_byte *from, *fromend;
+
+  store = bfd_make_empty_symbol (abfd);
+  if (store == NULL)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  from = (bfd_byte *) minisyms;
+  fromend = from + symcount * size;
+  for (; from < fromend; from += size)
+    {
+      asymbol *sym;
+
+      sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store);
+      if (sym == NULL)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      print_symbol (abfd, sym, archive_bfd);
+    }
+}
+
+/* Print the symbols when sorting by size.  */
+
+static void 
+print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd)
+     bfd *abfd;
+     boolean dynamic;
+     struct size_sym *symsizes;
+     long symcount;
+     bfd *archive_bfd;
+{
+  asymbol *store;
+  struct size_sym *from, *fromend;
+
+  store = bfd_make_empty_symbol (abfd);
+  if (store == NULL)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  from = symsizes;
+  fromend = from + symcount;
+  for (; from < fromend; from++)
+    {
+      asymbol *sym;
+
+      sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store);
+      if (sym == NULL)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      /* Set the symbol value so that we actually display the symbol
+         size.  */
+      sym->value = from->size - bfd_section_vma (abfd, bfd_get_section (sym));
+
+      print_symbol (abfd, sym, archive_bfd);
+    }
+}
+
+/* Print a single symbol.  */
+
+static void
+print_symbol (abfd, sym, archive_bfd)
+     bfd *abfd;
+     asymbol *sym;
+     bfd *archive_bfd;
+{
+  PROGRESS (1);
+
+  (*format->print_symbol_filename) (archive_bfd, abfd);
+
+  if (undefined_only)
+    {
+      if (bfd_is_und_section (bfd_get_section (sym)))
+       print_symname ("%s", bfd_asymbol_name (sym), abfd);
+    }
+  else
+    {
+      symbol_info syminfo;
+
+      bfd_get_symbol_info (abfd, sym, &syminfo);
+      (*format->print_symbol_info) (&syminfo, abfd);
+    }
+
+  if (line_numbers)
+    {
+      static asymbol **syms;
+      static long symcount;
+      const char *filename, *functionname;
+      unsigned int lineno;
+
+      /* We need to get the canonical symbols in order to call
+         bfd_find_nearest_line.  This is inefficient, but, then, you
+         don't have to use --line-numbers.  */
+      if (abfd != lineno_cache_bfd && syms != NULL)
+       {
+         free (syms);
+         syms = NULL;
+       }
+      if (syms == NULL)
+       {
+         long symsize;
+
+         symsize = bfd_get_symtab_upper_bound (abfd);
+         if (symsize < 0)
+           bfd_fatal (bfd_get_filename (abfd));
+         syms = (asymbol **) xmalloc (symsize);
+         symcount = bfd_canonicalize_symtab (abfd, syms);
+         if (symcount < 0)
+           bfd_fatal (bfd_get_filename (abfd));
+         lineno_cache_bfd = abfd;
+       }
+
+      if (bfd_is_und_section (bfd_get_section (sym)))
+       {
+         static asection **secs;
+         static arelent ***relocs;
+         static long *relcount;
+         static unsigned int seccount;
+         unsigned int i;
+         const char *symname;
+
+         /* For an undefined symbol, we try to find a reloc for the
+             symbol, and print the line number of the reloc.  */
+
+         if (abfd != lineno_cache_rel_bfd && relocs != NULL)
+           {
+             for (i = 0; i < seccount; i++)
+               if (relocs[i] != NULL)
+                 free (relocs[i]);
+             free (secs);
+             free (relocs);
+             free (relcount);
+             secs = NULL;
+             relocs = NULL;
+             relcount = NULL;
+           }
+
+         if (relocs == NULL)
+           {
+             struct get_relocs_info info;
+
+             seccount = bfd_count_sections (abfd);
+
+             secs = (asection **) xmalloc (seccount * sizeof *secs);
+             relocs = (arelent ***) xmalloc (seccount * sizeof *relocs);
+             relcount = (long *) xmalloc (seccount * sizeof *relcount);
+
+             info.secs = secs;
+             info.relocs = relocs;
+             info.relcount = relcount;
+             info.syms = syms;
+             bfd_map_over_sections (abfd, get_relocs, (PTR) &info);
+             lineno_cache_rel_bfd = abfd;
+           }
+
+         symname = bfd_asymbol_name (sym);
+         for (i = 0; i < seccount; i++)
+           {
+             long j;
+
+             for (j = 0; j < relcount[i]; j++)
+               {
+                 arelent *r;
+
+                 r = relocs[i][j];
+                 if (r->sym_ptr_ptr != NULL
+                     && (*r->sym_ptr_ptr)->section == sym->section
+                     && (*r->sym_ptr_ptr)->value == sym->value
+                     && strcmp (symname,
+                                bfd_asymbol_name (*r->sym_ptr_ptr)) == 0
+                     && bfd_find_nearest_line (abfd, secs[i], syms,
+                                               r->address, &filename,
+                                               &functionname, &lineno))
+                   {
+                     /* We only print the first one we find.  */
+                     printf ("\t%s:%u", filename, lineno);
+                     i = seccount;
+                     break;
+                   }
+               }
+           }
+       }
+      else if (bfd_get_section (sym)->owner == abfd)
+       {
+         if (bfd_find_nearest_line (abfd, bfd_get_section (sym), syms,
+                                    sym->value, &filename, &functionname,
+                                    &lineno)
+             && filename != NULL
+             && lineno != 0)
+           {
+             printf ("\t%s:%u", filename, lineno);
+           }
+       }
+    }
+
+  putchar ('\n');
+}
+\f
+/* The following 3 groups of functions are called unconditionally,
+   once at the start of processing each file of the appropriate type.
+   They should check `filename_per_file' and `filename_per_symbol',
+   as appropriate for their output format, to determine whether to
+   print anything.  */
+\f
+/* Print the name of an object file given on the command line.  */
+
+static void
+print_object_filename_bsd (filename)
+     char *filename;
+{
+  if (filename_per_file && !filename_per_symbol)
+    printf ("\n%s:\n", filename);
+}
+
+static void
+print_object_filename_sysv (filename)
+     char *filename;
+{
+  if (undefined_only)
+    printf (_("\n\nUndefined symbols from %s:\n\n"), filename);
+  else
+    printf (_("\n\nSymbols from %s:\n\n"), filename);
+  printf (_("\
+Name                  Value   Class        Type         Size   Line  Section\n\n"));
+}
+
+static void
+print_object_filename_posix (filename)
+     char *filename;
+{
+  if (filename_per_file && !filename_per_symbol)
+    printf ("%s:\n", filename);
+}
+\f
+/* Print the name of an archive file given on the command line.  */
+
+static void
+print_archive_filename_bsd (filename)
+     char *filename;
+{
+  if (filename_per_file)
+    printf ("\n%s:\n", filename);
+}
+
+static void
+print_archive_filename_sysv (filename)
+     char *filename;
+{
+}
+
+static void
+print_archive_filename_posix (filename)
+     char *filename;
+{
+}
+\f
+/* Print the name of an archive member file.  */
+
+static void
+print_archive_member_bsd (archive, filename)
+     char *archive;
+     CONST char *filename;
+{
+  if (!filename_per_symbol)
+    printf ("\n%s:\n", filename);
+}
+
+static void
+print_archive_member_sysv (archive, filename)
+     char *archive;
+     CONST char *filename;
+{
+  if (undefined_only)
+    printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename);
+  else
+    printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename);
+  printf (_("\
+Name                  Value   Class        Type         Size   Line  Section\n\n"));
+}
+
+static void
+print_archive_member_posix (archive, filename)
+     char *archive;
+     CONST char *filename;
+{
+  if (!filename_per_symbol)
+    printf ("%s[%s]:\n", archive, filename);
+}
+\f
+/* Print the name of the file (and archive, if there is one)
+   containing a symbol.  */
+
+static void
+print_symbol_filename_bsd (archive_bfd, abfd)
+     bfd *archive_bfd, *abfd;
+{
+  if (filename_per_symbol)
+    {
+      if (archive_bfd)
+       printf ("%s:", bfd_get_filename (archive_bfd));
+      printf ("%s:", bfd_get_filename (abfd));
+    }
+}
+
+static void
+print_symbol_filename_sysv (archive_bfd, abfd)
+     bfd *archive_bfd, *abfd;
+{
+  if (filename_per_symbol)
+    {
+      if (archive_bfd)
+       printf ("%s:", bfd_get_filename (archive_bfd));
+      printf ("%s:", bfd_get_filename (abfd));
+    }
+}
+
+static void
+print_symbol_filename_posix (archive_bfd, abfd)
+     bfd *archive_bfd, *abfd;
+{
+  if (filename_per_symbol)
+    {
+      if (archive_bfd)
+       printf ("%s[%s]: ", bfd_get_filename (archive_bfd),
+               bfd_get_filename (abfd));
+      else
+       printf ("%s: ", bfd_get_filename (abfd));
+    }
+}
+\f
+/* Print a symbol value.  */
+
+static void
+print_value (val)
+     bfd_vma val;
+{
+#if ! defined (BFD64) || BFD_HOST_64BIT_LONG
+  printf (value_format, val);
+#else
+  /* We have a 64 bit value to print, but the host is only 32 bit.  */
+  if (print_radix == 16)
+    fprintf_vma (stdout, val);
+  else
+    {
+      char buf[30];
+      char *s;
+
+      s = buf + sizeof buf;
+      *--s = '\0';
+      while (val > 0)
+       {
+         *--s = (val % print_radix) + '0';
+         val /= print_radix;
+       }
+      while ((buf + sizeof buf - 1) - s < 16)
+       *--s = '0';
+      printf ("%s", s);
+    }
+#endif
+}
+
+/* Print a line of information about a symbol.  */
+
+static void
+print_symbol_info_bsd (info, abfd)
+     symbol_info *info;
+     bfd *abfd;
+{
+  if (info->type == 'U')
+    {
+      printf ("%*s",
+#ifdef BFD64
+             16,
+#else
+             8,
+#endif
+             "");
+    }
+  else
+    print_value (info->value);
+  printf (" %c", info->type);
+  if (info->type == '-')
+    {
+      /* A stab.  */
+      printf (" ");
+      printf (other_format, info->stab_other);
+      printf (" ");
+      printf (desc_format, info->stab_desc);
+      printf (" %5s", info->stab_name);
+    }
+  print_symname (" %s", info->name, abfd);
+}
+
+static void
+print_symbol_info_sysv (info, abfd)
+     symbol_info *info;
+     bfd *abfd;
+{
+  print_symname ("%-20s|", info->name, abfd);  /* Name */
+  if (info->type == 'U')
+    printf ("        ");       /* Value */
+  else
+    print_value (info->value);
+  printf ("|   %c  |", info->type);    /* Class */
+  if (info->type == '-')
+    {
+      /* A stab.  */
+      printf ("%18s|  ", info->stab_name);     /* (C) Type */
+      printf (desc_format, info->stab_desc);   /* Size */
+      printf ("|     |");      /* Line, Section */
+    }
+  else
+    printf ("                  |      |     |");       /* Type, Size, Line, Section */
+}
+
+static void
+print_symbol_info_posix (info, abfd)
+     symbol_info *info;
+     bfd *abfd;
+{
+  print_symname ("%s ", info->name, abfd);
+  printf ("%c ", info->type);
+  if (info->type == 'U')
+    printf ("        ");
+  else
+    print_value (info->value);
+  /* POSIX.2 wants the symbol size printed here, when applicable;
+     BFD currently doesn't provide it, so we take the easy way out by
+     considering it to never be applicable.  */
+}
+\f
+static void
+print_symdef_entry (abfd)
+     bfd *abfd;
+{
+  symindex idx = BFD_NO_MORE_SYMBOLS;
+  carsym *thesym;
+  boolean everprinted = false;
+
+  for (idx = bfd_get_next_mapent (abfd, idx, &thesym);
+       idx != BFD_NO_MORE_SYMBOLS;
+       idx = bfd_get_next_mapent (abfd, idx, &thesym))
+    {
+      bfd *elt;
+      if (!everprinted)
+       {
+         printf (_("\nArchive index:\n"));
+         everprinted = true;
+       }
+      elt = bfd_get_elt_at_index (abfd, idx);
+      if (elt == NULL)
+       bfd_fatal ("bfd_get_elt_at_index");
+      if (thesym->name != (char *) NULL)
+       {
+         print_symname ("%s", thesym->name, abfd);
+         printf (" in %s\n", bfd_get_filename (elt));
+       }
+    }
+}
+\f
+/* This function is used to get the relocs for a particular section.
+   It is called via bfd_map_over_sections.  */
+
+static void
+get_relocs (abfd, sec, dataarg)
+     bfd *abfd;
+     asection *sec;
+     PTR dataarg;
+{
+  struct get_relocs_info *data = (struct get_relocs_info *) dataarg;
+
+  *data->secs = sec;
+
+  if ((sec->flags & SEC_RELOC) == 0)
+    {
+      *data->relocs = NULL;
+      *data->relcount = 0;
+    }
+  else
+    {
+      long relsize;
+
+      relsize = bfd_get_reloc_upper_bound (abfd, sec);
+      if (relsize < 0)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      *data->relocs = (arelent **) xmalloc (relsize);
+      *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs,
+                                               data->syms);
+      if (*data->relcount < 0)
+       bfd_fatal (bfd_get_filename (abfd));
+    }
+
+  ++data->secs;
+  ++data->relocs;
+  ++data->relcount;
+}
diff --git a/binutils/not-ranlib.c b/binutils/not-ranlib.c
new file mode 100644 (file)
index 0000000..afb9ceb
--- /dev/null
@@ -0,0 +1,3 @@
+/* Linked with ar.o to flag that this program is 'ar' (not 'ranlib'). */
+
+int is_ranlib = 0;
diff --git a/binutils/not-strip.c b/binutils/not-strip.c
new file mode 100644 (file)
index 0000000..98093ce
--- /dev/null
@@ -0,0 +1,4 @@
+/* Linked with objcopy.o to flag that this program is 'objcopy' (not
+   'strip'). */
+
+int is_strip = 0;
diff --git a/binutils/objcopy.1 b/binutils/objcopy.1
new file mode 100644 (file)
index 0000000..aee7760
--- /dev/null
@@ -0,0 +1,319 @@
+.\" Copyright (c) 1991, 93, 94, 95, 96, 97, 1998 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH objcopy 1 "October 1994" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+objcopy \- copy and translate object files
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B objcopy
+.RB "[\|" \-F\ \fIbfdname\fR\ |\ \fB\-\-target=\fIbfdname\fR "\|]" 
+.RB "[\|" \-I\ \fIbfdname\fR\ |\ \fB\-\-input\-target=\fIbfdname\fR "\|]" 
+.RB "[\|" \-O\ \fIbfdname\fR\ |\ \fB\-\-output\-target=\fIbfdname\fR "\|]" 
+.RB "[\|" \-R\ \fIsectionname\fR\ |\ \fB\-\-remove\-section=\fIsectionname\fR "\|]"
+.RB "[\|" \-S\fR\ |\ \fB\-\-strip\-all\fR "\|]" 
+.RB "[\|" \-g\fR\ |\ \fB\-\-strip\-debug\fR "\|]" 
+.RB "[\|" \-\-strip\-unneeded\fR "\|]" 
+.RB "[\|" \-K\ \fIsymbolname\fR\ |\ \fB\-\-keep\-symbol=\fIsymbolname\fR "\|]" 
+.RB "[\|" \-N\ \fIsymbolname\fR\ |\ \fB\-\-strip\-symbol=\fIsymbolname\fR "\|]" 
+.RB "[\|" \-L\ \fIsymbolname\fR\ |\ \fB\-\-localize\-symbol=\fIsymbolname\fR "\|]" 
+.RB "[\|" \-W\ \fIsymbolname\fR\ |\ \fB\-\-weaken\-symbol=\fIsymbolname\fR "\|]" 
+.RB "[\|" \-x\fR\ |\ \fB\-\-discard\-all\fR "\|]" 
+.RB "[\|" \-X\fR\ |\ \fB\-\-discard\-locals\fR "\|]" 
+.RB "[\|" \-b\ \fIbyte\fR\ |\ \fB\-\-byte=\fIbyte\fR "\|]" 
+.RB "[\|" \-i\ \fIinterleave\fR\ |\ \fB\-\-interleave=\fIinterleave\fR "\|]" 
+.RB "[\|" \-p\fR\ |\ \fB\-\-preserve\-dates\fR "\|]" 
+.RB "[\|" \-\-debugging "\|]"
+.RB "[\|" \-\-gap\-fill=\fIval\fR "\|]"
+.RB "[\|" \-\-pad\-to=\fIaddress\fR "\|]"
+.RB "[\|" \-\-set\-start=\fIval\fR "\|]"
+.RB "[\|" \-\-change\-start=\fIincr\fR "\|]"
+.RB "[\|" \-\-change\-addresses=\fIincr\fR "\|]"
+.RB "[\|" \-\-change\-section\-address=\fIsection{=,+,-}val\fR "\|]"
+.RB "[\|" \-\-change\-section\-lma=\fIsection{=,+,-}val\fR "\|]"
+.RB "[\|" \-\-change\-section\-vma=\fIsection{=,+,-}val\fR "\|]"
+.RB "[\|" \-\-change\-warnings\fR "\|]"
+.RB "[\|" \-\-no\-change\-warnings\fR "\|]"
+.RB "[\|" \-\-set\-section\-flags=\fIsection=flags\fR "\|]"
+.RB "[\|" \-\-add\-section=\fIsectionname=filename\fR "\|]"
+.RB "[\|" \-\-change\-leading\-char\fR "\|]"
+.RB "[\|" \-\-remove\-leading\-char\fR "\|]"
+.RB "[\|" \-\-weaken\fR "\|]"
+.RB "[\|" \-v\ |\ \-\-verbose\fR "\|]" 
+.RB "[\|" \-V\ |\ \-\-version\fR "\|]" 
+.RB "[\|" \-\-help\fR "\|]" 
+.B infile
+.RB "[\|" outfile\fR "\|]" 
+.SH DESCRIPTION
+The GNU 
+.B objcopy
+utility copies the contents of an object file to another.  
+.B objcopy 
+uses the GNU BFD Library to read and write the object files.  It can
+write the destination object file in a format different from that of
+the source object file.  The exact behavior of 
+.B objcopy
+is controlled by command-line options.
+.PP
+.B objcopy
+creates temporary files to do its translations and deletes them
+afterward.
+.B objcopy
+uses BFD to do all its translation work; it knows about all the
+formats BFD knows about, and thus is able to recognize most formats
+without being told explicitly.
+.PP
+.B objcopy
+can be used to generate S-records by using an output target of
+.B srec
+(e.g., use
+.B -O srec).
+.PP
+.B objcopy
+can be used to generate a raw binary file by using an output target of
+.B binary
+(e.g., use
+.B -O binary).
+When
+.B objcopy
+generates a raw binary file, it will essentially produce a memory dump
+of the contents of the input object file.  All symbols and relocation
+information will be discarded.  The memory dump will start at the
+virtual address of the lowest section copied into the output file.
+.PP
+When generating an S-record or a raw binary file, it may be helpful to
+use
+.B -S
+to remove sections containing debugging information.  In some cases
+.B -R
+will be useful to remove sections which contain information which is
+not needed by the binary file.
+.PP
+.I infile
+and
+.I outfile
+are the source and output files respectively.  If you do not specify
+.IR outfile ,
+.B objcopy
+creates a temporary file and destructively renames the result with the
+name of the input file.
+
+.SH OPTIONS
+.TP
+.B \-I \fIbfdname\fR, \fB\-\-input\-target=\fIbfdname
+Consider the source file's object format to be 
+.IR bfdname ,
+rather than attempting to deduce it.
+.TP
+.B \-O \fIbfdname\fR, \fB\-\-output\-target=\fIbfdname
+Write the output file using the object format 
+.IR bfdname .
+.TP
+.B \-F \fIbfdname\fR, \fB\-\-target=\fIbfdname
+Use 
+.I bfdname
+as the object format for both the input and the output file; i.e.
+simply transfer data from source to destination with no translation.
+.TP
+.B \-R \fIsectionname\fR, \fB\-\-remove-section=\fIsectionname
+Remove the named section from the file.  This option may be given more
+than once.  Note that using this option inappropriately may make the
+output file unusable.
+.TP
+.B \-S\fR, \fB\-\-strip\-all
+Do not copy relocation and symbol information from the source file.
+.TP
+.B \-g\fR, \fB\-\-strip\-debug
+Do not copy debugging symbols from the source file.
+.TP
+.B \-\-strip\-unneeded
+Strip all symbols that are not needed for relocation processing.
+.TP
+.B \-K \fIsymbolname\fR, \fB\-\-keep\-symbol=\fIsymbolname
+Copy only symbol \fIsymbolname\fP from the source file. This option
+may be given more than once.
+.TP
+.B \-N \fIsymbolname\fR, \fB\-\-strip\-symbol=\fIsymbolname
+Do not copy symbol \fIsymbolname\fP from the source file. This option
+may be given more than once.
+.TP
+.B \-L \fIsymbolname\fR, \fB\-\-localize\-symbol=\fIsymbolname
+Make symbol \fIsymbolname\fP local to the file, so that it is not
+visible externally.  This option may be given more than once.
+.TP
+.B \-W \fIsymbolname\fR, \fB\-\-weaken\-symbol=\fIsymbolname
+Make symbol \fIsymbolname\fP weak. This option may be given more than once.
+.TP
+.B \-x\fR, \fB \-\-discard\-all
+Do not copy non-global symbols from the source file.
+.TP
+.B \-X\fR, \fB\-\-discard\-locals
+Do not copy compiler-generated local symbols. (These usually start
+with "L" or ".").
+.TP
+.B \-b \fIbyte\fR, \fB\-\-byte=\fIbyte
+Keep only every \fIbyte\fPth byte of the input file (header data is
+not affected).  \fIbyte\fP can be in the range from 0 to the
+interleave-1.  This option is useful for creating files to program
+ROMs.  It is typically used with an srec output target.
+.TP
+.B \-i \fIinterleave\fR, \fB\-\-interleave=\fIinterleave
+Only copy one out of every \fIinterleave\fP bytes.  Which one to copy is
+selected by the \fB\-b\fP or \fB\-\-byte\fP option.  The default is 4.
+The interleave is ignored if neither \fB\-b\fP nor \fB\-\-byte\fP is given.
+.TP
+.B \-p\fR, \fB\-\-preserve\-dates
+Set the access and modification dates of the output file to be the same
+as those of the input file.
+.TP
+.B \-\-debugging
+Convert debugging information, if possible.  This is not the default
+because only certain debugging formats are supported, and the
+conversion process can be time consuming.
+.TP
+.B \-\-gap\-fill=\fIval
+Fill gaps between sections with \fIval\fP.  This operation applies to
+the \fIload address\fP (LMA) of the sections.  It is done by increasing
+the size of the section with the lower address, and filling in the extra
+space created with \fIval\fP.
+.TP
+.B \-\-pad\-to=\fIaddress
+Pad the output file up to the load address \fIaddress\fP.  This is
+done by increasing the size of the last section.  The extra space is
+filled in with the value specified by \fB\-\-gap\-fill\fP (default
+zero).
+.TP
+.B \fB\-\-set\-start=\fIval
+Set the start address of the new file to \fIval\fP.  Not all object
+file formats support setting the start address.
+.TP
+.B \fB\-\-change\-start=\fIincr\fR, \fB\-\-adjust\-start=\fIincr
+Changes the start address by adding \fIincr\fP.  Not all object file
+formats support setting the start address.
+.TP
+.B \fB\-\-change\-addresses=\fIincr\fR, \fB\-\-adjust\-vma=\fIincr
+Changes the address of all sections, as well as the start address, by
+adding \fIincr\fP.  Some object file formats do not permit section
+addresses to be changed arbitrarily.  Note that this does not relocate
+the sections; if the program expects sections to be loaded at a
+certain address, and this option is used to change the sections such
+that they are loaded at a different address, the program may fail.
+.TP
+.B \fB\-\-change\-section\-address=\fIsection{=,+,-}val\fR, \fB\-\-adjust\-section\-vma=\fIsection{=,+,-}val
+Set or changes the VMA and LMA addresses of the named \fIsection\fP.
+If \fI=\fP is used, the section address is set to \fIval\fP.
+Otherwise, \fIval\fP is added to or subtracted from the section
+address.  See the comments under \fB\-\-change\-addresses\fP, above.  If
+\fIsection\fP does not exist in the input file, a warning will be
+issued, unless \fB\-\-no\-change\-warnings\fP is used.
+.TP
+.B \fB\-\-change\-section\-lma=\fIsection{=,+,-}val
+Set or change the LMA address of the named \fIsection\fP.  If \fI=\fP is
+used, the section address is set to \fIval\fP.  Otherwise, \fIval\fP
+is added to or subtracted from the section address.  See the comments
+under \fB\-\-change\-addresses\fP, above.  If \fIsection\fP does not exist
+in the input file, a warning will be issued, unless
+\fB\-\-no\-change\-warnings\fP is used.
+.TP
+.B \fB\-\-change\-section\-vma=\fIsection{=,+,-}val
+Set or change the VMA address of the named \fIsection\fP.  If \fI=\fP is
+used, the section address is set to \fIval\fP.  Otherwise, \fIval\fP
+is added to or subtracted from the section address.  See the comments
+under \fB\-\-change\-addresses\fP, above.  If \fIsection\fP does not exist
+in the input file, a warning will be issued, unless
+\fB\-\-no\-change\-warnings\fP is used.
+.TP
+.B \fB\-\-change\-warnings\fR, \fB\-\-adjust\-warnings
+If \fB\-\-change\-section\-XXX\fP is used, and the named section does
+not exist, issue a warning.  This is the default.
+.TP
+.B \fB\-\-no\-change\-warnings\fR, \fB\-\-no\-adjust\-warnings
+Do not issue a warning if \fB\-\-change\-section\-XXX\fP is used, even
+if the named section does not exist.
+.TP
+.B \fB\-\-set\-section\-flags=\fIsection=flags
+Set the flags for the named section.  The \fIflags\fP argument is a
+comma separated string of flag names.  The recognized names are
+\fIalloc\fP, \fIload\fP, \fIreadonly\fP, \fIcode\fP, \fIdata\fP, and
+\fIrom\fP.  Not all flags are meaningful for all object file
+formats.
+.TP
+.B \fB\-\-add\-section=\fIsectionname=filename
+Add a new section named \fIsectionname\fR while copying the file.  The
+contents of the new section are taken from the file \fIfilename\fR.
+The size of the section will be the size of the file.  This option
+only works on file formats which can support sections with arbitrary
+names.
+.TP
+.B \-\-change\-leading\-char
+Some object file formats use special characters at the start of
+symbols.  The most common such character is underscore, which compilers
+often add before every symbol.  This option tells 
+.B objcopy
+to change the leading character of every symbol when it converts
+between object file formats.  If the object file formats use the same
+leading character, this option has no effect.  Otherwise, it will add
+a character, or remove a character, or change a character, as
+appropriate.
+.TP
+.B \-\-remove\-leading\-char
+If the first character of a global symbol is a special symbol leading
+character used by the object file format, remove the character.  The
+most common symbol leading character is underscore.  This option will
+remove a leading underscore from all global symbols.  This can be
+useful if you want to link together objects of different file formats
+with different conventions for symbol names.  This is different from
+\fB\-\-change\-leading\-char\fP because it always changes the symbol name
+when appropriate, regardless of the object file format of the output
+.TP
+.B \-\-weaken
+Change all global symbols in the file to be weak.
+.TP
+.B \-v\fR, \fB\-\-verbose
+Verbose output: list all object files modified.  In the case of
+archives, "\fBobjcopy \-V\fR" lists all members of the archive.
+.TP
+.B \-V\fR, \fB\-\-version
+Show the version number of
+.B objcopy
+and exit.
+.TP
+.B \-\-help
+Show a summary of the options to
+.B objcopy
+and exit.
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'" 
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (June 1993).
+
+.SH COPYING
+Copyright (c) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
new file mode 100644 (file)
index 0000000..5fd7777
--- /dev/null
@@ -0,0 +1,2029 @@
+/* objcopy.c -- copy object file from input to output, optionally massaging it.
+   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+\f
+#include "bfd.h"
+#include "progress.h"
+#include "bucomm.h"
+#include "getopt.h"
+#include "libiberty.h"
+#include "budbg.h"
+#include <sys/stat.h>
+
+/* A list of symbols to explicitly strip out, or to keep.  A linked
+   list is good enough for a small number from the command line, but
+   this will slow things down a lot if many symbols are being
+   deleted. */
+
+struct symlist
+{
+  const char *name;
+  struct symlist *next;
+};
+
+static void copy_usage PARAMS ((FILE *, int));
+static void strip_usage PARAMS ((FILE *, int));
+static flagword parse_flags PARAMS ((const char *));
+static struct section_list *find_section_list PARAMS ((const char *, boolean));
+static void setup_section PARAMS ((bfd *, asection *, PTR));
+static void copy_section PARAMS ((bfd *, asection *, PTR));
+static void get_sections PARAMS ((bfd *, asection *, PTR));
+static int compare_section_lma PARAMS ((const PTR, const PTR));
+static void add_specific_symbol PARAMS ((const char *, struct symlist **));
+static boolean is_specified_symbol PARAMS ((const char *, struct symlist *));
+static boolean is_strip_section PARAMS ((bfd *, asection *));
+static unsigned int filter_symbols
+  PARAMS ((bfd *, bfd *, asymbol **, asymbol **, long));
+static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR));
+static void filter_bytes PARAMS ((char *, bfd_size_type *));
+static boolean write_debugging_info PARAMS ((bfd *, PTR, long *, asymbol ***));
+static void copy_object PARAMS ((bfd *, bfd *));
+static void copy_archive PARAMS ((bfd *, bfd *, const char *));
+static void copy_file
+  PARAMS ((const char *, const char *, const char *, const char *));
+static int strip_main PARAMS ((int, char **));
+static int copy_main PARAMS ((int, char **));
+
+#define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;}
+
+static asymbol **isympp = NULL;        /* Input symbols */
+static asymbol **osympp = NULL;        /* Output symbols that survive stripping */
+
+/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes.  */
+static int copy_byte = -1;
+static int interleave = 4;
+
+static boolean verbose;                /* Print file and target names. */
+static boolean preserve_dates; /* Preserve input file timestamp.  */
+static int status = 0;         /* Exit status.  */
+
+enum strip_action
+  {
+    STRIP_UNDEF,
+    STRIP_NONE,                        /* don't strip */
+    STRIP_DEBUG,               /* strip all debugger symbols */
+    STRIP_UNNEEDED,            /* strip unnecessary symbols */
+    STRIP_ALL                  /* strip all symbols */
+  };
+
+/* Which symbols to remove. */
+static enum strip_action strip_symbols;
+
+enum locals_action
+  {
+    LOCALS_UNDEF,
+    LOCALS_START_L,            /* discard locals starting with L */
+    LOCALS_ALL                 /* discard all locals */
+  };
+
+/* Which local symbols to remove.  Overrides STRIP_ALL.  */
+static enum locals_action discard_locals;
+
+/* What kind of change to perform.  */
+enum change_action
+{
+  CHANGE_IGNORE,
+  CHANGE_MODIFY,
+  CHANGE_SET
+};
+
+/* Structure used to hold lists of sections and actions to take.  */
+struct section_list
+{
+  struct section_list * next;      /* Next section to change.  */
+  const char *          name;      /* Section name.  */
+  boolean               used;      /* Whether this entry was used.  */
+  boolean               remove;    /* Whether to remove this section.  */
+  enum change_action    change_vma;/* Whether to change or set VMA.  */
+  bfd_vma              vma_val;   /* Amount to change by or set to.  */
+  enum change_action    change_lma;/* Whether to change or set LMA.  */
+  bfd_vma              lma_val;   /* Amount to change by or set to.  */
+  boolean              set_flags; /* Whether to set the section flags.  */
+  flagword             flags;     /* What to set the section flags to.  */
+};
+
+static struct section_list *change_sections;
+static boolean sections_removed;
+
+/* Changes to the start address.  */
+static bfd_vma change_start = 0;
+static boolean set_start_set = false;
+static bfd_vma set_start;
+
+/* Changes to section addresses.  */
+static bfd_vma change_section_address = 0;
+
+/* Filling gaps between sections.  */
+static boolean gap_fill_set = false;
+static bfd_byte gap_fill = 0;
+
+/* Pad to a given address.  */
+static boolean pad_to_set = false;
+static bfd_vma pad_to;
+
+/* List of sections to add.  */
+
+struct section_add
+{
+  /* Next section to add.  */
+  struct section_add *next;
+  /* Name of section to add.  */
+  const char *name;
+  /* Name of file holding section contents.  */
+  const char *filename;
+  /* Size of file.  */
+  size_t size;
+  /* Contents of file.  */
+  bfd_byte *contents;
+  /* BFD section, after it has been added.  */
+  asection *section;
+};
+
+static struct section_add *add_sections;
+
+/* Whether to convert debugging information.  */
+
+static boolean convert_debugging = false;
+
+/* Whether to change the leading character in symbol names.  */
+
+static boolean change_leading_char = false;
+
+/* Whether to remove the leading character from global symbol names.  */
+
+static boolean remove_leading_char = false;
+
+/* List of symbols to strip, keep, localize, and weaken.  */
+
+static struct symlist *strip_specific_list = NULL;
+static struct symlist *keep_specific_list = NULL;
+static struct symlist *localize_specific_list = NULL;
+static struct symlist *weaken_specific_list = NULL;
+
+/* If this is true, we weaken global symbols (set BSF_WEAK).  */
+
+static boolean weaken = false;
+
+/* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
+
+#define OPTION_ADD_SECTION 150
+#define OPTION_CHANGE_ADDRESSES (OPTION_ADD_SECTION + 1)
+#define OPTION_CHANGE_LEADING_CHAR (OPTION_CHANGE_ADDRESSES + 1)
+#define OPTION_CHANGE_START (OPTION_CHANGE_LEADING_CHAR + 1)
+#define OPTION_CHANGE_SECTION_ADDRESS (OPTION_CHANGE_START + 1)
+#define OPTION_CHANGE_SECTION_LMA (OPTION_CHANGE_SECTION_ADDRESS + 1)
+#define OPTION_CHANGE_SECTION_VMA (OPTION_CHANGE_SECTION_LMA + 1)
+#define OPTION_CHANGE_WARNINGS (OPTION_CHANGE_SECTION_VMA + 1)
+#define OPTION_DEBUGGING (OPTION_CHANGE_WARNINGS + 1)
+#define OPTION_GAP_FILL (OPTION_DEBUGGING + 1)
+#define OPTION_NO_CHANGE_WARNINGS (OPTION_GAP_FILL + 1)
+#define OPTION_PAD_TO (OPTION_NO_CHANGE_WARNINGS + 1)
+#define OPTION_REMOVE_LEADING_CHAR (OPTION_PAD_TO + 1)
+#define OPTION_SET_SECTION_FLAGS (OPTION_REMOVE_LEADING_CHAR + 1)
+#define OPTION_SET_START (OPTION_SET_SECTION_FLAGS + 1)
+#define OPTION_STRIP_UNNEEDED (OPTION_SET_START + 1)
+#define OPTION_WEAKEN (OPTION_STRIP_UNNEEDED + 1)
+
+/* Options to handle if running as "strip".  */
+
+static struct option strip_options[] =
+{
+  {"discard-all", no_argument, 0, 'x'},
+  {"discard-locals", no_argument, 0, 'X'},
+  {"format", required_argument, 0, 'F'}, /* Obsolete */
+  {"help", no_argument, 0, 'h'},
+  {"input-format", required_argument, 0, 'I'}, /* Obsolete */
+  {"input-target", required_argument, 0, 'I'},
+  {"keep-symbol", required_argument, 0, 'K'},
+  {"output-format", required_argument, 0, 'O'},        /* Obsolete */
+  {"output-target", required_argument, 0, 'O'},
+  {"preserve-dates", no_argument, 0, 'p'},
+  {"remove-section", required_argument, 0, 'R'},
+  {"strip-all", no_argument, 0, 's'},
+  {"strip-debug", no_argument, 0, 'S'},
+  {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
+  {"strip-symbol", required_argument, 0, 'N'},
+  {"target", required_argument, 0, 'F'},
+  {"verbose", no_argument, 0, 'v'},
+  {"version", no_argument, 0, 'V'},
+  {0, no_argument, 0, 0}
+};
+
+/* Options to handle if running as "objcopy".  */
+
+static struct option copy_options[] =
+{
+  {"add-section", required_argument, 0, OPTION_ADD_SECTION},
+  {"adjust-start", required_argument, 0, OPTION_CHANGE_START},
+  {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES},
+  {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
+  {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
+  {"byte", required_argument, 0, 'b'},
+  {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES},
+  {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR},
+  {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
+  {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA},
+  {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA},
+  {"change-start", required_argument, 0, OPTION_CHANGE_START},
+  {"change-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
+  {"debugging", no_argument, 0, OPTION_DEBUGGING},
+  {"discard-all", no_argument, 0, 'x'},
+  {"discard-locals", no_argument, 0, 'X'},
+  {"format", required_argument, 0, 'F'}, /* Obsolete */
+  {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
+  {"help", no_argument, 0, 'h'},
+  {"input-format", required_argument, 0, 'I'}, /* Obsolete */
+  {"input-target", required_argument, 0, 'I'},
+  {"interleave", required_argument, 0, 'i'},
+  {"keep-symbol", required_argument, 0, 'K'},
+  {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
+  {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
+  {"output-format", required_argument, 0, 'O'},        /* Obsolete */
+  {"output-target", required_argument, 0, 'O'},
+  {"pad-to", required_argument, 0, OPTION_PAD_TO},
+  {"preserve-dates", no_argument, 0, 'p'},
+  {"localize-symbol", required_argument, 0, 'L'},
+  {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
+  {"remove-section", required_argument, 0, 'R'},
+  {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
+  {"set-start", required_argument, 0, OPTION_SET_START},
+  {"strip-all", no_argument, 0, 'S'},
+  {"strip-debug", no_argument, 0, 'g'},
+  {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
+  {"strip-symbol", required_argument, 0, 'N'},
+  {"target", required_argument, 0, 'F'},
+  {"verbose", no_argument, 0, 'v'},
+  {"version", no_argument, 0, 'V'},
+  {"weaken", no_argument, 0, OPTION_WEAKEN},
+  {"weaken-symbol", required_argument, 0, 'W'},
+  {0, no_argument, 0, 0}
+};
+
+/* IMPORTS */
+extern char *program_name;
+
+/* This flag distinguishes between strip and objcopy:
+   1 means this is 'strip'; 0 means this is 'objcopy'.
+   -1 means if we should use argv[0] to decide. */
+extern int is_strip;
+
+
+static void
+copy_usage (stream, exit_status)
+     FILE *stream;
+     int exit_status;
+{
+  fprintf (stream, _("\
+Usage: %s [-vVSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
+       [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\
+       [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
+       [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\
+       [--discard-locals] [--debugging] [--remove-section=section]\n"),
+          program_name);
+  fprintf (stream, _("\
+       [--gap-fill=val] [--pad-to=address] [--preserve-dates]\n\
+       [--set-start=val] \n\
+       [--change-start=incr] [--change-addresses=incr] \n\
+       (--adjust-start   and  --adjust-vma are aliases for these two) \n\
+       [--change-section-address=section{=,+,-}val]\n\
+       (--adjust-section-vma is an alias for --change-section-address)\n\
+       [--change-section-lma=section{=,+,-}val]\n\
+       [--change-section-vma=section{=,+,-}val]\n\
+       [--adjust-warnings] [--no-adjust-warnings]\n\
+       [--change-warnings] [--no-change-warnings]\n\
+       [--set-section-flags=section=flags] [--add-section=sectionname=filename]\n\
+       [--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N symbol]\n\
+       [--localize-symbol symbol] [-L symbol] [--weaken-symbol symbol]\n\
+       [-W symbol] [--change-leading-char] [--remove-leading-char] [--weaken]\n\
+       [--verbose] [--version] [--help] in-file [out-file]\n"));
+  list_supported_targets (program_name, stream);
+  if (exit_status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (exit_status);
+}
+
+static void
+strip_usage (stream, exit_status)
+     FILE *stream;
+     int exit_status;
+{
+  fprintf (stream, _("\
+Usage: %s [-vVsSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\
+       [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
+       [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\
+       [--discard-locals] [--keep-symbol symbol] [-K symbol]\n\
+       [--strip-symbol symbol] [-N symbol] [--remove-section=section]\n\
+       [-o file] [--preserve-dates] [--verbose] [--version] [--help] file...\n"),
+          program_name);
+  list_supported_targets (program_name, stream);
+  if (exit_status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (exit_status);
+}
+
+/* Parse section flags into a flagword, with a fatal error if the
+   string can't be parsed.  */
+
+static flagword
+parse_flags (s)
+     const char *s;
+{
+  flagword ret;
+  const char *snext;
+  int len;
+
+  ret = SEC_NO_FLAGS;
+
+  do
+    {
+      snext = strchr (s, ',');
+      if (snext == NULL)
+       len = strlen (s);
+      else
+       {
+         len = snext - s;
+         ++snext;
+       }
+
+      if (0) ;
+#define PARSE_FLAG(fname,fval) \
+  else if (strncasecmp (fname, s, len) == 0) ret |= fval
+      PARSE_FLAG ("alloc", SEC_ALLOC);
+      PARSE_FLAG ("load", SEC_LOAD);
+      PARSE_FLAG ("readonly", SEC_READONLY);
+      PARSE_FLAG ("code", SEC_CODE);
+      PARSE_FLAG ("data", SEC_DATA);
+      PARSE_FLAG ("rom", SEC_ROM);
+      PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
+#undef PARSE_FLAG
+      else
+       {
+         char *copy;
+
+         copy = xmalloc (len + 1);
+         strncpy (copy, s, len);
+         copy[len] = '\0';
+         non_fatal (_("unrecognized section flag `%s'"), copy);
+         fatal (_("supported flags: alloc, load, readonly, code, data, rom, contents"));
+       }
+
+      s = snext;
+    }
+  while (s != NULL);
+
+  return ret;
+}
+
+/* Find and optionally add an entry in the change_sections list.  */
+
+static struct section_list *
+find_section_list (name, add)
+     const char *name;
+     boolean add;
+{
+  register struct section_list *p;
+
+  for (p = change_sections; p != NULL; p = p->next)
+    if (strcmp (p->name, name) == 0)
+      return p;
+
+  if (! add)
+    return NULL;
+
+  p = (struct section_list *) xmalloc (sizeof (struct section_list));
+  p->name = name;
+  p->used = false;
+  p->remove = false;
+  p->change_vma = CHANGE_IGNORE;
+  p->change_lma = CHANGE_IGNORE;
+  p->vma_val = 0;
+  p->lma_val = 0;
+  p->set_flags = false;
+  p->flags = 0;
+
+  p->next = change_sections;
+  change_sections = p;
+
+  return p;
+}
+
+/* Add a symbol to strip_specific_list.  */
+
+static void 
+add_specific_symbol (name, list)
+     const char *name;
+     struct symlist **list;
+{
+  struct symlist *tmp_list;
+
+  tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist));
+  tmp_list->name = name;
+  tmp_list->next = *list;
+  *list = tmp_list;
+}
+
+/* See whether a symbol should be stripped or kept based on
+   strip_specific_list and keep_symbols.  */
+
+static boolean
+is_specified_symbol (name, list)
+     const char *name;
+     struct symlist *list;
+{
+  struct symlist *tmp_list;
+
+  for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
+    {
+      if (strcmp (name, tmp_list->name) == 0)
+       return true;
+    }
+  return false;
+}
+
+/* See if a section is being removed.  */
+
+static boolean
+is_strip_section (abfd, sec)
+     bfd *abfd;
+     asection *sec;
+{
+  struct section_list *p;
+
+  if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0
+      && (strip_symbols == STRIP_DEBUG
+         || strip_symbols == STRIP_UNNEEDED
+         || strip_symbols == STRIP_ALL
+         || discard_locals == LOCALS_ALL
+         || convert_debugging))
+    return true;
+
+  if (! sections_removed)
+    return false;
+  p = find_section_list (bfd_get_section_name (abfd, sec), false);
+  return p != NULL && p->remove ? true : false;
+}
+
+/* Choose which symbol entries to copy; put the result in OSYMS.
+   We don't copy in place, because that confuses the relocs.
+   Return the number of symbols to print.  */
+
+static unsigned int
+filter_symbols (abfd, obfd, osyms, isyms, symcount)
+     bfd *abfd;
+     bfd *obfd;
+     asymbol **osyms, **isyms;
+     long symcount;
+{
+  register asymbol **from = isyms, **to = osyms;
+  long src_count = 0, dst_count = 0;
+
+  for (; src_count < symcount; src_count++)
+    {
+      asymbol *sym = from[src_count];
+      flagword flags = sym->flags;
+      const char *name = bfd_asymbol_name (sym);
+      int keep;
+
+      if (change_leading_char
+         && (bfd_get_symbol_leading_char (abfd)
+             != bfd_get_symbol_leading_char (obfd))
+         && (bfd_get_symbol_leading_char (abfd) == '\0'
+             || (name[0] == bfd_get_symbol_leading_char (abfd))))
+       {
+         if (bfd_get_symbol_leading_char (obfd) == '\0')
+           name = bfd_asymbol_name (sym) = name + 1;
+         else
+           {
+             char *n;
+
+             n = xmalloc (strlen (name) + 2);
+             n[0] = bfd_get_symbol_leading_char (obfd);
+             if (bfd_get_symbol_leading_char (abfd) == '\0')
+               strcpy (n + 1, name);
+             else
+               strcpy (n + 1, name + 1);
+             name = bfd_asymbol_name (sym) = n;
+           }
+       }
+
+      if (remove_leading_char
+         && ((flags & BSF_GLOBAL) != 0
+             || (flags & BSF_WEAK) != 0
+             || bfd_is_und_section (bfd_get_section (sym))
+             || bfd_is_com_section (bfd_get_section (sym)))
+         && name[0] == bfd_get_symbol_leading_char (abfd))
+       name = bfd_asymbol_name (sym) = name + 1;
+
+      if (strip_symbols == STRIP_ALL)
+       keep = 0;
+      else if ((flags & BSF_KEEP) != 0         /* Used in relocation.  */
+              || ((flags & BSF_SECTION_SYM) != 0
+                  && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags
+                      & BSF_KEEP) != 0))
+       keep = 1;
+      else if ((flags & BSF_GLOBAL) != 0       /* Global symbol.  */
+              || (flags & BSF_WEAK) != 0
+              || bfd_is_und_section (bfd_get_section (sym))
+              || bfd_is_com_section (bfd_get_section (sym)))
+       keep = strip_symbols != STRIP_UNNEEDED;
+      else if ((flags & BSF_DEBUGGING) != 0)   /* Debugging symbol.  */
+       keep = (strip_symbols != STRIP_DEBUG
+               && strip_symbols != STRIP_UNNEEDED
+               && ! convert_debugging);
+      else                     /* Local symbol.  */
+       keep = (strip_symbols != STRIP_UNNEEDED
+               && (discard_locals != LOCALS_ALL
+                   && (discard_locals != LOCALS_START_L
+                       || ! bfd_is_local_label (abfd, sym))));
+
+      if (keep && is_specified_symbol (name, strip_specific_list))
+       keep = 0;
+      if (!keep && is_specified_symbol (name, keep_specific_list))
+       keep = 1;
+      if (keep && is_strip_section (abfd, bfd_get_section (sym)))
+       keep = 0;
+
+      if (keep && (flags & BSF_GLOBAL) != 0
+         && (weaken || is_specified_symbol (name, weaken_specific_list)))
+       {
+         sym->flags &=~ BSF_GLOBAL;
+         sym->flags |= BSF_WEAK;
+       }
+      if (keep && (flags & (BSF_GLOBAL | BSF_WEAK))
+         && is_specified_symbol (name, localize_specific_list))
+       {
+         sym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
+         sym->flags |= BSF_LOCAL;
+       }
+
+      if (keep)
+       to[dst_count++] = sym;
+    }
+
+  to[dst_count] = NULL;
+
+  return dst_count;
+}
+
+/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
+   Adjust *SIZE.  */
+
+static void
+filter_bytes (memhunk, size)
+     char *memhunk;
+     bfd_size_type *size;
+{
+  char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
+
+  for (; from < end; from += interleave)
+    *to++ = *from;
+  if (*size % interleave > copy_byte)
+    *size = (*size / interleave) + 1;
+  else
+    *size /= interleave;
+}
+
+/* Copy object file IBFD onto OBFD.  */
+
+static void
+copy_object (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  bfd_vma start;
+  long symcount;
+  asection **osections = NULL;
+  bfd_size_type *gaps = NULL;
+  bfd_size_type max_gap = 0;
+  long symsize;
+  PTR dhandle;
+
+
+  if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
+    RETURN_NONFATAL (bfd_get_filename (obfd));
+
+  if (verbose)
+    printf (_("copy from %s(%s) to %s(%s)\n"),
+           bfd_get_filename (ibfd), bfd_get_target (ibfd),
+           bfd_get_filename (obfd), bfd_get_target (obfd));
+
+  if (set_start_set)
+    start = set_start;
+  else
+    start = bfd_get_start_address (ibfd);
+  start += change_start;
+
+  if (!bfd_set_start_address (obfd, start)
+      || !bfd_set_file_flags (obfd,
+                             (bfd_get_file_flags (ibfd)
+                              & bfd_applicable_file_flags (obfd))))
+    RETURN_NONFATAL (bfd_get_filename (ibfd));
+
+  /* Copy architecture of input file to output file */
+  if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
+                         bfd_get_mach (ibfd)))
+    non_fatal (_("Warning: Output file cannot represent architecture %s"),
+              bfd_printable_arch_mach (bfd_get_arch (ibfd),
+                                       bfd_get_mach (ibfd)));
+  
+  if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
+    RETURN_NONFATAL (bfd_get_filename (ibfd));
+
+  if (isympp)
+    free (isympp);
+  
+  if (osympp != isympp)
+    free (osympp);
+
+  /* BFD mandates that all output sections be created and sizes set before
+     any output is done.  Thus, we traverse all sections multiple times.  */
+  bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
+
+  if (add_sections != NULL)
+    {
+      struct section_add *padd;
+      struct section_list *pset;
+
+      for (padd = add_sections; padd != NULL; padd = padd->next)
+       {
+         padd->section = bfd_make_section (obfd, padd->name);
+         if (padd->section == NULL)
+           {
+             non_fatal (_("can't create section `%s': %s"),
+                      padd->name, bfd_errmsg (bfd_get_error ()));
+             status = 1;
+             return;
+           }
+         else
+           {
+             flagword flags;
+             
+             if (! bfd_set_section_size (obfd, padd->section, padd->size))
+               RETURN_NONFATAL (bfd_get_filename (obfd));
+
+             pset = find_section_list (padd->name, false);
+             if (pset != NULL)
+               pset->used = true;
+
+             if (pset != NULL && pset->set_flags)
+               flags = pset->flags | SEC_HAS_CONTENTS;
+             else
+               flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
+             
+             if (! bfd_set_section_flags (obfd, padd->section, flags))
+               RETURN_NONFATAL (bfd_get_filename (obfd));
+
+             if (pset != NULL)
+               {
+                 if (pset->change_vma != CHANGE_IGNORE)
+                   if (! bfd_set_section_vma (obfd, padd->section, pset->vma_val))
+                     RETURN_NONFATAL (bfd_get_filename (obfd));
+                 
+                 if (pset->change_lma != CHANGE_IGNORE)
+                   {
+                     padd->section->lma = pset->lma_val;
+                     
+                     if (! bfd_set_section_alignment
+                         (obfd, padd->section,
+                          bfd_section_alignment (obfd, padd->section)))
+                       RETURN_NONFATAL (bfd_get_filename (obfd));
+                   }
+               }
+           }
+       }
+    }
+
+  if (gap_fill_set || pad_to_set)
+    {
+      asection **set;
+      unsigned int c, i;
+
+      /* We must fill in gaps between the sections and/or we must pad
+        the last section to a specified address.  We do this by
+        grabbing a list of the sections, sorting them by VMA, and
+        increasing the section sizes as required to fill the gaps.
+        We write out the gap contents below.  */
+
+      c = bfd_count_sections (obfd);
+      osections = (asection **) xmalloc (c * sizeof (asection *));
+      set = osections;
+      bfd_map_over_sections (obfd, get_sections, (void *) &set);
+
+      qsort (osections, c, sizeof (asection *), compare_section_lma);
+
+      gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
+      memset (gaps, 0, c * sizeof (bfd_size_type));
+
+      if (gap_fill_set)
+       {
+         for (i = 0; i < c - 1; i++)
+           {
+             flagword flags;
+             bfd_size_type size;
+             bfd_vma gap_start, gap_stop;
+
+             flags = bfd_get_section_flags (obfd, osections[i]);
+             if ((flags & SEC_HAS_CONTENTS) == 0
+                 || (flags & SEC_LOAD) == 0)
+               continue;
+
+             size = bfd_section_size (obfd, osections[i]);
+             gap_start = bfd_section_lma (obfd, osections[i]) + size;
+             gap_stop = bfd_section_lma (obfd, osections[i + 1]);
+             if (gap_start < gap_stop)
+               {
+                 if (! bfd_set_section_size (obfd, osections[i],
+                                             size + (gap_stop - gap_start)))
+                   {
+                     non_fatal (_("Can't fill gap after %s: %s"),
+                              bfd_get_section_name (obfd, osections[i]),
+                              bfd_errmsg (bfd_get_error ()));
+                     status = 1;
+                     break;
+                   }
+                 gaps[i] = gap_stop - gap_start;
+                 if (max_gap < gap_stop - gap_start)
+                   max_gap = gap_stop - gap_start;
+               }
+           }
+       }
+
+      if (pad_to_set)
+       {
+         bfd_vma lma;
+         bfd_size_type size;
+
+         lma = bfd_section_lma (obfd, osections[c - 1]);
+         size = bfd_section_size (obfd, osections[c - 1]);
+         if (lma + size < pad_to)
+           {
+             if (! bfd_set_section_size (obfd, osections[c - 1],
+                                         pad_to - lma))
+               {
+                 non_fatal (_("Can't add padding to %s: %s"),
+                          bfd_get_section_name (obfd, osections[c - 1]),
+                          bfd_errmsg (bfd_get_error ()));
+                 status = 1;
+               }
+             else
+               {
+                 gaps[c - 1] = pad_to - (lma + size);
+                 if (max_gap < pad_to - (lma + size))
+                   max_gap = pad_to - (lma + size);
+               }
+           }
+       }
+    }
+
+  /* Symbol filtering must happen after the output sections have
+     been created, but before their contents are set.  */
+  dhandle = NULL;
+  symsize = bfd_get_symtab_upper_bound (ibfd);
+  if (symsize < 0)
+    RETURN_NONFATAL (bfd_get_filename (ibfd));
+  
+  osympp = isympp = (asymbol **) xmalloc (symsize);
+  symcount = bfd_canonicalize_symtab (ibfd, isympp);
+  if (symcount < 0)
+    RETURN_NONFATAL (bfd_get_filename (ibfd));
+  
+  if (convert_debugging)
+    dhandle = read_debugging_info (ibfd, isympp, symcount);
+  
+  if (strip_symbols == STRIP_DEBUG 
+      || strip_symbols == STRIP_ALL
+      || strip_symbols == STRIP_UNNEEDED
+      || discard_locals != LOCALS_UNDEF
+      || strip_specific_list != NULL
+      || keep_specific_list != NULL
+      || localize_specific_list != NULL
+      || weaken_specific_list != NULL
+      || sections_removed
+      || convert_debugging
+      || change_leading_char
+      || remove_leading_char
+      || weaken)
+    {
+      /* Mark symbols used in output relocations so that they
+        are kept, even if they are local labels or static symbols.
+        
+        Note we iterate over the input sections examining their
+        relocations since the relocations for the output sections
+        haven't been set yet.  mark_symbols_used_in_relocations will
+        ignore input sections which have no corresponding output
+        section.  */
+      if (strip_symbols != STRIP_ALL)
+       bfd_map_over_sections (ibfd,
+                              mark_symbols_used_in_relocations,
+                              (PTR)isympp);
+      osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
+      symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
+    }
+
+  if (convert_debugging && dhandle != NULL)
+    {
+      if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
+       {
+         status = 1;
+         return;
+       }
+    }
+
+  bfd_set_symtab (obfd, osympp, symcount);
+
+  /* This has to happen after the symbol table has been set.  */
+  bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
+
+  if (add_sections != NULL)
+    {
+      struct section_add *padd;
+
+      for (padd = add_sections; padd != NULL; padd = padd->next)
+       {
+         if (! bfd_set_section_contents (obfd, padd->section,
+                                         (PTR) padd->contents,
+                                         (file_ptr) 0,
+                                         (bfd_size_type) padd->size))
+           RETURN_NONFATAL (bfd_get_filename (obfd));
+       }
+    }
+
+  if (gap_fill_set || pad_to_set)
+    {
+      bfd_byte *buf;
+      int c, i;
+
+      /* Fill in the gaps.  */
+
+      if (max_gap > 8192)
+       max_gap = 8192;
+      buf = (bfd_byte *) xmalloc (max_gap);
+      memset (buf, gap_fill, (size_t) max_gap);
+
+      c = bfd_count_sections (obfd);
+      for (i = 0; i < c; i++)
+       {
+         if (gaps[i] != 0)
+           {
+             bfd_size_type left;
+             file_ptr off;
+
+             left = gaps[i];
+             off = bfd_section_size (obfd, osections[i]) - left;
+             while (left > 0)
+               {
+                 bfd_size_type now;
+
+                 if (left > 8192)
+                   now = 8192;
+                 else
+                   now = left;
+
+                 if (! bfd_set_section_contents (obfd, osections[i], buf,
+                                                 off, now))
+                   RETURN_NONFATAL (bfd_get_filename (obfd));
+
+                 left -= now;
+                 off += now;
+               }
+           }
+       }
+    }
+
+  /* Allow the BFD backend to copy any private data it understands
+     from the input BFD to the output BFD.  This is done last to
+     permit the routine to look at the filtered symbol table, which is
+     important for the ECOFF code at least.  */
+  if (!bfd_copy_private_bfd_data (ibfd, obfd))
+    {
+      non_fatal (_("%s: error copying private BFD data: %s"),
+                bfd_get_filename (obfd),
+                bfd_errmsg (bfd_get_error ()));
+      status = 1;
+      return;
+    }
+}
+
+/* Read each archive element in turn from IBFD, copy the
+   contents to temp file, and keep the temp file handle.  */
+
+static void
+copy_archive (ibfd, obfd, output_target)
+     bfd *ibfd;
+     bfd *obfd;
+     const char *output_target;
+{
+  struct name_list
+    {
+      struct name_list *next;
+      char *name;
+      bfd *obfd;
+    } *list, *l;
+  bfd **ptr = &obfd->archive_head;
+  bfd *this_element;
+  char *dir = make_tempname (bfd_get_filename (obfd));
+
+  /* Make a temp directory to hold the contents.  */
+#if defined (_WIN32) && !defined (__CYGWIN32__)
+  if (mkdir (dir) != 0)
+#else
+  if (mkdir (dir, 0700) != 0)
+#endif
+    {
+      fatal (_("cannot mkdir %s for archive copying (error: %s)"),
+            dir, strerror (errno));
+    }
+  obfd->has_armap = ibfd->has_armap;
+
+  list = NULL;
+
+  this_element = bfd_openr_next_archived_file (ibfd, NULL);
+  while (!status && this_element != (bfd *) NULL)
+    {
+      /* Create an output file for this member.  */
+      char *output_name = concat (dir, "/", bfd_get_filename (this_element),
+                                 (char *) NULL);
+      bfd *output_bfd = bfd_openw (output_name, output_target);
+      bfd *last_element;
+
+      l = (struct name_list *) xmalloc (sizeof (struct name_list));
+      l->name = output_name;
+      l->next = list;
+      list = l;
+
+      if (output_bfd == (bfd *) NULL)
+       RETURN_NONFATAL (output_name);
+
+      if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
+       RETURN_NONFATAL (bfd_get_filename (obfd));
+
+      if (bfd_check_format (this_element, bfd_object) == true)
+       copy_object (this_element, output_bfd);
+
+      if (!bfd_close (output_bfd))
+       {
+         bfd_nonfatal (bfd_get_filename (output_bfd));
+         /* Error in new object file. Don't change archive. */
+         status = 1;
+       }
+
+      /* Open the newly output file and attach to our list.  */
+      output_bfd = bfd_openr (output_name, output_target);
+
+      l->obfd = output_bfd;
+
+      *ptr = output_bfd;
+      ptr = &output_bfd->next;
+
+      last_element = this_element;
+
+      this_element = bfd_openr_next_archived_file (ibfd, last_element);
+
+      bfd_close (last_element);
+    }
+  *ptr = (bfd *) NULL;
+
+  if (!bfd_close (obfd))
+    RETURN_NONFATAL (bfd_get_filename (obfd));
+
+  if (!bfd_close (ibfd))
+    RETURN_NONFATAL (bfd_get_filename (ibfd));
+
+  /* Delete all the files that we opened.  */
+  for (l = list; l != NULL; l = l->next)
+    {
+      bfd_close (l->obfd);
+      unlink (l->name);
+    }
+  rmdir (dir);
+}
+
+/* The top-level control.  */
+
+static void
+copy_file (input_filename, output_filename, input_target, output_target)
+     const char *input_filename;
+     const char *output_filename;
+     const char *input_target;
+     const char *output_target;
+{
+  bfd *ibfd;
+  char **matching;
+
+  /* To allow us to do "strip *" without dying on the first
+     non-object file, failures are nonfatal.  */
+
+  ibfd = bfd_openr (input_filename, input_target);
+  if (ibfd == NULL)
+    RETURN_NONFATAL (input_filename);
+
+  if (bfd_check_format (ibfd, bfd_archive))
+    {
+      bfd *obfd;
+
+      /* bfd_get_target does not return the correct value until
+         bfd_check_format succeeds.  */
+      if (output_target == NULL)
+       output_target = bfd_get_target (ibfd);
+
+      obfd = bfd_openw (output_filename, output_target);
+      if (obfd == NULL)
+       RETURN_NONFATAL (output_filename);
+
+      copy_archive (ibfd, obfd, output_target);
+    }
+  else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
+    {
+      bfd *obfd;
+
+      /* bfd_get_target does not return the correct value until
+         bfd_check_format succeeds.  */
+      if (output_target == NULL)
+       output_target = bfd_get_target (ibfd);
+
+      obfd = bfd_openw (output_filename, output_target);
+      if (obfd == NULL)
+       RETURN_NONFATAL (output_filename);
+
+      copy_object (ibfd, obfd);
+
+      if (!bfd_close (obfd))
+       RETURN_NONFATAL (output_filename);
+
+      if (!bfd_close (ibfd))
+       RETURN_NONFATAL (input_filename);
+    }
+  else
+    {
+      bfd_nonfatal (input_filename);
+      
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      
+      status = 1;
+    }
+}
+
+/* Create a section in OBFD with the same name and attributes
+   as ISECTION in IBFD.  */
+
+static void
+setup_section (ibfd, isection, obfdarg)
+     bfd *ibfd;
+     sec_ptr isection;
+     PTR obfdarg;
+{
+  bfd *obfd = (bfd *) obfdarg;
+  struct section_list *p;
+  sec_ptr osection;
+  bfd_size_type size;
+  bfd_vma vma;
+  bfd_vma lma;
+  flagword flags;
+  char *err;
+
+  if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
+      && (strip_symbols == STRIP_DEBUG
+         || strip_symbols == STRIP_UNNEEDED
+         || strip_symbols == STRIP_ALL
+         || discard_locals == LOCALS_ALL
+         || convert_debugging))
+    return;
+
+  p = find_section_list (bfd_section_name (ibfd, isection), false);
+  if (p != NULL)
+    p->used = true;
+
+  if (p != NULL && p->remove)
+    return;
+
+  osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection));
+  
+  if (osection == NULL)
+    {
+      err = "making";
+      goto loser;
+    }
+
+  size = bfd_section_size (ibfd, isection);
+  if (copy_byte >= 0)
+    size = (size + interleave - 1) / interleave;
+  if (! bfd_set_section_size (obfd, osection, size))
+    {
+      err = "size";
+      goto loser;
+    }
+  
+  vma = bfd_section_vma (ibfd, isection);
+  if (p != NULL && p->change_vma == CHANGE_MODIFY)
+    vma += p->vma_val;
+  else if (p != NULL && p->change_vma == CHANGE_SET)
+    vma = p->vma_val;
+  else
+    vma += change_section_address;
+  
+  if (! bfd_set_section_vma (obfd, osection, vma))
+    {
+      err = "vma";
+      goto loser;
+    }
+
+  lma = isection->lma;
+  if ((p != NULL) && p->change_lma != CHANGE_IGNORE)
+    {
+      if (p->change_lma == CHANGE_MODIFY)
+       lma += p->lma_val;
+      else if (p->change_lma == CHANGE_SET)
+       lma = p->lma_val;
+      else
+       abort ();
+    }
+  else
+    lma += change_section_address;
+  
+  osection->lma = lma;
+
+  /* FIXME: This is probably not enough.  If we change the LMA we
+     may have to recompute the header for the file as well.  */
+  if (bfd_set_section_alignment (obfd,
+                                osection,
+                                bfd_section_alignment (ibfd, isection))
+      == false)
+    {
+      err = "alignment";
+      goto loser;
+    }
+
+  flags = bfd_get_section_flags (ibfd, isection);
+  if (p != NULL && p->set_flags)
+    flags = p->flags | (flags & SEC_HAS_CONTENTS);
+  if (!bfd_set_section_flags (obfd, osection, flags))
+    {
+      err = "flags";
+      goto loser;
+    }
+
+  /* This used to be mangle_section; we do here to avoid using
+     bfd_get_section_by_name since some formats allow multiple
+     sections with the same name.  */
+  isection->output_section = osection;
+  isection->output_offset = 0;
+
+  /* Allow the BFD backend to copy any private data it understands
+     from the input section to the output section.  */
+  if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
+    {
+      err = "private data";
+      goto loser;
+    }
+
+  /* All went well */
+  return;
+
+loser:
+  non_fatal (_("%s: section `%s': error in %s: %s"),
+            bfd_get_filename (ibfd),
+            bfd_section_name (ibfd, isection),
+            err, bfd_errmsg (bfd_get_error ()));
+  status = 1;
+}
+
+/* Copy the data of input section ISECTION of IBFD
+   to an output section with the same name in OBFD.
+   If stripping then don't copy any relocation info.  */
+
+static void
+copy_section (ibfd, isection, obfdarg)
+     bfd *ibfd;
+     sec_ptr isection;
+     PTR obfdarg;
+{
+  bfd *obfd = (bfd *) obfdarg;
+  struct section_list *p;
+  arelent **relpp;
+  long relcount;
+  sec_ptr osection;
+  bfd_size_type size;
+  long relsize;
+
+  /* If we have already failed earlier on, do not keep on generating
+     complaints now.  */
+  if (status != 0)
+    return;
+  
+  if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
+      && (strip_symbols == STRIP_DEBUG
+         || strip_symbols == STRIP_UNNEEDED
+         || strip_symbols == STRIP_ALL
+         || discard_locals == LOCALS_ALL
+         || convert_debugging))
+    {
+      return;
+    }
+
+  p = find_section_list (bfd_section_name (ibfd, isection), false);
+
+  if (p != NULL && p->remove)
+    return;
+
+  osection = isection->output_section;
+  size = bfd_get_section_size_before_reloc (isection);
+
+  if (size == 0 || osection == 0)
+    return;
+
+
+  relsize = bfd_get_reloc_upper_bound (ibfd, isection);
+  if (relsize < 0)
+    RETURN_NONFATAL (bfd_get_filename (ibfd));
+  
+  if (relsize == 0)
+    bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
+  else
+    {
+      relpp = (arelent **) xmalloc (relsize);
+      relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
+      if (relcount < 0)
+       RETURN_NONFATAL (bfd_get_filename (ibfd));
+      
+      if (strip_symbols == STRIP_ALL)
+       {
+         /* Remove relocations which are not in
+            keep_strip_specific_list. */
+         arelent **temp_relpp;
+         long temp_relcount = 0;
+         long i;
+         
+         temp_relpp = (arelent **) xmalloc (relsize);
+         for (i = 0; i < relcount; i++)
+           if (is_specified_symbol
+               (bfd_asymbol_name (*relpp [i]->sym_ptr_ptr),
+                keep_specific_list))
+             temp_relpp [temp_relcount++] = relpp [i];
+         relcount = temp_relcount;
+         free (relpp);
+         relpp = temp_relpp;
+       }
+      bfd_set_reloc (obfd, osection,
+                    (relcount == 0 ? (arelent **) NULL : relpp), relcount);
+    }
+  
+  isection->_cooked_size = isection->_raw_size;
+  isection->reloc_done = true;
+
+  if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
+    {
+      PTR memhunk = (PTR) xmalloc ((unsigned) size);
+
+      if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
+                                    size))
+       RETURN_NONFATAL (bfd_get_filename (ibfd));
+
+      if (copy_byte >= 0) 
+       filter_bytes (memhunk, &size);
+
+      if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
+                                    size))
+       RETURN_NONFATAL (bfd_get_filename (obfd));
+
+      free (memhunk);
+    }
+  else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0)
+    {
+      PTR memhunk = (PTR) xmalloc ((unsigned) size);
+
+      /* We don't permit the user to turn off the SEC_HAS_CONTENTS
+        flag--they can just remove the section entirely and add it
+        back again.  However, we do permit them to turn on the
+        SEC_HAS_CONTENTS flag, and take it to mean that the section
+        contents should be zeroed out.  */
+
+      memset (memhunk, 0, size);
+      if (! bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
+                                     size))
+       RETURN_NONFATAL (bfd_get_filename (obfd));
+      free (memhunk);
+    }
+}
+
+/* Get all the sections.  This is used when --gap-fill or --pad-to is
+   used.  */
+
+static void
+get_sections (obfd, osection, secppparg)
+     bfd *obfd;
+     asection *osection;
+     PTR secppparg;
+{
+  asection ***secppp = (asection ***) secppparg;
+
+  **secppp = osection;
+  ++(*secppp);
+}
+
+/* Sort sections by VMA.  This is called via qsort, and is used when
+   --gap-fill or --pad-to is used.  We force non loadable or empty
+   sections to the front, where they are easier to ignore.  */
+
+static int
+compare_section_lma (arg1, arg2)
+     const PTR arg1;
+     const PTR arg2;
+{
+  const asection **sec1 = (const asection **) arg1;
+  const asection **sec2 = (const asection **) arg2;
+  flagword flags1, flags2;
+
+  /* Sort non loadable sections to the front.  */
+  flags1 = (*sec1)->flags;
+  flags2 = (*sec2)->flags;
+  if ((flags1 & SEC_HAS_CONTENTS) == 0
+      || (flags1 & SEC_LOAD) == 0)
+    {
+      if ((flags2 & SEC_HAS_CONTENTS) != 0
+         && (flags2 & SEC_LOAD) != 0)
+       return -1;
+    }
+  else
+    {
+      if ((flags2 & SEC_HAS_CONTENTS) == 0
+         || (flags2 & SEC_LOAD) == 0)
+       return 1;
+    }
+
+  /* Sort sections by LMA.  */
+  if ((*sec1)->lma > (*sec2)->lma)
+    return 1;
+  else if ((*sec1)->lma < (*sec2)->lma)
+    return -1;
+
+  /* Sort sections with the same LMA by size.  */
+  if ((*sec1)->_raw_size > (*sec2)->_raw_size)
+    return 1;
+  else if ((*sec1)->_raw_size < (*sec2)->_raw_size)
+    return -1;
+
+  return 0;
+}
+
+/* Mark all the symbols which will be used in output relocations with
+   the BSF_KEEP flag so that those symbols will not be stripped.
+
+   Ignore relocations which will not appear in the output file.  */
+
+static void
+mark_symbols_used_in_relocations (ibfd, isection, symbolsarg)
+     bfd *ibfd;
+     sec_ptr isection;
+     PTR symbolsarg;
+{
+  asymbol **symbols = (asymbol **) symbolsarg;
+  long relsize;
+  arelent **relpp;
+  long relcount, i;
+
+  /* Ignore an input section with no corresponding output section.  */
+  if (isection->output_section == NULL)
+    return;
+
+  relsize = bfd_get_reloc_upper_bound (ibfd, isection);
+  if (relsize < 0)
+    bfd_fatal (bfd_get_filename (ibfd));
+
+  if (relsize == 0)
+    return;
+
+  relpp = (arelent **) xmalloc (relsize);
+  relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
+  if (relcount < 0)
+    bfd_fatal (bfd_get_filename (ibfd));
+
+  /* Examine each symbol used in a relocation.  If it's not one of the
+     special bfd section symbols, then mark it with BSF_KEEP.  */
+  for (i = 0; i < relcount; i++)
+    {
+      if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
+         && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
+         && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
+       (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
+    }
+
+  if (relpp != NULL)
+    free (relpp);
+}
+
+/* Write out debugging information.  */
+
+static boolean
+write_debugging_info (obfd, dhandle, symcountp, symppp)
+     bfd *obfd;
+     PTR dhandle;
+     long *symcountp;
+     asymbol ***symppp;
+{
+  if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour)
+    return write_ieee_debugging_info (obfd, dhandle);
+
+  if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
+      || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
+    {
+      bfd_byte *syms, *strings;
+      bfd_size_type symsize, stringsize;
+      asection *stabsec, *stabstrsec;
+
+      if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms,
+                                                   &symsize, &strings,
+                                                   &stringsize))
+       return false;
+
+      stabsec = bfd_make_section (obfd, ".stab");
+      stabstrsec = bfd_make_section (obfd, ".stabstr");
+      if (stabsec == NULL
+         || stabstrsec == NULL
+         || ! bfd_set_section_size (obfd, stabsec, symsize)
+         || ! bfd_set_section_size (obfd, stabstrsec, stringsize)
+         || ! bfd_set_section_alignment (obfd, stabsec, 2)
+         || ! bfd_set_section_alignment (obfd, stabstrsec, 0)
+         || ! bfd_set_section_flags (obfd, stabsec,
+                                  (SEC_HAS_CONTENTS
+                                   | SEC_READONLY
+                                   | SEC_DEBUGGING))
+         || ! bfd_set_section_flags (obfd, stabstrsec,
+                                     (SEC_HAS_CONTENTS
+                                      | SEC_READONLY
+                                      | SEC_DEBUGGING)))
+       {
+         non_fatal (_("%s: can't create debugging section: %s"),
+                    bfd_get_filename (obfd),
+                    bfd_errmsg (bfd_get_error ()));
+         return false;
+       }
+
+      /* We can get away with setting the section contents now because
+         the next thing the caller is going to do is copy over the
+         real sections.  We may someday have to split the contents
+         setting out of this function.  */
+      if (! bfd_set_section_contents (obfd, stabsec, syms, (file_ptr) 0,
+                                     symsize)
+         || ! bfd_set_section_contents (obfd, stabstrsec, strings,
+                                        (file_ptr) 0, stringsize))
+       {
+         non_fatal (_("%s: can't set debugging section contents: %s"),
+                    bfd_get_filename (obfd),
+                    bfd_errmsg (bfd_get_error ()));
+         return false;
+       }
+
+      return true;
+    }
+
+  non_fatal (_("%s: don't know how to write debugging information for %s"),
+            bfd_get_filename (obfd), bfd_get_target (obfd));
+  return false;
+}
+
+static int
+strip_main (argc, argv)
+     int argc;
+     char *argv[];
+{
+  char *input_target = NULL, *output_target = NULL;
+  boolean show_version = false;
+  int c, i;
+  struct section_list *p;
+  char *output_file = NULL;
+
+  while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpgxXVv",
+                          strip_options, (int *) 0)) != EOF)
+    {
+      switch (c)
+       {
+       case 'I':
+         input_target = optarg;
+         break;
+       case 'O':
+         output_target = optarg;
+         break;
+       case 'F':
+         input_target = output_target = optarg;
+         break;
+       case 'R':
+         p = find_section_list (optarg, true);
+         p->remove = true;
+         sections_removed = true;
+         break;
+       case 's':
+         strip_symbols = STRIP_ALL;
+         break;
+       case 'S':
+       case 'g':
+         strip_symbols = STRIP_DEBUG;
+         break;
+       case OPTION_STRIP_UNNEEDED:
+         strip_symbols = STRIP_UNNEEDED;
+         break;
+       case 'K':
+         add_specific_symbol (optarg, &keep_specific_list);
+         break;
+       case 'N':
+         add_specific_symbol (optarg, &strip_specific_list);
+         break;
+       case 'o':
+         output_file = optarg;
+         break;
+       case 'p':
+         preserve_dates = true;
+         break;
+       case 'x':
+         discard_locals = LOCALS_ALL;
+         break;
+       case 'X':
+         discard_locals = LOCALS_START_L;
+         break;
+       case 'v':
+         verbose = true;
+         break;
+       case 'V':
+         show_version = true;
+         break;
+       case 0:
+         break;                /* we've been given a long option */
+       case 'h':
+         strip_usage (stdout, 0);
+       default:
+         strip_usage (stderr, 1);
+       }
+    }
+
+  if (show_version)
+    print_version ("strip");
+
+  /* Default is to strip all symbols.  */
+  if (strip_symbols == STRIP_UNDEF
+      && discard_locals == LOCALS_UNDEF
+      && strip_specific_list == NULL)
+    strip_symbols = STRIP_ALL;
+
+  if (output_target == (char *) NULL)
+    output_target = input_target;
+
+  i = optind;
+  if (i == argc
+      || (output_file != NULL && (i + 1) < argc))
+    strip_usage (stderr, 1);
+
+  for (; i < argc; i++)
+    {
+      int hold_status = status;
+      struct stat statbuf;
+      char *tmpname;
+
+      if (preserve_dates)
+       {
+         if (stat (argv[i], &statbuf) < 0)
+           {
+             non_fatal (_("%s: cannot stat: %s"), argv[i], strerror (errno));
+             continue;
+           }
+       }
+
+      if (output_file != NULL)
+       tmpname = output_file;
+      else
+       tmpname = make_tempname (argv[i]);
+      status = 0;
+
+      copy_file (argv[i], tmpname, input_target, output_target);
+      if (status == 0)
+       {
+         if (preserve_dates)
+           set_times (tmpname, &statbuf);
+         if (output_file == NULL)
+           smart_rename (tmpname, argv[i], preserve_dates);
+         status = hold_status;
+       }
+      else
+       unlink (tmpname);
+      if (output_file == NULL)
+       free (tmpname);
+    }
+
+  return 0;
+}
+
+static int
+copy_main (argc, argv)
+     int argc;
+     char *argv[];
+{
+  char *input_filename = NULL, *output_filename = NULL;
+  char *input_target = NULL, *output_target = NULL;
+  boolean show_version = false;
+  boolean change_warn = true;
+  int c;
+  struct section_list *p;
+  struct stat statbuf;
+
+  while ((c = getopt_long (argc, argv, "b:i:I:K:N:s:O:d:F:L:R:SpgxXVvW:",
+                          copy_options, (int *) 0)) != EOF)
+    {
+      switch (c)
+       {
+       case 'b':
+         copy_byte = atoi (optarg);
+         if (copy_byte < 0)
+           fatal (_("byte number must be non-negative"));
+         break;
+       case 'i':
+         interleave = atoi (optarg);
+         if (interleave < 1)
+           fatal (_("interleave must be positive"));
+         break;
+       case 'I':
+       case 's':               /* "source" - 'I' is preferred */
+         input_target = optarg;
+         break;
+       case 'O':
+       case 'd':               /* "destination" - 'O' is preferred */
+         output_target = optarg;
+         break;
+       case 'F':
+         input_target = output_target = optarg;
+         break;
+       case 'R':
+         p = find_section_list (optarg, true);
+         p->remove = true;
+         sections_removed = true;
+         break;
+       case 'S':
+         strip_symbols = STRIP_ALL;
+         break;
+       case 'g':
+         strip_symbols = STRIP_DEBUG;
+         break;
+       case OPTION_STRIP_UNNEEDED:
+         strip_symbols = STRIP_UNNEEDED;
+         break;
+       case 'K':
+         add_specific_symbol (optarg, &keep_specific_list);
+         break;
+       case 'N':
+         add_specific_symbol (optarg, &strip_specific_list);
+         break;
+       case 'L':
+         add_specific_symbol (optarg, &localize_specific_list);
+         break;
+       case 'W':
+         add_specific_symbol (optarg, &weaken_specific_list);
+         break;
+       case 'p':
+         preserve_dates = true;
+         break;
+       case 'x':
+         discard_locals = LOCALS_ALL;
+         break;
+       case 'X':
+         discard_locals = LOCALS_START_L;
+         break;
+       case 'v':
+         verbose = true;
+         break;
+       case 'V':
+         show_version = true;
+         break;
+       case OPTION_WEAKEN:
+         weaken = true;
+         break;
+       case OPTION_ADD_SECTION:
+         {
+           const char *s;
+           struct stat st;
+           struct section_add *pa;
+           int len;
+           char *name;
+           FILE *f;
+
+           s = strchr (optarg, '=');
+           
+           if (s == NULL)
+             fatal (_("bad format for --add-section NAME=FILENAME"));
+
+           if (stat (s + 1, & st) < 0)
+             fatal (_("cannot stat: %s: %s"), s + 1, strerror (errno));
+
+           pa = (struct section_add *) xmalloc (sizeof (struct section_add));
+
+           len = s - optarg;
+           name = (char *) xmalloc (len + 1);
+           strncpy (name, optarg, len);
+           name[len] = '\0';
+           pa->name = name;
+
+           pa->filename = s + 1;
+
+           pa->size = st.st_size;
+
+           pa->contents = (bfd_byte *) xmalloc (pa->size);
+           f = fopen (pa->filename, FOPEN_RB);
+           
+           if (f == NULL)
+             fatal (_("cannot open: %s: %s"), pa->filename, strerror (errno));
+           
+           if (fread (pa->contents, 1, pa->size, f) == 0
+               || ferror (f))
+             fatal (_("%s: fread failed"), pa->filename);
+
+           fclose (f);
+
+           pa->next = add_sections;
+           add_sections = pa;
+         }
+         break;
+       case OPTION_CHANGE_START:
+         change_start = parse_vma (optarg, "--change-start");
+         break;
+       case OPTION_CHANGE_SECTION_ADDRESS:
+       case OPTION_CHANGE_SECTION_LMA:
+       case OPTION_CHANGE_SECTION_VMA:
+         {
+           const char *s;
+           int len;
+           char *name;
+           char *option;
+           bfd_vma val;
+           enum change_action what;
+           
+           switch (c)
+             {
+             case OPTION_CHANGE_SECTION_ADDRESS: option = "--change-section-address"; break;
+             case OPTION_CHANGE_SECTION_LMA: option = "--change-section-lma"; break;
+             case OPTION_CHANGE_SECTION_VMA: option = "--change-section-vma"; break;
+             }
+           
+           s = strchr (optarg, '=');
+           if (s == NULL)
+             {
+               s = strchr (optarg, '+');
+               if (s == NULL)
+                 {
+                   s = strchr (optarg, '-');
+                   if (s == NULL)
+                     fatal (_("bad format for %s"), option);
+                 }
+             }
+
+           len = s - optarg;
+           name = (char *) xmalloc (len + 1);
+           strncpy (name, optarg, len);
+           name[len] = '\0';
+
+           p = find_section_list (name, true);
+
+           val = parse_vma (s + 1, option);
+
+           switch (*s)
+             {
+             case '=': what = CHANGE_SET; break;
+             case '-': val  = - val; /* Drop through.  */
+             case '+': what = CHANGE_MODIFY; break;
+             }
+           
+           switch (c)
+             {
+             case OPTION_CHANGE_SECTION_ADDRESS:
+               p->change_vma = what;
+               p->vma_val    = val;
+               /* Drop through.  */
+               
+             case OPTION_CHANGE_SECTION_LMA:
+               p->change_lma = what;
+               p->lma_val    = val;
+               break;
+               
+             case OPTION_CHANGE_SECTION_VMA:
+               p->change_vma = what;
+               p->vma_val    = val;
+               break;
+             }
+         }
+         break;
+       case OPTION_CHANGE_ADDRESSES:
+         change_section_address = parse_vma (optarg, "--change-addresses");
+         change_start = change_section_address;
+         break;
+       case OPTION_CHANGE_WARNINGS:
+         change_warn = true;
+         break;
+       case OPTION_CHANGE_LEADING_CHAR:
+         change_leading_char = true;
+         break;
+       case OPTION_DEBUGGING:
+         convert_debugging = true;
+         break;
+       case OPTION_GAP_FILL:
+         {
+           bfd_vma gap_fill_vma;
+
+           gap_fill_vma = parse_vma (optarg, "--gap-fill");
+           gap_fill = (bfd_byte) gap_fill_vma;
+           if ((bfd_vma) gap_fill != gap_fill_vma)
+             {
+               char buff[20];
+               
+               sprintf_vma (buff, gap_fill_vma);
+               
+               non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"),
+                          buff, gap_fill);
+             }
+           gap_fill_set = true;
+         }
+         break;
+       case OPTION_NO_CHANGE_WARNINGS:
+         change_warn = false;
+         break;
+       case OPTION_PAD_TO:
+         pad_to = parse_vma (optarg, "--pad-to");
+         pad_to_set = true;
+         break;
+       case OPTION_REMOVE_LEADING_CHAR:
+         remove_leading_char = true;
+         break;
+       case OPTION_SET_SECTION_FLAGS:
+         {
+           const char *s;
+           int len;
+           char *name;
+
+           s = strchr (optarg, '=');
+           if (s == NULL)
+             fatal (_("bad format for --set-section-flags"));
+
+           len = s - optarg;
+           name = (char *) xmalloc (len + 1);
+           strncpy (name, optarg, len);
+           name[len] = '\0';
+
+           p = find_section_list (name, true);
+
+           p->set_flags = true;
+           p->flags = parse_flags (s + 1);
+         }
+         break;
+       case OPTION_SET_START:
+         set_start = parse_vma (optarg, "--set-start");
+         set_start_set = true;
+         break;
+       case 0:
+         break;                /* we've been given a long option */
+       case 'h':
+         copy_usage (stdout, 0);
+       default:
+         copy_usage (stderr, 1);
+       }
+    }
+
+  if (show_version)
+    print_version ("objcopy");
+
+  if (copy_byte >= interleave)
+    fatal (_("byte number must be less than interleave"));
+
+  if (optind == argc || optind + 2 < argc)
+    copy_usage (stderr, 1);
+
+  input_filename = argv[optind];
+  if (optind + 1 < argc)
+    output_filename = argv[optind + 1];
+
+  /* Default is to strip no symbols.  */
+  if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF)
+    strip_symbols = STRIP_NONE;
+
+  if (output_target == (char *) NULL)
+    output_target = input_target;
+
+  if (preserve_dates)
+    {
+      if (stat (input_filename, &statbuf) < 0)
+       fatal (_("Cannot stat: %s: %s"), input_filename, strerror (errno));
+    }
+
+  /* If there is no destination file then create a temp and rename
+     the result into the input.  */
+
+  if (output_filename == (char *) NULL)
+    {
+      char *tmpname = make_tempname (input_filename);
+
+      copy_file (input_filename, tmpname, input_target, output_target);
+      if (status == 0)
+       {       
+         if (preserve_dates)
+           set_times (tmpname, &statbuf);
+         smart_rename (tmpname, input_filename, preserve_dates);
+       }
+      else
+       unlink (tmpname);
+    }
+  else
+    {
+      copy_file (input_filename, output_filename, input_target, output_target);
+      if (status == 0 && preserve_dates)
+       set_times (output_filename, &statbuf);
+    }
+
+  if (change_warn)
+    {
+      for (p = change_sections; p != NULL; p = p->next)
+       {
+         if (! p->used)
+           {
+             if (p->change_vma != CHANGE_IGNORE)
+               {
+                 char buff [20];
+
+                 sprintf_vma (buff, p->vma_val);
+                 
+                 /* xgettext:c-format */
+                 non_fatal (_("Warning: --change-section-vma %s%c0x%s never used"),
+                            p->name,
+                            p->change_vma == CHANGE_SET ? '=' : '+',
+                            buff);
+               }
+             
+             if (p->change_lma != CHANGE_IGNORE)
+               {
+                 char buff [20];
+
+                 sprintf_vma (buff, p->lma_val);
+                 
+                 /* xgettext:c-format */
+                 non_fatal (_("Warning: --change-section-lma %s%c0x%s never used"),
+                            p->name,
+                            p->change_lma == CHANGE_SET ? '=' : '+',
+                            buff);
+               }
+           }
+       }
+    }
+
+  return 0;
+}
+
+int
+main (argc, argv)
+     int argc;
+     char *argv[];
+{
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = argv[0];
+  xmalloc_set_program_name (program_name);
+
+  START_PROGRESS (program_name, 0);
+
+  strip_symbols = STRIP_UNDEF;
+  discard_locals = LOCALS_UNDEF;
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  if (is_strip < 0)
+    {
+      int i = strlen (program_name);
+      is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip") == 0);
+    }
+
+  if (is_strip)
+    strip_main (argc, argv);
+  else
+    copy_main (argc, argv);
+
+  END_PROGRESS (program_name);
+
+  return status;
+}
diff --git a/binutils/objdump.1 b/binutils/objdump.1
new file mode 100644 (file)
index 0000000..ddc153e
--- /dev/null
@@ -0,0 +1,412 @@
+.\" Copyright (c) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH objdump 1 "5 November 1991" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+objdump \- display information from object files.
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B objdump
+.RB "[\|" \-a | \-\-archive\-headers "\|]" 
+.RB "[\|" "\-b\ "\c
+.I bfdname\c
+.RB " | " "\-\-target="\c
+.I bfdname\c
+\&\|] 
+.RB "[\|" \-C | \-\-demangle "\|]" 
+.RB "[\|" \-\-debugging "\|]" 
+.RB "[\|" \-d | \-\-disassemble "\|]" 
+.RB "[\|" \-D | \-\-disassemble-all "\|]" 
+.RB "[\|" \-\-disassemble\-zeroes "\|]" 
+.RB "[\|" \-EB | \-EL | \-\-endian=\c
+.I {big|little}\c
+\&\|]
+.RB "[\|" \-f | \-\-file\-headers "\|]"
+.RB "[\|" \-h | \-\-section\-headers
+.RB "| " \-\-headers "\|]" 
+.RB "[\|" \-i | \-\-info "\|]" 
+.RB "[\|" "\-j\ "\c
+.I section\c
+.RB " | " "\-\-section="\c
+.I section\c
+\&\|] 
+.RB "[\|" \-l | \-\-line\-numbers "\|]"
+.RB "[\|" "\-m\ "\c
+.I machine\c
+.RB " | " "\-\-architecture="\c
+.I machine\c
+\&\|] 
+.RB "[\|" \-p | \-\-private\-headers "\|]" 
+.RB "[\|" \-\-prefix\-addresses "\|]" 
+.RB "[\|" \-r | \-\-reloc "\|]" 
+.RB "[\|" \-R | \-\-dynamic\-reloc "\|]" 
+.RB "[\|" \-s | \-\-full\-contents "\|]"
+.RB "[\|" \-S | \-\-source "\|]"
+.RB "[\|" \-\-[no\-]show\-raw\-insn "\|]" 
+.RB "[\|" \-\-stabs "\|]"
+.RB "[\|" \-t | \-\-syms "\|]" 
+.RB "[\|" \-T | \-\-dynamic\-syms "\|]" 
+.RB "[\|" \-x | \-\-all\-headers "\|]"
+.RB "[\|" "\-\-start\-address="\c
+.I address\c
+\&\|]
+.RB "[\|" "\-\-stop\-address="\c
+.I address\c
+\&\|]
+.RB "[\|" "\-\-adjust\-vma="\c
+.I offset\c
+\&\|]
+.RB "[\|" \-\-version "\|]"
+.RB "[\|" \-\-help "\|]"
+.I objfile\c
+\&.\|.\|.
+.ad b
+.hy 1
+.SH DESCRIPTION
+\c
+.B objdump\c
+\& displays information about one or more object files.
+The options control what particular information to display.  This
+information is mostly useful to programmers who are working on the
+compilation tools, as opposed to programmers who just want their
+program to compile and work.
+.PP
+.IR  "objfile" .\|.\|.
+are the object files to be examined.  When you specify archives,
+\c
+.B objdump\c
+\& shows information on each of the member object files.
+
+.SH OPTIONS
+Where long and short forms of an option are shown together, they are
+equivalent.  At least one option besides
+.B \-l
+(\fB\-\-line\-numbers\fP) must be given.
+
+.TP
+.B \-a
+.TP
+.B \-\-archive\-headers
+If any files from \c
+.I objfile\c
+\& are archives, display the archive
+header information (in a format similar to `\|\c
+.B ls \-l\c
+\|').  Besides the
+information you could list with `\|\c
+.B ar tv\c
+\|', `\|\c
+.B objdump \-a\c
+\|' shows
+the object file format of each archive member.
+
+.TP
+.BI "\-\-adjust\-vma=" "offset"
+When dumping information, first add
+.I offset
+to all the section addresses.  This is useful if the section addresses
+do not correspond to the symbol table, which can happen when putting
+sections at particular addresses when using a format which can not
+represent section addresses, such as a.out.
+
+.TP
+.BI "\-b " "bfdname"\c
+.TP
+.BI "\-\-target=" "bfdname"
+Specify the object-code format for the object files to be
+\c
+.I bfdname\c
+\&.  This may not be necessary; \c
+.I objdump\c
+\& can
+automatically recognize many formats.  For example,
+.sp
+.br
+objdump\ \-b\ oasys\ \-m\ vax\ \-h\ fu.o
+.br
+.sp
+display summary information from the section headers (`\|\c
+.B \-h\c
+\|') of
+`\|\c
+.B fu.o\c
+\|', which is explicitly identified (`\|\c
+.B \-m\c
+\|') as a Vax object
+file in the format produced by Oasys compilers.  You can list the
+formats available with the `\|\c
+.B \-i\c
+\|' option.
+
+.TP
+.B \-C
+.TP
+.B \-\-demangle
+Decode (\fIdemangle\fP) low-level symbol names into user-level names.
+Besides removing any initial underscore prepended by the system, this
+makes C++ function names readable.
+
+.TP
+.B \-\-debugging
+Display debugging information.  This attempts to parse debugging
+information stored in the file and print it out using a C like syntax.
+Only certain types of debugging information have been implemented.
+
+.TP
+.B \-d
+.TP
+.B \-\-disassemble
+Display the assembler mnemonics for the machine
+instructions from \c
+.I objfile\c
+\&.
+This option only disassembles those sections which are
+expected to contain instructions.
+
+.TP
+.B \-D
+.TP
+.B \-\-disassemble-all
+Like \fB\-d\fP, but disassemble the contents of all sections, not just
+those expected to contain instructions.
+
+.TP
+.B \-\-prefix\-addresses
+When disassembling, print the complete address on each line.  This is
+the older disassembly format.
+
+.TP
+.B \-\-disassemble\-zeroes
+Normally the disassembly output will skip blocks of zeroes.  This
+option directs the disassembler to disassemble those blocks, just like
+any other data.
+
+.TP
+.B \-EB
+.TP
+.B \-EL
+.TP
+.BI "\-\-endian=" "{big|little}"
+Specify the endianness of the object files.  This only affects
+disassembly.  This can be useful when disassembling a file format which
+does not describe endianness information, such as S-records.
+
+.TP
+.B \-f
+.TP
+.B \-\-file\-headers
+Display summary information from the overall header of
+each file in \c
+.I objfile\c
+\&.
+
+.TP
+.B \-h
+.TP
+.B \-\-section\-headers
+.TP
+.B \-\-headers
+Display summary information from the section headers of the
+object file.
+
+.TP
+.B \-\-help
+Print a summary of the options to
+.B objdump
+and exit.
+
+.TP
+.B \-i
+.TP
+.B \-\-info
+Display a list showing all architectures and object formats available
+for specification with \c
+.B \-b\c
+\& or \c
+.B \-m\c
+\&.
+
+.TP
+.BI "\-j " "name"\c
+.TP
+.BI "\-\-section=" "name"
+Display information only for section \c
+.I name\c
+\&.
+
+.TP
+.B \-l
+.TP
+.B \-\-line\-numbers
+Label the display (using debugging information) with the filename
+and source line numbers corresponding to the object code shown.
+Only useful with \fB\-d\fP, \fB\-D\fP, or \fB\-r\fP.
+
+.TP
+.BI "\-m " "machine"\c
+.TP
+.BI "\-\-architecture=" "machine"
+Specify the architecture to use when disassembling object files.  This
+can be useful when disassembling object files which do not describe
+architecture information, such as S-records.  You can list the available
+architectures with the \fB\-i\fP option. 
+
+.TP
+.B \-p
+.TP
+.B \-\-private\-headers
+Print information that is specific to the object file format.  The
+exact information printed depends upon the object file format.  For
+some object file formats, no additional information is printed.
+
+.TP
+.B \-r
+.TP
+.B \-\-reloc
+Print the relocation entries of the file.  If used with \fB\-d\fP or
+\fB\-D\fP, the relocations are printed interspersed with the
+disassembly.
+
+.TP
+.B \-R
+.TP
+.B \-\-dynamic\-reloc
+Print the dynamic relocation entries of the file.  This is only
+meaningful for dynamic objects, such as certain types of shared
+libraries.
+
+.TP
+.B \-s
+.TP
+.B \-\-full\-contents
+Display the full contents of any sections requested.
+
+.TP
+.B \-S
+.TP
+.B \-\-source
+Display source code intermixed with disassembly, if possible.  Implies
+\fB-d\fP.
+
+.TP
+.B \-\-show\-raw\-insn
+When disassembling instructions, print the instruction in hex as well as
+in symbolic form.  This is the default except when
+.B \-\-prefix\-addresses
+is used.
+
+.TP
+.B \-\-no\-show\-raw\-insn
+When disassembling instructions, do not print the instruction bytes.
+This is the default when
+.B \-\-prefix\-addresses
+is used.
+
+.TP
+.B \-\-stabs
+Display the contents of the .stab, .stab.index, and .stab.excl
+sections from an ELF file.  This is only useful on systems (such as
+Solaris 2.0) in which .stab debugging symbol-table entries are carried
+in an ELF section.  In most other file formats, debugging symbol-table
+entries are interleaved with linkage symbols, and are visible in the
+.B \-\-syms
+output.
+
+.TP
+.BI "\-\-start\-address=" "address"
+Start displaying data at the specified address.  This affects the output
+of the
+.B \-d\c
+,
+.B \-r
+and
+.B \-s
+options.
+
+.TP
+.BI "\-\-stop\-address=" "address"
+Stop displaying data at the specified address.  This affects the output
+of the
+.B \-d\c
+,
+.B \-r
+and
+.B \-s
+options.
+
+.TP
+.B \-t
+.TP
+.B \-\-syms
+Symbol Table.  Print the symbol table entries of the file.
+This is similar to the information provided by the `\|\c
+.B nm\c
+\|' program.
+
+.TP
+.B \-T
+.TP
+.B \-\-dynamic\-syms
+Dynamic Symbol Table.  Print the dynamic symbol table entries of the
+file.  This is only meaningful for dynamic objects, such as certain
+types of shared libraries.  This is similar to the information
+provided by the `\|\c
+.B nm\c
+\|' program when given the
+.B \-D (\-\-dynamic)
+option.
+
+.TP
+.B \-\-version
+Print the version number of
+.B objdump
+and exit.
+
+.TP
+.B \-x
+.TP
+.B \-\-all\-headers
+Display all available header information, including the symbol table and
+relocation entries.  Using `\|\c
+.B \-x\c
+\|' is equivalent to specifying all of
+`\|\c
+.B \-a \-f \-h \-r \-t\c
+\|'.
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'"
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (October 1991); 
+.BR nm "(" 1 ")."
+
+.SH COPYING
+Copyright (c) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/objdump.c b/binutils/objdump.c
new file mode 100644 (file)
index 0000000..3f9e8c4
--- /dev/null
@@ -0,0 +1,2829 @@
+/* objdump.c -- dump information about an object file.
+   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+
+This file is part of 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 2, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "bfd.h"
+#include "getopt.h"
+#include "progress.h"
+#include "bucomm.h"
+#include <ctype.h>
+#include "dis-asm.h"
+#include "libiberty.h"
+#include "demangle.h"
+#include "debug.h"
+#include "budbg.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/* Internal headers for the ELF .stab-dump code - sorry.  */
+#define        BYTES_IN_WORD   32
+#include "aout/aout64.h"
+
+#ifdef NEED_DECLARATION_FPRINTF
+/* This is needed by INIT_DISASSEMBLE_INFO.  */
+extern int fprintf PARAMS ((FILE *, const char *, ...));
+#endif
+
+static char *default_target = NULL;    /* default at runtime */
+
+static int show_version = 0;           /* show the version number */
+static int dump_section_contents;      /* -s */
+static int dump_section_headers;       /* -h */
+static boolean dump_file_header;       /* -f */
+static int dump_symtab;                        /* -t */
+static int dump_dynamic_symtab;                /* -T */
+static int dump_reloc_info;            /* -r */
+static int dump_dynamic_reloc_info;    /* -R */
+static int dump_ar_hdrs;               /* -a */
+static int dump_private_headers;       /* -p */
+static int prefix_addresses;           /* --prefix-addresses */
+static int with_line_numbers;          /* -l */
+static boolean with_source_code;       /* -S */
+static int show_raw_insn;              /* --show-raw-insn */
+static int dump_stab_section_info;     /* --stabs */
+static int do_demangle;                        /* -C, --demangle */
+static boolean disassemble;            /* -d */
+static boolean disassemble_all;                /* -D */
+static int disassemble_zeroes;         /* --disassemble-zeroes */
+static boolean formats_info;           /* -i */
+static char *only;                     /* -j secname */
+static int wide_output;                        /* -w */
+static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
+static bfd_vma stop_address = (bfd_vma) -1;  /* --stop-address */
+static int dump_debugging;             /* --debugging */
+static bfd_vma adjust_section_vma = 0; /* --adjust-vma */
+
+/* Extra info to pass to the disassembler address printing function.  */
+struct objdump_disasm_info {
+  bfd *abfd;
+  asection *sec;
+  boolean require_sec;
+};
+
+/* Architecture to disassemble for, or default if NULL.  */
+static char *machine = (char *) NULL;
+
+/* Endianness to disassemble for, or default if BFD_ENDIAN_UNKNOWN.  */
+static enum bfd_endian endian = BFD_ENDIAN_UNKNOWN;
+
+/* The symbol table.  */
+static asymbol **syms;
+
+/* Number of symbols in `syms'.  */
+static long symcount = 0;
+
+/* The sorted symbol table.  */
+static asymbol **sorted_syms;
+
+/* Number of symbols in `sorted_syms'.  */
+static long sorted_symcount = 0;
+
+/* The dynamic symbol table.  */
+static asymbol **dynsyms;
+
+/* Number of symbols in `dynsyms'.  */
+static long dynsymcount = 0;
+
+/* Static declarations.  */
+
+static void
+usage PARAMS ((FILE *, int));
+
+static void
+display_file PARAMS ((char *filename, char *target));
+
+static void
+dump_section_header PARAMS ((bfd *, asection *, PTR));
+
+static void
+dump_headers PARAMS ((bfd *));
+
+static void
+dump_data PARAMS ((bfd *abfd));
+
+static void
+dump_relocs PARAMS ((bfd *abfd));
+
+static void
+dump_dynamic_relocs PARAMS ((bfd * abfd));
+
+static void
+dump_reloc_set PARAMS ((bfd *, asection *, arelent **, long));
+
+static void
+dump_symbols PARAMS ((bfd *abfd, boolean dynamic));
+
+static void
+dump_bfd_header PARAMS ((bfd *));
+
+static void
+dump_bfd_private_header PARAMS ((bfd *));
+
+static void
+display_bfd PARAMS ((bfd *abfd));
+
+static void
+display_target_list PARAMS ((void));
+
+static void
+display_info_table PARAMS ((int, int));
+
+static void
+display_target_tables PARAMS ((void));
+
+static void
+display_info PARAMS ((void));
+
+static void
+objdump_print_value PARAMS ((bfd_vma, struct disassemble_info *, boolean));
+
+static void
+objdump_print_symname PARAMS ((bfd *, struct disassemble_info *, asymbol *));
+
+static asymbol *
+find_symbol_for_address PARAMS ((bfd *, asection *, bfd_vma, boolean, long *));
+
+static void
+objdump_print_addr_with_sym PARAMS ((bfd *, asection *, asymbol *, bfd_vma,
+                                    struct disassemble_info *, boolean));
+
+static void
+objdump_print_addr PARAMS ((bfd_vma, struct disassemble_info *, boolean));
+
+static void
+objdump_print_address PARAMS ((bfd_vma, struct disassemble_info *));
+
+static void
+show_line PARAMS ((bfd *, asection *, bfd_vma));
+
+static void
+disassemble_bytes PARAMS ((struct disassemble_info *, disassembler_ftype,
+                          boolean, bfd_byte *, bfd_vma, bfd_vma,
+                          arelent ***, arelent **));
+
+static void
+disassemble_data PARAMS ((bfd *));
+
+static const char *
+endian_string PARAMS ((enum bfd_endian));
+
+static asymbol **
+slurp_symtab PARAMS ((bfd *));
+
+static asymbol **
+slurp_dynamic_symtab PARAMS ((bfd *));
+
+static long
+remove_useless_symbols PARAMS ((asymbol **, long));
+
+static int
+compare_symbols PARAMS ((const PTR, const PTR));
+
+static int
+compare_relocs PARAMS ((const PTR, const PTR));
+
+static void
+dump_stabs PARAMS ((bfd *));
+
+static boolean
+read_section_stabs PARAMS ((bfd *, const char *, const char *));
+
+static void
+print_section_stabs PARAMS ((bfd *, const char *, const char *));
+\f
+static void
+usage (stream, status)
+     FILE *stream;
+     int status;
+{
+  fprintf (stream, _("\
+Usage: %s [-ahifCdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n\
+       [--archive-headers] [--target=bfdname] [--debugging] [--disassemble]\n\
+       [--disassemble-all] [--disassemble-zeroes] [--file-headers]\n\
+       [--section-headers] [--headers]\n\
+       [--info] [--section=section-name] [--line-numbers] [--source]\n"),
+          program_name);
+  fprintf (stream, _("\
+       [--architecture=machine] [--reloc] [--full-contents] [--stabs]\n\
+       [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\
+       [--wide] [--version] [--help] [--private-headers]\n\
+       [--start-address=addr] [--stop-address=addr]\n\
+       [--prefix-addresses] [--[no-]show-raw-insn] [--demangle]\n\
+       [--adjust-vma=offset] [-EB|-EL] [--endian={big|little}] objfile...\n\
+at least one option besides -l (--line-numbers) must be given\n"));
+  list_supported_targets (program_name, stream);
+  if (status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (status);
+}
+
+/* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
+
+#define OPTION_ENDIAN (150)
+#define OPTION_START_ADDRESS (OPTION_ENDIAN + 1)
+#define OPTION_STOP_ADDRESS (OPTION_START_ADDRESS + 1)
+#define OPTION_ADJUST_VMA (OPTION_STOP_ADDRESS + 1)
+
+static struct option long_options[]=
+{
+  {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA},
+  {"all-headers", no_argument, NULL, 'x'},
+  {"private-headers", no_argument, NULL, 'p'},
+  {"architecture", required_argument, NULL, 'm'},
+  {"archive-headers", no_argument, NULL, 'a'},
+  {"debugging", no_argument, &dump_debugging, 1},
+  {"demangle", no_argument, &do_demangle, 1},
+  {"disassemble", no_argument, NULL, 'd'},
+  {"disassemble-all", no_argument, NULL, 'D'},
+  {"disassemble-zeroes", no_argument, &disassemble_zeroes, 1},
+  {"dynamic-reloc", no_argument, NULL, 'R'},
+  {"dynamic-syms", no_argument, NULL, 'T'},
+  {"endian", required_argument, NULL, OPTION_ENDIAN},
+  {"file-headers", no_argument, NULL, 'f'},
+  {"full-contents", no_argument, NULL, 's'},
+  {"headers", no_argument, NULL, 'h'},
+  {"help", no_argument, NULL, 'H'},
+  {"info", no_argument, NULL, 'i'},
+  {"line-numbers", no_argument, NULL, 'l'},
+  {"no-show-raw-insn", no_argument, &show_raw_insn, -1},
+  {"prefix-addresses", no_argument, &prefix_addresses, 1},
+  {"reloc", no_argument, NULL, 'r'},
+  {"section", required_argument, NULL, 'j'},
+  {"section-headers", no_argument, NULL, 'h'},
+  {"show-raw-insn", no_argument, &show_raw_insn, 1},
+  {"source", no_argument, NULL, 'S'},
+  {"stabs", no_argument, &dump_stab_section_info, 1},
+  {"start-address", required_argument, NULL, OPTION_START_ADDRESS},
+  {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS},
+  {"syms", no_argument, NULL, 't'},
+  {"target", required_argument, NULL, 'b'},
+  {"version", no_argument, &show_version, 1},
+  {"wide", no_argument, &wide_output, 'w'},
+  {0, no_argument, 0, 0}
+};
+\f
+static void
+dump_section_header (abfd, section, ignored)
+     bfd *abfd;
+     asection *section;
+     PTR ignored;
+{
+  char *comma = "";
+
+  printf ("%3d %-13s %08lx  ", section->index,
+         bfd_get_section_name (abfd, section),
+         (unsigned long) bfd_section_size (abfd, section));
+  printf_vma (bfd_get_section_vma (abfd, section));
+  printf ("  ");
+  printf_vma (section->lma);
+  printf ("  %08lx  2**%u", section->filepos,
+         bfd_get_section_alignment (abfd, section));
+  if (! wide_output)
+    printf ("\n                ");
+  printf ("  ");
+
+#define PF(x, y) \
+  if (section->flags & x) { printf ("%s%s", comma, y); comma = ", "; }
+
+  PF (SEC_HAS_CONTENTS, "CONTENTS");
+  PF (SEC_ALLOC, "ALLOC");
+  PF (SEC_CONSTRUCTOR, "CONSTRUCTOR");
+  PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT");
+  PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA");
+  PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS");
+  PF (SEC_LOAD, "LOAD");
+  PF (SEC_RELOC, "RELOC");
+#ifdef SEC_BALIGN
+  PF (SEC_BALIGN, "BALIGN");
+#endif
+  PF (SEC_READONLY, "READONLY");
+  PF (SEC_CODE, "CODE");
+  PF (SEC_DATA, "DATA");
+  PF (SEC_ROM, "ROM");
+  PF (SEC_DEBUGGING, "DEBUGGING");
+  PF (SEC_NEVER_LOAD, "NEVER_LOAD");
+  PF (SEC_EXCLUDE, "EXCLUDE");
+  PF (SEC_SORT_ENTRIES, "SORT_ENTRIES");
+
+  if ((section->flags & SEC_LINK_ONCE) != 0)
+    {
+      const char *ls;
+
+      switch (section->flags & SEC_LINK_DUPLICATES)
+       {
+       default:
+         abort ();
+       case SEC_LINK_DUPLICATES_DISCARD:
+         ls = "LINK_ONCE_DISCARD";
+         break;
+       case SEC_LINK_DUPLICATES_ONE_ONLY:
+         ls = "LINK_ONCE_ONE_ONLY";
+         break;
+       case SEC_LINK_DUPLICATES_SAME_SIZE:
+         ls = "LINK_ONCE_SAME_SIZE";
+         break;
+       case SEC_LINK_DUPLICATES_SAME_CONTENTS:
+         ls = "LINK_ONCE_SAME_CONTENTS";
+         break;
+       }
+      printf ("%s%s", comma, ls);
+      comma = ", ";
+    }
+
+  printf ("\n");
+#undef PF
+}
+
+static void
+dump_headers (abfd)
+     bfd *abfd;
+{
+  printf (_("Sections:\n"));
+#ifndef BFD64
+  printf (_("Idx Name          Size      VMA       LMA       File off  Algn\n"));
+#else
+  printf (_("Idx Name          Size      VMA               LMA               File off  Algn\n"));
+#endif
+  bfd_map_over_sections (abfd, dump_section_header, (PTR) NULL);
+}
+\f
+static asymbol **
+slurp_symtab (abfd)
+     bfd *abfd;
+{
+  asymbol **sy = (asymbol **) NULL;
+  long storage;
+
+  if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
+    {
+      fprintf (stderr, _("%s: no symbols\n"), bfd_get_filename (abfd));
+      symcount = 0;
+      return NULL;
+    }
+
+  storage = bfd_get_symtab_upper_bound (abfd);
+  if (storage < 0)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  if (storage)
+    {
+      sy = (asymbol **) xmalloc (storage);
+    }
+  symcount = bfd_canonicalize_symtab (abfd, sy);
+  if (symcount < 0)
+    bfd_fatal (bfd_get_filename (abfd));
+  if (symcount == 0)
+    fprintf (stderr, _("%s: no symbols\n"), bfd_get_filename (abfd));
+  return sy;
+}
+
+/* Read in the dynamic symbols.  */
+
+static asymbol **
+slurp_dynamic_symtab (abfd)
+     bfd *abfd;
+{
+  asymbol **sy = (asymbol **) NULL;
+  long storage;
+
+  storage = bfd_get_dynamic_symtab_upper_bound (abfd);
+  if (storage < 0)
+    {
+      if (!(bfd_get_file_flags (abfd) & DYNAMIC))
+       {
+         fprintf (stderr, _("%s: %s: not a dynamic object\n"),
+                  program_name, bfd_get_filename (abfd));
+         dynsymcount = 0;
+         return NULL;
+       }
+
+      bfd_fatal (bfd_get_filename (abfd));
+    }
+
+  if (storage)
+    {
+      sy = (asymbol **) xmalloc (storage);
+    }
+  dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy);
+  if (dynsymcount < 0)
+    bfd_fatal (bfd_get_filename (abfd));
+  if (dynsymcount == 0)
+    fprintf (stderr, _("%s: %s: No dynamic symbols\n"),
+            program_name, bfd_get_filename (abfd));
+  return sy;
+}
+
+/* Filter out (in place) symbols that are useless for disassembly.
+   COUNT is the number of elements in SYMBOLS.
+   Return the number of useful symbols. */
+
+static long
+remove_useless_symbols (symbols, count)
+     asymbol **symbols;
+     long count;
+{
+  register asymbol **in_ptr = symbols, **out_ptr = symbols;
+
+  while (--count >= 0)
+    {
+      asymbol *sym = *in_ptr++;
+
+      if (sym->name == NULL || sym->name[0] == '\0')
+       continue;
+      if (sym->flags & (BSF_DEBUGGING))
+       continue;
+      if (bfd_is_und_section (sym->section)
+         || bfd_is_com_section (sym->section))
+       continue;
+
+      *out_ptr++ = sym;
+    }
+  return out_ptr - symbols;
+}
+
+/* Sort symbols into value order.  */
+
+static int 
+compare_symbols (ap, bp)
+     const PTR ap;
+     const PTR bp;
+{
+  const asymbol *a = *(const asymbol **)ap;
+  const asymbol *b = *(const asymbol **)bp;
+  const char *an, *bn;
+  size_t anl, bnl;
+  boolean af, bf;
+  flagword aflags, bflags;
+
+  if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
+    return 1;
+  else if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
+    return -1;
+
+  if (a->section > b->section)
+    return 1;
+  else if (a->section < b->section)
+    return -1;
+
+  an = bfd_asymbol_name (a);
+  bn = bfd_asymbol_name (b);
+  anl = strlen (an);
+  bnl = strlen (bn);
+
+  /* The symbols gnu_compiled and gcc2_compiled convey no real
+     information, so put them after other symbols with the same value.  */
+
+  af = (strstr (an, "gnu_compiled") != NULL
+       || strstr (an, "gcc2_compiled") != NULL);
+  bf = (strstr (bn, "gnu_compiled") != NULL
+       || strstr (bn, "gcc2_compiled") != NULL);
+
+  if (af && ! bf)
+    return 1;
+  if (! af && bf)
+    return -1;
+
+  /* We use a heuristic for the file name, to try to sort it after
+     more useful symbols.  It may not work on non Unix systems, but it
+     doesn't really matter; the only difference is precisely which
+     symbol names get printed.  */
+
+#define file_symbol(s, sn, snl)                        \
+  (((s)->flags & BSF_FILE) != 0                        \
+   || ((sn)[(snl) - 2] == '.'                  \
+       && ((sn)[(snl) - 1] == 'o'              \
+          || (sn)[(snl) - 1] == 'a')))
+
+  af = file_symbol (a, an, anl);
+  bf = file_symbol (b, bn, bnl);
+
+  if (af && ! bf)
+    return 1;
+  if (! af && bf)
+    return -1;
+
+  /* Try to sort global symbols before local symbols before function
+     symbols before debugging symbols.  */
+
+  aflags = a->flags;
+  bflags = b->flags;
+
+  if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING))
+    {
+      if ((aflags & BSF_DEBUGGING) != 0)
+       return 1;
+      else
+       return -1;
+    }
+  if ((aflags & BSF_FUNCTION) != (bflags & BSF_FUNCTION))
+    {
+      if ((aflags & BSF_FUNCTION) != 0)
+       return -1;
+      else
+       return 1;
+    }
+  if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL))
+    {
+      if ((aflags & BSF_LOCAL) != 0)
+       return 1;
+      else
+       return -1;
+    }
+  if ((aflags & BSF_GLOBAL) != (bflags & BSF_GLOBAL))
+    {
+      if ((aflags & BSF_GLOBAL) != 0)
+       return -1;
+      else
+       return 1;
+    }
+
+  /* Symbols that start with '.' might be section names, so sort them
+     after symbols that don't start with '.'.  */
+  if (an[0] == '.' && bn[0] != '.')
+    return 1;
+  if (an[0] != '.' && bn[0] == '.')
+    return -1;
+
+  /* Finally, if we can't distinguish them in any other way, try to
+     get consistent results by sorting the symbols by name.  */
+  return strcmp (an, bn);
+}
+
+/* Sort relocs into address order.  */
+
+static int
+compare_relocs (ap, bp)
+     const PTR ap;
+     const PTR bp;
+{
+  const arelent *a = *(const arelent **)ap;
+  const arelent *b = *(const arelent **)bp;
+
+  if (a->address > b->address)
+    return 1;
+  else if (a->address < b->address)
+    return -1;
+
+  /* So that associated relocations tied to the same address show up
+     in the correct order, we don't do any further sorting.  */
+  if (a > b)
+    return 1;
+  else if (a < b)
+    return -1;
+  else
+    return 0;
+}
+
+/* Print VMA to STREAM.  If SKIP_ZEROES is true, omit leading zeroes.  */
+
+static void
+objdump_print_value (vma, info, skip_zeroes)
+     bfd_vma vma;
+     struct disassemble_info *info;
+     boolean skip_zeroes;
+{
+  char buf[30];
+  char *p;
+
+  sprintf_vma (buf, vma);
+  if (! skip_zeroes)
+    p = buf;
+  else
+    {
+      for (p = buf; *p == '0'; ++p)
+       ;
+      if (*p == '\0')
+       --p;
+    }
+  (*info->fprintf_func) (info->stream, "%s", p);
+}
+
+/* Print the name of a symbol.  */
+
+static void
+objdump_print_symname (abfd, info, sym)
+     bfd *abfd;
+     struct disassemble_info *info;
+     asymbol *sym;
+{
+  char *alloc;
+  const char *name;
+  const char *print;
+
+  alloc = NULL;
+  name = bfd_asymbol_name (sym);
+  if (! do_demangle || name[0] == '\0')
+    print = name;
+  else
+    {
+      /* Demangle the name.  */
+      if (bfd_get_symbol_leading_char (abfd) == name[0])
+       ++name;
+
+      alloc = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+      if (alloc == NULL)
+       print = name;
+      else
+       print = alloc;
+    }
+
+  if (info != NULL)
+    (*info->fprintf_func) (info->stream, "%s", print);
+  else
+    printf ("%s", print);
+
+  if (alloc != NULL)
+    free (alloc);
+}
+
+/* Locate a symbol given a bfd, a section, and a VMA.  If REQUIRE_SEC
+   is true, then always require the symbol to be in the section.  This
+   returns NULL if there is no suitable symbol.  If PLACE is not NULL,
+   then *PLACE is set to the index of the symbol in sorted_syms.  */
+
+static asymbol *
+find_symbol_for_address (abfd, sec, vma, require_sec, place)
+     bfd *abfd;
+     asection *sec;
+     bfd_vma vma;
+     boolean require_sec;
+     long *place;
+{
+  /* @@ Would it speed things up to cache the last two symbols returned,
+     and maybe their address ranges?  For many processors, only one memory
+     operand can be present at a time, so the 2-entry cache wouldn't be
+     constantly churned by code doing heavy memory accesses.  */
+
+  /* Indices in `sorted_syms'.  */
+  long min = 0;
+  long max = sorted_symcount;
+  long thisplace;
+
+  if (sorted_symcount < 1)
+    return NULL;
+
+  /* Perform a binary search looking for the closest symbol to the
+     required value.  We are searching the range (min, max].  */
+  while (min + 1 < max)
+    {
+      asymbol *sym;
+
+      thisplace = (max + min) / 2;
+      sym = sorted_syms[thisplace];
+
+      if (bfd_asymbol_value (sym) > vma)
+       max = thisplace;
+      else if (bfd_asymbol_value (sym) < vma)
+       min = thisplace;
+      else
+       {
+         min = thisplace;
+         break;
+       }
+    }
+
+  /* The symbol we want is now in min, the low end of the range we
+     were searching.  If there are several symbols with the same
+     value, we want the first one.  */
+  thisplace = min;
+  while (thisplace > 0
+        && (bfd_asymbol_value (sorted_syms[thisplace])
+            == bfd_asymbol_value (sorted_syms[thisplace - 1])))
+    --thisplace;
+
+  /* If the file is relocateable, and the symbol could be from this
+     section, prefer a symbol from this section over symbols from
+     others, even if the other symbol's value might be closer.
+       
+     Note that this may be wrong for some symbol references if the
+     sections have overlapping memory ranges, but in that case there's
+     no way to tell what's desired without looking at the relocation
+     table.  */
+
+  if (sorted_syms[thisplace]->section != sec
+      && (require_sec
+         || ((abfd->flags & HAS_RELOC) != 0
+             && vma >= bfd_get_section_vma (abfd, sec)
+             && vma < (bfd_get_section_vma (abfd, sec)
+                       + bfd_section_size (abfd, sec)))))
+    {
+      long i;
+
+      for (i = thisplace + 1; i < sorted_symcount; i++)
+       {
+         if (bfd_asymbol_value (sorted_syms[i])
+             != bfd_asymbol_value (sorted_syms[thisplace]))
+           break;
+       }
+      --i;
+      for (; i >= 0; i--)
+       {
+         if (sorted_syms[i]->section == sec
+             && (i == 0
+                 || sorted_syms[i - 1]->section != sec
+                 || (bfd_asymbol_value (sorted_syms[i])
+                     != bfd_asymbol_value (sorted_syms[i - 1]))))
+           {
+             thisplace = i;
+             break;
+           }
+       }
+
+      if (sorted_syms[thisplace]->section != sec)
+       {
+         /* We didn't find a good symbol with a smaller value.
+            Look for one with a larger value.  */
+         for (i = thisplace + 1; i < sorted_symcount; i++)
+           {
+             if (sorted_syms[i]->section == sec)
+               {
+                 thisplace = i;
+                 break;
+               }
+           }
+       }
+
+      if (sorted_syms[thisplace]->section != sec
+         && (require_sec
+             || ((abfd->flags & HAS_RELOC) != 0
+                 && vma >= bfd_get_section_vma (abfd, sec)
+                 && vma < (bfd_get_section_vma (abfd, sec)
+                           + bfd_section_size (abfd, sec)))))
+       {
+         /* There is no suitable symbol.  */
+         return NULL;
+       }
+    }
+
+  if (place != NULL)
+    *place = thisplace;
+
+  return sorted_syms[thisplace];
+}
+
+/* Print an address to INFO symbolically.  */
+
+static void
+objdump_print_addr_with_sym (abfd, sec, sym, vma, info, skip_zeroes)
+     bfd *abfd;
+     asection *sec;
+     asymbol *sym;
+     bfd_vma vma;
+     struct disassemble_info *info;
+     boolean skip_zeroes;
+{
+  objdump_print_value (vma, info, skip_zeroes);
+
+  if (sym == NULL)
+    {
+      bfd_vma secaddr;
+
+      (*info->fprintf_func) (info->stream, " <%s",
+                            bfd_get_section_name (abfd, sec));
+      secaddr = bfd_get_section_vma (abfd, sec);
+      if (vma < secaddr)
+       {
+         (*info->fprintf_func) (info->stream, "-0x");
+         objdump_print_value (secaddr - vma, info, true);
+       }
+      else if (vma > secaddr)
+       {
+         (*info->fprintf_func) (info->stream, "+0x");
+         objdump_print_value (vma - secaddr, info, true);
+       }
+      (*info->fprintf_func) (info->stream, ">");
+    }
+  else
+    {
+      (*info->fprintf_func) (info->stream, " <");
+      objdump_print_symname (abfd, info, sym);
+      if (bfd_asymbol_value (sym) > vma)
+       {
+         (*info->fprintf_func) (info->stream, "-0x");
+         objdump_print_value (bfd_asymbol_value (sym) - vma, info, true);
+       }
+      else if (vma > bfd_asymbol_value (sym))
+       {
+         (*info->fprintf_func) (info->stream, "+0x");
+         objdump_print_value (vma - bfd_asymbol_value (sym), info, true);
+       }
+      (*info->fprintf_func) (info->stream, ">");
+    }
+}
+
+/* Print VMA to INFO, symbolically if possible.  If SKIP_ZEROES is
+   true, don't output leading zeroes.  */
+
+static void
+objdump_print_addr (vma, info, skip_zeroes)
+     bfd_vma vma;
+     struct disassemble_info *info;
+     boolean skip_zeroes;
+{
+  struct objdump_disasm_info *aux;
+  asymbol *sym;
+
+  if (sorted_symcount < 1)
+    {
+      (*info->fprintf_func) (info->stream, "0x");
+      objdump_print_value (vma, info, skip_zeroes);
+      return;
+    }
+
+  aux = (struct objdump_disasm_info *) info->application_data;
+  sym = find_symbol_for_address (aux->abfd, aux->sec, vma, aux->require_sec,
+                                (long *) NULL);
+  objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info,
+                              skip_zeroes);
+}
+
+/* Print VMA to INFO.  This function is passed to the disassembler
+   routine.  */
+
+static void
+objdump_print_address (vma, info)
+     bfd_vma vma;
+     struct disassemble_info *info;
+{
+  objdump_print_addr (vma, info, ! prefix_addresses);
+}
+
+/* Determine of the given address has a symbol associated with it.  */
+
+static int
+objdump_symbol_at_address (vma, info)
+     bfd_vma vma;
+     struct disassemble_info * info;
+{
+  struct objdump_disasm_info * aux;
+  asymbol * sym;
+
+  /* No symbols - do not bother checking.  */
+  if (sorted_symcount < 1)
+    return 0;
+
+  aux = (struct objdump_disasm_info *) info->application_data;
+  sym = find_symbol_for_address (aux->abfd, aux->sec, vma, aux->require_sec,
+                                (long *) NULL);
+
+  return (sym != NULL && (bfd_asymbol_value (sym) == vma));
+}
+
+/* Hold the last function name and the last line number we displayed
+   in a disassembly.  */
+
+static char *prev_functionname;
+static unsigned int prev_line;
+
+/* We keep a list of all files that we have seen when doing a
+   dissassembly with source, so that we know how much of the file to
+   display.  This can be important for inlined functions.  */
+
+struct print_file_list
+{
+  struct print_file_list *next;
+  char *filename;
+  unsigned int line;
+  FILE *f;
+};
+
+static struct print_file_list *print_files;
+
+/* The number of preceding context lines to show when we start
+   displaying a file for the first time.  */
+
+#define SHOW_PRECEDING_CONTEXT_LINES (5)
+
+/* Skip ahead to a given line in a file, optionally printing each
+   line.  */
+
+static void
+skip_to_line PARAMS ((struct print_file_list *, unsigned int, boolean));
+
+static void
+skip_to_line (p, line, show)
+     struct print_file_list *p;
+     unsigned int line;
+     boolean show;
+{
+  while (p->line < line)
+    {
+      char buf[100];
+
+      if (fgets (buf, sizeof buf, p->f) == NULL)
+       {
+         fclose (p->f);
+         p->f = NULL;
+         break;
+       }
+
+      if (show)
+       printf ("%s", buf);
+
+      if (strchr (buf, '\n') != NULL)
+       ++p->line;
+    }
+}  
+
+/* Show the line number, or the source line, in a dissassembly
+   listing.  */
+
+static void
+show_line (abfd, section, off)
+     bfd *abfd;
+     asection *section;
+     bfd_vma off;
+{
+  CONST char *filename;
+  CONST char *functionname;
+  unsigned int line;
+
+  if (! with_line_numbers && ! with_source_code)
+    return;
+
+  if (! bfd_find_nearest_line (abfd, section, syms, off, &filename,
+                              &functionname, &line))
+    return;
+
+  if (filename != NULL && *filename == '\0')
+    filename = NULL;
+  if (functionname != NULL && *functionname == '\0')
+    functionname = NULL;
+
+  if (with_line_numbers)
+    {
+      if (functionname != NULL
+         && (prev_functionname == NULL
+             || strcmp (functionname, prev_functionname) != 0))
+       printf ("%s():\n", functionname);
+      if (line > 0 && line != prev_line)
+       printf ("%s:%u\n", filename == NULL ? "???" : filename, line);
+    }
+
+  if (with_source_code
+      && filename != NULL
+      && line > 0)
+    {
+      struct print_file_list **pp, *p;
+
+      for (pp = &print_files; *pp != NULL; pp = &(*pp)->next)
+       if (strcmp ((*pp)->filename, filename) == 0)
+         break;
+      p = *pp;
+
+      if (p != NULL)
+       {
+         if (p != print_files)
+           {
+             int l;
+
+             /* We have reencountered a file name which we saw
+                earlier.  This implies that either we are dumping out
+                code from an included file, or the same file was
+                linked in more than once.  There are two common cases
+                of an included file: inline functions in a header
+                file, and a bison or flex skeleton file.  In the
+                former case we want to just start printing (but we
+                back up a few lines to give context); in the latter
+                case we want to continue from where we left off.  I
+                can't think of a good way to distinguish the cases,
+                so I used a heuristic based on the file name.  */
+             if (strcmp (p->filename + strlen (p->filename) - 2, ".h") != 0)
+               l = p->line;
+             else
+               {
+                 l = line - SHOW_PRECEDING_CONTEXT_LINES;
+                 if (l <= 0)
+                   l = 1;
+               }
+
+             if (p->f == NULL)
+               {
+                 p->f = fopen (p->filename, "r");
+                 p->line = 0;
+               }
+             if (p->f != NULL)
+               skip_to_line (p, l, false);
+
+             if (print_files->f != NULL)
+               {
+                 fclose (print_files->f);
+                 print_files->f = NULL;
+               }
+           }
+
+         if (p->f != NULL)
+           {
+             skip_to_line (p, line, true);
+             *pp = p->next;
+             p->next = print_files;
+             print_files = p;
+           }
+       }
+      else
+       {
+         FILE *f;
+
+         f = fopen (filename, "r");
+         if (f != NULL)
+           {
+             int l;
+
+             p = ((struct print_file_list *)
+                  xmalloc (sizeof (struct print_file_list)));
+             p->filename = xmalloc (strlen (filename) + 1);
+             strcpy (p->filename, filename);
+             p->line = 0;
+             p->f = f;
+
+             if (print_files != NULL && print_files->f != NULL)
+               {
+                 fclose (print_files->f);
+                 print_files->f = NULL;
+               }
+             p->next = print_files;
+             print_files = p;
+
+             l = line - SHOW_PRECEDING_CONTEXT_LINES;
+             if (l <= 0)
+               l = 1;
+             skip_to_line (p, l, false);
+             if (p->f != NULL)
+               skip_to_line (p, line, true);
+           }
+       }
+    }
+
+  if (functionname != NULL
+      && (prev_functionname == NULL
+         || strcmp (functionname, prev_functionname) != 0))
+    {
+      if (prev_functionname != NULL)
+       free (prev_functionname);
+      prev_functionname = xmalloc (strlen (functionname) + 1);
+      strcpy (prev_functionname, functionname);
+    }
+
+  if (line > 0 && line != prev_line)
+    prev_line = line;
+}
+
+/* Pseudo FILE object for strings.  */
+typedef struct
+{
+  char *buffer;
+  size_t size;
+  char *current;
+} SFILE;
+
+/* sprintf to a "stream" */
+
+static int
+#ifdef ANSI_PROTOTYPES
+objdump_sprintf (SFILE *f, const char *format, ...)
+#else
+objdump_sprintf (va_alist)
+     va_dcl
+#endif
+{
+#ifndef ANSI_PROTOTYPES
+  SFILE *f;
+  const char *format;
+#endif
+  char *buf;
+  va_list args;
+  size_t n;
+
+#ifdef ANSI_PROTOTYPES
+  va_start (args, format);
+#else
+  va_start (args);
+  f = va_arg (args, SFILE *);
+  format = va_arg (args, const char *);
+#endif
+
+  vasprintf (&buf, format, args);
+
+  va_end (args);
+
+  if (buf == NULL)
+    {
+      fprintf (stderr, _("Out of virtual memory\n"));
+      exit (1);
+    }
+
+  n = strlen (buf);
+
+  while ((f->buffer + f->size) - f->current < n + 1)
+    {
+      size_t curroff;
+
+      curroff = f->current - f->buffer;
+      f->size *= 2;
+      f->buffer = xrealloc (f->buffer, f->size);
+      f->current = f->buffer + curroff;
+    }
+
+  memcpy (f->current, buf, n);
+  f->current += n;
+  f->current[0] = '\0';
+
+  free (buf);
+
+  return n;
+}
+
+/* The number of zeroes we want to see before we start skipping them.
+   The number is arbitrarily chosen.  */
+
+#define SKIP_ZEROES (8)
+
+/* The number of zeroes to skip at the end of a section.  If the
+   number of zeroes at the end is between SKIP_ZEROES_AT_END and
+   SKIP_ZEROES, they will be disassembled.  If there are fewer than
+   SKIP_ZEROES_AT_END, they will be skipped.  This is a heuristic
+   attempt to avoid disassembling zeroes inserted by section
+   alignment.  */
+
+#define SKIP_ZEROES_AT_END (3)
+
+/* Disassemble some data in memory between given values.  */
+
+static void
+disassemble_bytes (info, disassemble_fn, insns, data, start, stop, relppp,
+                  relppend)
+     struct disassemble_info *info;
+     disassembler_ftype disassemble_fn;
+     boolean insns;
+     bfd_byte *data;
+     bfd_vma start;
+     bfd_vma stop;
+     arelent ***relppp;
+     arelent **relppend;
+{
+  struct objdump_disasm_info *aux;
+  asection *section;
+  int bytes_per_line;
+  boolean done_dot;
+  int skip_addr_chars;
+  bfd_vma i;
+
+  aux = (struct objdump_disasm_info *) info->application_data;
+  section = aux->sec;
+
+  if (insns)
+    bytes_per_line = 4;
+  else
+    bytes_per_line = 16;
+
+  /* Figure out how many characters to skip at the start of an
+     address, to make the disassembly look nicer.  We discard leading
+     zeroes in chunks of 4, ensuring that there is always a leading
+     zero remaining.  */
+  skip_addr_chars = 0;
+  if (! prefix_addresses)
+    {
+      char buf[30];
+      char *s;
+
+      sprintf_vma (buf,
+                  section->vma + bfd_section_size (section->owner, section));
+      s = buf;
+      while (s[0] == '0' && s[1] == '0' && s[2] == '0' && s[3] == '0'
+            && s[4] == '0')
+       {
+         skip_addr_chars += 4;
+         s += 4;
+       }
+    }
+
+  info->insn_info_valid = 0;
+
+  done_dot = false;
+  i = start;
+  while (i < stop)
+    {
+      bfd_vma z;
+      int bytes = 0;
+      boolean need_nl = false;
+
+      /* If we see more than SKIP_ZEROES bytes of zeroes, we just
+         print `...'.  */
+      for (z = i; z < stop; z++)
+       if (data[z] != 0)
+         break;
+      if (! disassemble_zeroes
+         && (info->insn_info_valid == 0
+             || info->branch_delay_insns == 0)
+         && (z - i >= SKIP_ZEROES
+             || (z == stop && z - i < SKIP_ZEROES_AT_END)))
+       {
+         printf ("\t...\n");
+
+         /* If there are more nonzero bytes to follow, we only skip
+             zeroes in multiples of 4, to try to avoid running over
+             the start of an instruction which happens to start with
+             zero.  */
+         if (z != stop)
+           z = i + ((z - i) &~ 3);
+
+         bytes = z - i;
+       }
+      else
+       {
+         char buf[50];
+         SFILE sfile;
+         int bpc = 0;
+         int pb = 0;
+
+         done_dot = false;
+
+         if (with_line_numbers || with_source_code)
+           show_line (aux->abfd, section, i);
+
+         if (! prefix_addresses)
+           {
+             char *s;
+
+             sprintf_vma (buf, section->vma + i);
+             for (s = buf + skip_addr_chars; *s == '0'; s++)
+               *s = ' ';
+             if (*s == '\0')
+               *--s = '0';
+             printf ("%s:\t", buf + skip_addr_chars);
+           }
+         else
+           {
+             aux->require_sec = true;
+             objdump_print_address (section->vma + i, info);
+             aux->require_sec = false;
+             putchar (' ');
+           }
+
+         if (insns)
+           {
+             sfile.size = 120;
+             sfile.buffer = xmalloc (sfile.size);
+             sfile.current = sfile.buffer;
+             info->fprintf_func = (fprintf_ftype) objdump_sprintf;
+             info->stream = (FILE *) &sfile;
+             info->bytes_per_line = 0;
+             info->bytes_per_chunk = 0;
+
+             /* FIXME: This is wrong.  It tests the number of bytes
+                 in the last instruction, not the current one.  */
+             if (*relppp < relppend
+                 && (**relppp)->address >= i
+                 && (**relppp)->address < i + bytes)
+               info->flags = INSN_HAS_RELOC;
+             else
+               info->flags = 0;
+
+             bytes = (*disassemble_fn) (section->vma + i, info);
+             info->fprintf_func = (fprintf_ftype) fprintf;
+             info->stream = stdout;
+             if (info->bytes_per_line != 0)
+               bytes_per_line = info->bytes_per_line;
+             if (bytes < 0)
+               break;
+           }
+         else
+           {
+             long j;
+
+             bytes = bytes_per_line;
+             if (i + bytes > stop)
+               bytes = stop - i;
+
+             for (j = i; j < i + bytes; ++j)
+               {
+                 if (isprint (data[j]))
+                   buf[j - i] = data[j];
+                 else
+                   buf[j - i] = '.';
+               }
+             buf[j - i] = '\0';
+           }
+
+         if (prefix_addresses
+             ? show_raw_insn > 0
+             : show_raw_insn >= 0)
+           {
+             long j;
+
+             /* If ! prefix_addresses and ! wide_output, we print
+                 bytes_per_line bytes per line.  */
+             pb = bytes;
+             if (pb > bytes_per_line && ! prefix_addresses && ! wide_output)
+               pb = bytes_per_line;
+
+             if (info->bytes_per_chunk)
+               bpc = info->bytes_per_chunk;
+             else
+               bpc = 1;
+
+             for (j = i; j < i + pb; j += bpc)
+               {
+                 int k;
+                 if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE)
+                   {
+                     for (k = bpc - 1; k >= 0; k--)
+                       printf ("%02x", (unsigned) data[j + k]);
+                     putchar (' ');
+                   }
+                 else
+                   {
+                     for (k = 0; k < bpc; k++)
+                       printf ("%02x", (unsigned) data[j + k]);
+                     putchar (' ');
+                   }
+               }
+
+             for (; pb < bytes_per_line; pb += bpc)
+               {
+                 int k;
+
+                 for (k = 0; k < bpc; k++)
+                   printf ("  ");
+                 putchar (' ');
+               }
+
+             /* Separate raw data from instruction by extra space.  */
+             if (insns)
+               putchar ('\t');
+             else
+               printf ("    ");
+           }
+
+         if (! insns)
+           printf ("%s", buf);
+         else
+           {
+             printf ("%s", sfile.buffer);
+             free (sfile.buffer);
+           }
+
+         if (prefix_addresses
+             ? show_raw_insn > 0
+             : show_raw_insn >= 0)
+           {
+             while (pb < bytes)
+               {
+                 long j;
+                 char *s;
+
+                 putchar ('\n');
+                 j = i + pb;
+
+                 sprintf_vma (buf, section->vma + j);
+                 for (s = buf + skip_addr_chars; *s == '0'; s++)
+                   *s = ' ';
+                 if (*s == '\0')
+                   *--s = '0';
+                 printf ("%s:\t", buf + skip_addr_chars);
+
+                 pb += bytes_per_line;
+                 if (pb > bytes)
+                   pb = bytes;
+                 for (; j < i + pb; j += bpc)
+                   {
+                     int k;
+
+                     if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE)
+                       {
+                         for (k = bpc - 1; k >= 0; k--)
+                           printf ("%02x", (unsigned) data[j + k]);
+                         putchar (' ');
+                       }
+                     else
+                       {
+                         for (k = 0; k < bpc; k++)
+                           printf ("%02x", (unsigned) data[j + k]);
+                         putchar (' ');
+                       }
+                   }
+               }
+           }
+
+         if (!wide_output)
+           putchar ('\n');
+         else
+           need_nl = true;
+       }
+
+      if (dump_reloc_info
+         && (section->flags & SEC_RELOC) != 0)
+       {
+         while ((*relppp) < relppend
+                && ((**relppp)->address >= (bfd_vma) i
+                    && (**relppp)->address < (bfd_vma) i + bytes))
+           {
+             arelent *q;
+
+             q = **relppp;
+
+             if (wide_output)
+               putchar ('\t');
+             else
+               printf ("\t\t\t");
+
+             objdump_print_value (section->vma + q->address, info, true);
+
+             printf (": %s\t", q->howto->name);
+
+             if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL)
+               printf ("*unknown*");
+             else
+               {
+                 const char *sym_name;
+
+                 sym_name = bfd_asymbol_name (*q->sym_ptr_ptr);
+                 if (sym_name != NULL && *sym_name != '\0')
+                   objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr);
+                 else
+                   {
+                     asection *sym_sec;
+
+                     sym_sec = bfd_get_section (*q->sym_ptr_ptr);
+                     sym_name = bfd_get_section_name (aux->abfd, sym_sec);
+                     if (sym_name == NULL || *sym_name == '\0')
+                       sym_name = "*unknown*";
+                     printf ("%s", sym_name);
+                   }
+               }
+
+             if (q->addend)
+               {
+                 printf ("+0x");
+                 objdump_print_value (q->addend, info, true);
+               }
+
+             printf ("\n");
+             need_nl = false;
+             ++(*relppp);
+           }
+       }
+
+      if (need_nl)
+       printf ("\n");
+
+      i += bytes;
+    }
+}
+
+/* Disassemble the contents of an object file.  */
+
+static void
+disassemble_data (abfd)
+     bfd *abfd;
+{
+  long i;
+  disassembler_ftype disassemble_fn;
+  struct disassemble_info disasm_info;
+  struct objdump_disasm_info aux;
+  asection *section;
+
+  print_files = NULL;
+  prev_functionname = NULL;
+  prev_line = -1;
+
+  /* We make a copy of syms to sort.  We don't want to sort syms
+     because that will screw up the relocs.  */
+  sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
+  memcpy (sorted_syms, syms, symcount * sizeof (asymbol *));
+
+  sorted_symcount = remove_useless_symbols (sorted_syms, symcount);
+
+  /* Sort the symbols into section and symbol order */
+  qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols);
+
+  INIT_DISASSEMBLE_INFO(disasm_info, stdout, fprintf);
+  disasm_info.application_data = (PTR) &aux;
+  aux.abfd = abfd;
+  aux.require_sec = false;
+  disasm_info.print_address_func = objdump_print_address;
+  disasm_info.symbol_at_address_func = objdump_symbol_at_address;
+
+  if (machine != (char *) NULL)
+    {
+      const bfd_arch_info_type *info = bfd_scan_arch (machine);
+      if (info == NULL)
+       {
+         fprintf (stderr, _("%s: Can't use supplied machine %s\n"),
+                  program_name,
+                  machine);
+         exit (1);
+       }
+      abfd->arch_info = info;
+    }
+
+  if (endian != BFD_ENDIAN_UNKNOWN)
+    {
+      struct bfd_target *xvec;
+
+      xvec = (struct bfd_target *) xmalloc (sizeof (struct bfd_target));
+      memcpy (xvec, abfd->xvec, sizeof (struct bfd_target));
+      xvec->byteorder = endian;
+      abfd->xvec = xvec;
+    }
+
+  disassemble_fn = disassembler (abfd);
+  if (!disassemble_fn)
+    {
+      fprintf (stderr, _("%s: Can't disassemble for architecture %s\n"),
+              program_name,
+              bfd_printable_arch_mach (bfd_get_arch (abfd), 0));
+      return;
+    }
+
+  disasm_info.flavour = bfd_get_flavour (abfd);
+  disasm_info.arch = bfd_get_arch (abfd);
+  disasm_info.mach = bfd_get_mach (abfd);
+  if (bfd_big_endian (abfd))
+    disasm_info.endian = BFD_ENDIAN_BIG;
+  else if (bfd_little_endian (abfd))
+    disasm_info.endian = BFD_ENDIAN_LITTLE;
+  else
+    /* ??? Aborting here seems too drastic.  We could default to big or little
+       instead.  */
+    disasm_info.endian = BFD_ENDIAN_UNKNOWN;
+
+  for (section = abfd->sections;
+       section != (asection *) NULL;
+       section = section->next)
+    {
+      bfd_byte *data = NULL;
+      bfd_size_type datasize = 0;
+      arelent **relbuf = NULL;
+      arelent **relpp = NULL;
+      arelent **relppend = NULL;
+      long stop;
+      asymbol *sym = NULL;
+      long place = 0;
+
+      if ((section->flags & SEC_LOAD) == 0
+         || (! disassemble_all
+             && only == NULL
+             && (section->flags & SEC_CODE) == 0))
+       continue;
+      if (only != (char *) NULL && strcmp (only, section->name) != 0)
+       continue;
+
+      if (dump_reloc_info
+         && (section->flags & SEC_RELOC) != 0)
+       {
+         long relsize;
+
+         relsize = bfd_get_reloc_upper_bound (abfd, section);
+         if (relsize < 0)
+           bfd_fatal (bfd_get_filename (abfd));
+
+         if (relsize > 0)
+           {
+             long relcount;
+
+             relbuf = (arelent **) xmalloc (relsize);
+             relcount = bfd_canonicalize_reloc (abfd, section, relbuf, syms);
+             if (relcount < 0)
+               bfd_fatal (bfd_get_filename (abfd));
+
+             /* Sort the relocs by address.  */
+             qsort (relbuf, relcount, sizeof (arelent *), compare_relocs);
+
+             relpp = relbuf;
+             relppend = relpp + relcount;
+
+             /* Skip over the relocs belonging to addresses below the
+                start address.  */
+             if (start_address != (bfd_vma) -1)
+               {
+                 while (relpp < relppend
+                        && (*relpp)->address < start_address)
+                   ++relpp;
+               }
+           }
+       }
+
+      printf (_("Disassembly of section %s:\n"), section->name);
+
+      datasize = bfd_get_section_size_before_reloc (section);
+      if (datasize == 0)
+       continue;
+
+      data = (bfd_byte *) xmalloc ((size_t) datasize);
+
+      bfd_get_section_contents (abfd, section, data, 0, datasize);
+
+      aux.sec = section;
+      disasm_info.buffer = data;
+      disasm_info.buffer_vma = section->vma;
+      disasm_info.buffer_length = datasize;
+      if (start_address == (bfd_vma) -1
+         || start_address < disasm_info.buffer_vma)
+       i = 0;
+      else
+       i = start_address - disasm_info.buffer_vma;
+      if (stop_address == (bfd_vma) -1)
+       stop = datasize;
+      else
+       {
+         if (stop_address < disasm_info.buffer_vma)
+           stop = 0;
+         else
+           stop = stop_address - disasm_info.buffer_vma;
+         if (stop > disasm_info.buffer_length)
+           stop = disasm_info.buffer_length;
+       }
+
+      sym = find_symbol_for_address (abfd, section, section->vma + i,
+                                    true, &place);
+
+      while (i < stop)
+       {
+         asymbol *nextsym;
+         long nextstop;
+         boolean insns;
+         
+         if (sym != NULL && bfd_asymbol_value (sym) <= section->vma + i)
+           {
+             int x;
+
+             for (x = place;
+                  (x < sorted_symcount
+                   && bfd_asymbol_value (sorted_syms[x]) <= section->vma + i);
+                  ++x)
+               continue;
+             disasm_info.symbols = & sorted_syms[place];
+             disasm_info.num_symbols = x - place;
+           }
+         else
+           disasm_info.symbols = NULL;
+
+         if (! prefix_addresses)
+           {
+             printf ("\n");
+             objdump_print_addr_with_sym (abfd, section, sym,
+                                          section->vma + i,
+                                          &disasm_info,
+                                          false);
+             printf (":\n");
+           }
+         
+         if (sym != NULL && bfd_asymbol_value (sym) > section->vma + i)
+           nextsym = sym;
+         else if (sym == NULL)
+           nextsym = NULL;
+         else
+           {
+             while (place < sorted_symcount
+                    /* ??? Why the test for != section?  */
+                    && (sorted_syms[place]->section != section
+                        || (bfd_asymbol_value (sorted_syms[place])
+                            <= bfd_asymbol_value (sym))))
+               ++place;
+             if (place >= sorted_symcount)
+               nextsym = NULL;
+             else
+               nextsym = sorted_syms[place];
+           }
+         
+         if (sym != NULL && bfd_asymbol_value (sym) > section->vma + i)
+           {
+             nextstop = bfd_asymbol_value (sym) - section->vma;
+             if (nextstop > stop)
+               nextstop = stop;
+           }
+         else if (nextsym == NULL)
+           nextstop = stop;
+         else
+           {
+             nextstop = bfd_asymbol_value (nextsym) - section->vma;
+             if (nextstop > stop)
+               nextstop = stop;
+           }
+         
+         /* If a symbol is explicitly marked as being an object
+            rather than a function, just dump the bytes without
+            disassembling them.  */
+         if (disassemble_all
+             || sym == NULL
+             || bfd_asymbol_value (sym) > section->vma + i
+             || ((sym->flags & BSF_OBJECT) == 0
+                 && (strstr (bfd_asymbol_name (sym), "gnu_compiled")
+                     == NULL)
+                 && (strstr (bfd_asymbol_name (sym), "gcc2_compiled")
+                     == NULL))
+             || (sym->flags & BSF_FUNCTION) != 0)
+           insns = true;
+         else
+           insns = false;
+         
+         disassemble_bytes (&disasm_info, disassemble_fn, insns, data, i,
+                            nextstop, &relpp, relppend);
+         
+         i = nextstop;
+         sym = nextsym;
+       }
+      
+      free (data);
+      if (relbuf != NULL)
+       free (relbuf);
+    }
+  free (sorted_syms);
+}
+\f
+
+/* Define a table of stab values and print-strings.  We wish the initializer
+   could be a direct-mapped table, but instead we build one the first
+   time we need it.  */
+
+static void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name,
+                                       char *strsect_name));
+
+/* Dump the stabs sections from an object file that has a section that
+   uses Sun stabs encoding.  */
+
+static void
+dump_stabs (abfd)
+     bfd *abfd;
+{
+  dump_section_stabs (abfd, ".stab", ".stabstr");
+  dump_section_stabs (abfd, ".stab.excl", ".stab.exclstr");
+  dump_section_stabs (abfd, ".stab.index", ".stab.indexstr");
+  dump_section_stabs (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$");
+}
+
+static bfd_byte *stabs;
+static bfd_size_type stab_size;
+
+static char *strtab;
+static bfd_size_type stabstr_size;
+
+/* Read ABFD's stabs section STABSECT_NAME into `stabs'
+   and string table section STRSECT_NAME into `strtab'.
+   If the section exists and was read, allocate the space and return true.
+   Otherwise return false.  */
+
+static boolean
+read_section_stabs (abfd, stabsect_name, strsect_name)
+     bfd *abfd;
+     const char *stabsect_name;
+     const char *strsect_name;
+{
+  asection *stabsect, *stabstrsect;
+
+  stabsect = bfd_get_section_by_name (abfd, stabsect_name);
+  if (0 == stabsect)
+    {
+      printf (_("No %s section present\n\n"), stabsect_name);
+      return false;
+    }
+
+  stabstrsect = bfd_get_section_by_name (abfd, strsect_name);
+  if (0 == stabstrsect)
+    {
+      fprintf (stderr, _("%s: %s has no %s section\n"), program_name,
+              bfd_get_filename (abfd), strsect_name);
+      return false;
+    }
+  stab_size    = bfd_section_size (abfd, stabsect);
+  stabstr_size = bfd_section_size (abfd, stabstrsect);
+
+  stabs  = (bfd_byte *) xmalloc (stab_size);
+  strtab = (char *) xmalloc (stabstr_size);
+  
+  if (! bfd_get_section_contents (abfd, stabsect, (PTR) stabs, 0, stab_size))
+    {
+      fprintf (stderr, _("%s: Reading %s section of %s failed: %s\n"),
+              program_name, stabsect_name, bfd_get_filename (abfd),
+              bfd_errmsg (bfd_get_error ()));
+      free (stabs);
+      free (strtab);
+      return false;
+    }
+
+  if (! bfd_get_section_contents (abfd, stabstrsect, (PTR) strtab, 0,
+                                 stabstr_size))
+    {
+      fprintf (stderr, _("%s: Reading %s section of %s failed: %s\n"),
+              program_name, strsect_name, bfd_get_filename (abfd),
+              bfd_errmsg (bfd_get_error ()));
+      free (stabs);
+      free (strtab);
+      return false;
+    }
+
+  return true;
+}
+
+/* Stabs entries use a 12 byte format:
+     4 byte string table index
+     1 byte stab type
+     1 byte stab other field
+     2 byte stab desc field
+     4 byte stab value
+   FIXME: This will have to change for a 64 bit object format.  */
+
+#define STRDXOFF (0)
+#define TYPEOFF (4)
+#define OTHEROFF (5)
+#define DESCOFF (6)
+#define VALOFF (8)
+#define STABSIZE (12)
+
+/* Print ABFD's stabs section STABSECT_NAME (in `stabs'),
+   using string table section STRSECT_NAME (in `strtab').  */
+
+static void
+print_section_stabs (abfd, stabsect_name, strsect_name)
+     bfd *abfd;
+     const char *stabsect_name;
+     const char *strsect_name;
+{
+  int i;
+  unsigned file_string_table_offset = 0, next_file_string_table_offset = 0;
+  bfd_byte *stabp, *stabs_end;
+
+  stabp = stabs;
+  stabs_end = stabp + stab_size;
+
+  printf (_("Contents of %s section:\n\n"), stabsect_name);
+  printf ("Symnum n_type n_othr n_desc n_value  n_strx String\n");
+
+  /* Loop through all symbols and print them.
+
+     We start the index at -1 because there is a dummy symbol on
+     the front of stabs-in-{coff,elf} sections that supplies sizes.  */
+
+  for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++)
+    {
+      const char *name;
+      unsigned long strx;
+      unsigned char type, other;
+      unsigned short desc;
+      bfd_vma value;
+
+      strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);
+      type = bfd_h_get_8 (abfd, stabp + TYPEOFF);
+      other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
+      desc = bfd_h_get_16 (abfd, stabp + DESCOFF);
+      value = bfd_h_get_32 (abfd, stabp + VALOFF);
+
+      printf ("\n%-6d ", i);
+      /* Either print the stab name, or, if unnamed, print its number
+        again (makes consistent formatting for tools like awk). */
+      name = bfd_get_stab_name (type);
+      if (name != NULL)
+       printf ("%-6s", name);
+      else if (type == N_UNDF)
+       printf ("HdrSym");
+      else
+       printf ("%-6d", type);
+      printf (" %-6d %-6d ", other, desc);
+      printf_vma (value);
+      printf (" %-6lu", strx);
+
+      /* Symbols with type == 0 (N_UNDF) specify the length of the
+        string table associated with this file.  We use that info
+        to know how to relocate the *next* file's string table indices.  */
+
+      if (type == N_UNDF)
+       {
+         file_string_table_offset = next_file_string_table_offset;
+         next_file_string_table_offset += value;
+       }
+      else
+       {
+         /* Using the (possibly updated) string table offset, print the
+            string (if any) associated with this symbol.  */
+
+         if ((strx + file_string_table_offset) < stabstr_size)
+           printf (" %s", &strtab[strx + file_string_table_offset]);
+         else
+           printf (" *");
+       }
+    }
+  printf ("\n\n");
+}
+
+static void
+dump_section_stabs (abfd, stabsect_name, strsect_name)
+     bfd *abfd;
+     char *stabsect_name;
+     char *strsect_name;
+{
+  asection *s;
+
+  /* Check for section names for which stabsect_name is a prefix, to
+     handle .stab0, etc.  */
+  for (s = abfd->sections;
+       s != NULL;
+       s = s->next)
+    {
+      int len;
+
+      len = strlen (stabsect_name);
+
+      /* If the prefix matches, and the files section name ends with a
+        nul or a digit, then we match.  I.e., we want either an exact
+        match or a section followed by a number.  */
+      if (strncmp (stabsect_name, s->name, len) == 0
+         && (s->name[len] == '\000'
+             || isdigit ((unsigned char) s->name[len])))
+       {
+         if (read_section_stabs (abfd, s->name, strsect_name))
+           {
+             print_section_stabs (abfd, s->name, strsect_name);
+             free (stabs);
+             free (strtab);
+           }
+       }
+    }
+}
+\f
+static void
+dump_bfd_header (abfd)
+     bfd *abfd;
+{
+  char *comma = "";
+
+  printf (_("architecture: %s, "),
+         bfd_printable_arch_mach (bfd_get_arch (abfd),
+                                  bfd_get_mach (abfd)));
+  printf (_("flags 0x%08x:\n"), abfd->flags);
+
+#define PF(x, y)    if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}
+  PF (HAS_RELOC, "HAS_RELOC");
+  PF (EXEC_P, "EXEC_P");
+  PF (HAS_LINENO, "HAS_LINENO");
+  PF (HAS_DEBUG, "HAS_DEBUG");
+  PF (HAS_SYMS, "HAS_SYMS");
+  PF (HAS_LOCALS, "HAS_LOCALS");
+  PF (DYNAMIC, "DYNAMIC");
+  PF (WP_TEXT, "WP_TEXT");
+  PF (D_PAGED, "D_PAGED");
+  PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");
+  printf (_("\nstart address 0x"));
+  printf_vma (abfd->start_address);
+  printf ("\n");
+}
+\f
+static void
+dump_bfd_private_header (abfd)
+bfd *abfd;
+{
+  bfd_print_private_bfd_data (abfd, stdout);
+}
+
+static void
+display_bfd (abfd)
+     bfd *abfd;
+{
+  char **matching;
+
+  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
+    {
+      bfd_nonfatal (bfd_get_filename (abfd));
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      return;
+    }
+
+  /* If we are adjusting section VMA's, change them all now.  Changing
+     the BFD information is a hack.  However, we must do it, or
+     bfd_find_nearest_line will not do the right thing.  */
+  if (adjust_section_vma != 0)
+    {
+      asection *s;
+
+      for (s = abfd->sections; s != NULL; s = s->next)
+       {
+         s->vma += adjust_section_vma;
+         s->lma += adjust_section_vma;
+       }
+    }
+
+  printf (_("\n%s:     file format %s\n"), bfd_get_filename (abfd),
+         abfd->xvec->name);
+  if (dump_ar_hdrs)
+    print_arelt_descr (stdout, abfd, true);
+  if (dump_file_header)
+    dump_bfd_header (abfd);
+  if (dump_private_headers)
+    dump_bfd_private_header (abfd);
+  putchar ('\n');
+  if (dump_section_headers)
+    dump_headers (abfd);
+  if (dump_symtab || dump_reloc_info || disassemble || dump_debugging)
+    {
+      syms = slurp_symtab (abfd);
+    }
+  if (dump_dynamic_symtab || dump_dynamic_reloc_info)
+    {
+      dynsyms = slurp_dynamic_symtab (abfd);
+    }
+  if (dump_symtab)
+    dump_symbols (abfd, false);
+  if (dump_dynamic_symtab)
+    dump_symbols (abfd, true);
+  if (dump_stab_section_info)
+    dump_stabs (abfd);
+  if (dump_reloc_info && ! disassemble)
+    dump_relocs (abfd);
+  if (dump_dynamic_reloc_info)
+    dump_dynamic_relocs (abfd);
+  if (dump_section_contents)
+    dump_data (abfd);
+  if (disassemble)
+    disassemble_data (abfd);
+  if (dump_debugging)
+    {
+      PTR dhandle;
+
+      dhandle = read_debugging_info (abfd, syms, symcount);
+      if (dhandle != NULL)
+       {
+         if (! print_debugging_info (stdout, dhandle))
+           fprintf (stderr, _("%s: printing debugging information failed\n"),
+                    bfd_get_filename (abfd));
+       }
+    }
+  if (syms)
+    {
+      free (syms);
+      syms = NULL;
+    }
+  if (dynsyms)
+    {
+      free (dynsyms);
+      dynsyms = NULL;
+    }
+}
+
+static void
+display_file (filename, target)
+     char *filename;
+     char *target;
+{
+  bfd *file, *arfile = (bfd *) NULL;
+
+  file = bfd_openr (filename, target);
+  if (file == NULL)
+    {
+      bfd_nonfatal (filename);
+      return;
+    }
+
+  if (bfd_check_format (file, bfd_archive) == true)
+    {
+      bfd *last_arfile = NULL;
+
+      printf (_("In archive %s:\n"), bfd_get_filename (file));
+      for (;;)
+       {
+         bfd_set_error (bfd_error_no_error);
+
+         arfile = bfd_openr_next_archived_file (file, arfile);
+         if (arfile == NULL)
+           {
+             if (bfd_get_error () != bfd_error_no_more_archived_files)
+               {
+                 bfd_nonfatal (bfd_get_filename (file));
+               }
+             break;
+           }
+
+         display_bfd (arfile);
+
+         if (last_arfile != NULL)
+           bfd_close (last_arfile);
+         last_arfile = arfile;
+       }
+
+      if (last_arfile != NULL)
+       bfd_close (last_arfile);
+    }
+  else
+    display_bfd (file);
+
+  bfd_close (file);
+}
+\f
+/* Actually display the various requested regions */
+
+static void
+dump_data (abfd)
+     bfd *abfd;
+{
+  asection *section;
+  bfd_byte *data = 0;
+  bfd_size_type datasize = 0;
+  bfd_size_type i;
+  bfd_size_type start, stop;
+
+  for (section = abfd->sections; section != NULL; section =
+       section->next)
+    {
+      int onaline = 16;
+
+      if (only == (char *) NULL ||
+         strcmp (only, section->name) == 0)
+       {
+         if (section->flags & SEC_HAS_CONTENTS)
+           {
+             printf (_("Contents of section %s:\n"), section->name);
+
+             if (bfd_section_size (abfd, section) == 0)
+               continue;
+             data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section));
+             datasize = bfd_section_size (abfd, section);
+
+
+             bfd_get_section_contents (abfd, section, (PTR) data, 0, bfd_section_size (abfd, section));
+
+             if (start_address == (bfd_vma) -1
+                 || start_address < section->vma)
+               start = 0;
+             else
+               start = start_address - section->vma;
+             if (stop_address == (bfd_vma) -1)
+               stop = bfd_section_size (abfd, section);
+             else
+               {
+                 if (stop_address < section->vma)
+                   stop = 0;
+                 else
+                   stop = stop_address - section->vma;
+                 if (stop > bfd_section_size (abfd, section))
+                   stop = bfd_section_size (abfd, section);
+               }
+             for (i = start; i < stop; i += onaline)
+               {
+                 bfd_size_type j;
+
+                 printf (" %04lx ", (unsigned long int) (i + section->vma));
+                 for (j = i; j < i + onaline; j++)
+                   {
+                     if (j < stop)
+                       printf ("%02x", (unsigned) (data[j]));
+                     else
+                       printf ("  ");
+                     if ((j & 3) == 3)
+                       printf (" ");
+                   }
+
+                 printf (" ");
+                 for (j = i; j < i + onaline; j++)
+                   {
+                     if (j >= stop)
+                       printf (" ");
+                     else
+                       printf ("%c", isprint (data[j]) ? data[j] : '.');
+                   }
+                 putchar ('\n');
+               }
+             free (data);
+           }
+       }
+    }
+}
+
+/* Should perhaps share code and display with nm? */
+static void
+dump_symbols (abfd, dynamic)
+     bfd *abfd;
+     boolean dynamic;
+{
+  asymbol **current;
+  long max;
+  long count;
+
+  if (dynamic)
+    {
+      current = dynsyms;
+      max = dynsymcount;
+      if (max == 0)
+       return;
+      printf ("DYNAMIC SYMBOL TABLE:\n");
+    }
+  else
+    {
+      current = syms;
+      max = symcount;
+      if (max == 0)
+       return;
+      printf ("SYMBOL TABLE:\n");
+    }
+
+  for (count = 0; count < max; count++)
+    {
+      if (*current)
+       {
+         bfd *cur_bfd = bfd_asymbol_bfd (*current);
+
+         if (cur_bfd != NULL)
+           {
+             const char *name;
+             char *alloc;
+
+             name = bfd_asymbol_name (*current);
+             alloc = NULL;
+             if (do_demangle && name != NULL && *name != '\0')
+               {
+                 const char *n;
+
+                 /* If we want to demangle the name, we demangle it
+                     here, and temporarily clobber it while calling
+                     bfd_print_symbol.  FIXME: This is a gross hack.  */
+
+                 n = name;
+                 if (bfd_get_symbol_leading_char (cur_bfd) == *n)
+                   ++n;
+                 alloc = cplus_demangle (n, DMGL_ANSI | DMGL_PARAMS);
+                 if (alloc != NULL)
+                   (*current)->name = alloc;
+                 else
+                   (*current)->name = n;
+               }
+
+             bfd_print_symbol (cur_bfd, stdout, *current,
+                               bfd_print_symbol_all);
+
+             (*current)->name = name;
+             if (alloc != NULL)
+               free (alloc);
+
+             printf ("\n");
+           }
+       }
+      current++;
+    }
+  printf ("\n");
+  printf ("\n");
+}
+
+static void
+dump_relocs (abfd)
+     bfd *abfd;
+{
+  arelent **relpp;
+  long relcount;
+  asection *a;
+
+  for (a = abfd->sections; a != (asection *) NULL; a = a->next)
+    {
+      long relsize;
+
+      if (bfd_is_abs_section (a))
+       continue;
+      if (bfd_is_und_section (a))
+       continue;
+      if (bfd_is_com_section (a))
+       continue;
+
+      if (only)
+       {
+         if (strcmp (only, a->name))
+           continue;
+       }
+      else if ((a->flags & SEC_RELOC) == 0)
+       continue;
+
+      relsize = bfd_get_reloc_upper_bound (abfd, a);
+      if (relsize < 0)
+       bfd_fatal (bfd_get_filename (abfd));
+
+      printf ("RELOCATION RECORDS FOR [%s]:", a->name);
+
+      if (relsize == 0)
+       {
+         printf (" (none)\n\n");
+       }
+      else
+       {
+         relpp = (arelent **) xmalloc (relsize);
+         relcount = bfd_canonicalize_reloc (abfd, a, relpp, syms);
+         if (relcount < 0)
+           bfd_fatal (bfd_get_filename (abfd));
+         else if (relcount == 0)
+           {
+             printf (" (none)\n\n");
+           }
+         else
+           {
+             printf ("\n");
+             dump_reloc_set (abfd, a, relpp, relcount);
+             printf ("\n\n");
+           }
+         free (relpp);
+       }
+    }
+}
+
+static void
+dump_dynamic_relocs (abfd)
+     bfd *abfd;
+{
+  long relsize;
+  arelent **relpp;
+  long relcount;
+
+  relsize = bfd_get_dynamic_reloc_upper_bound (abfd);
+  if (relsize < 0)
+    bfd_fatal (bfd_get_filename (abfd));
+
+  printf ("DYNAMIC RELOCATION RECORDS");
+
+  if (relsize == 0)
+    {
+      printf (" (none)\n\n");
+    }
+  else
+    {
+      relpp = (arelent **) xmalloc (relsize);
+      relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms);
+      if (relcount < 0)
+       bfd_fatal (bfd_get_filename (abfd));
+      else if (relcount == 0)
+       {
+         printf (" (none)\n\n");
+       }
+      else
+       {
+         printf ("\n");
+         dump_reloc_set (abfd, (asection *) NULL, relpp, relcount);
+         printf ("\n\n");
+       }
+      free (relpp);
+    }
+}
+
+static void
+dump_reloc_set (abfd, sec, relpp, relcount)
+     bfd *abfd;
+     asection *sec;
+     arelent **relpp;
+     long relcount;
+{
+  arelent **p;
+  char *last_filename, *last_functionname;
+  unsigned int last_line;
+
+  /* Get column headers lined up reasonably.  */
+  {
+    static int width;
+    if (width == 0)
+      {
+       char buf[30];
+       sprintf_vma (buf, (bfd_vma) -1);
+       width = strlen (buf) - 7;
+      }
+    printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, "");
+  }
+
+  last_filename = NULL;
+  last_functionname = NULL;
+  last_line = 0;
+
+  for (p = relpp; relcount && *p != (arelent *) NULL; p++, relcount--)
+    {
+      arelent *q = *p;
+      const char *filename, *functionname;
+      unsigned int line;
+      const char *sym_name;
+      const char *section_name;
+
+      if (start_address != (bfd_vma) -1
+         && q->address < start_address)
+       continue;
+      if (stop_address != (bfd_vma) -1
+         && q->address > stop_address)
+       continue;
+
+      if (with_line_numbers
+         && sec != NULL
+         && bfd_find_nearest_line (abfd, sec, syms, q->address,
+                                   &filename, &functionname, &line))
+       {
+         if (functionname != NULL
+             && (last_functionname == NULL
+                 || strcmp (functionname, last_functionname) != 0))
+           {
+             printf ("%s():\n", functionname);
+             if (last_functionname != NULL)
+               free (last_functionname);
+             last_functionname = xstrdup (functionname);
+           }
+         if (line > 0
+             && (line != last_line
+                 || (filename != NULL
+                     && last_filename != NULL
+                     && strcmp (filename, last_filename) != 0)))
+           {
+             printf ("%s:%u\n", filename == NULL ? "???" : filename, line);
+             last_line = line;
+             if (last_filename != NULL)
+               free (last_filename);
+             if (filename == NULL)
+               last_filename = NULL;
+             else
+               last_filename = xstrdup (filename);
+           }
+       }
+
+      if (q->sym_ptr_ptr && *q->sym_ptr_ptr)
+       {
+         sym_name = (*(q->sym_ptr_ptr))->name;
+         section_name = (*(q->sym_ptr_ptr))->section->name;
+       }
+      else
+       {
+         sym_name = NULL;
+         section_name = NULL;
+       }
+      if (sym_name)
+       {
+         printf_vma (q->address);
+         printf (" %-16s  ", q->howto->name);
+         objdump_print_symname (abfd, (struct disassemble_info *) NULL,
+                                *q->sym_ptr_ptr);
+       }
+      else
+       {
+         if (section_name == (CONST char *) NULL)
+           section_name = "*unknown*";
+         printf_vma (q->address);
+         printf (" %-16s  [%s]",
+                 q->howto->name,
+                 section_name);
+       }
+      if (q->addend)
+       {
+         printf ("+0x");
+         printf_vma (q->addend);
+       }
+      printf ("\n");
+    }
+}
+\f
+/* The length of the longest architecture name + 1.  */
+#define LONGEST_ARCH sizeof("rs6000:6000")
+
+static const char *
+endian_string (endian)
+     enum bfd_endian endian;
+{
+  if (endian == BFD_ENDIAN_BIG)
+    return "big endian";
+  else if (endian == BFD_ENDIAN_LITTLE)
+    return "little endian";
+  else
+    return "endianness unknown";
+}
+
+/* List the targets that BFD is configured to support, each followed
+   by its endianness and the architectures it supports.  */
+
+static void
+display_target_list ()
+{
+  extern bfd_target *bfd_target_vector[];
+  char *dummy_name;
+  int t;
+
+  dummy_name = choose_temp_base ();
+  for (t = 0; bfd_target_vector[t]; t++)
+    {
+      bfd_target *p = bfd_target_vector[t];
+      bfd *abfd = bfd_openw (dummy_name, p->name);
+      int a;
+
+      printf ("%s\n (header %s, data %s)\n", p->name,
+             endian_string (p->header_byteorder),
+             endian_string (p->byteorder));
+
+      if (abfd == NULL)
+       {
+         bfd_nonfatal (dummy_name);
+         continue;
+       }
+
+      if (! bfd_set_format (abfd, bfd_object))
+       {
+         if (bfd_get_error () != bfd_error_invalid_operation)
+           bfd_nonfatal (p->name);
+         continue;
+       }
+
+      for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++)
+       if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
+         printf ("  %s\n",
+                 bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
+    }
+  unlink (dummy_name);
+  free (dummy_name);
+}
+
+/* Print a table showing which architectures are supported for entries
+   FIRST through LAST-1 of bfd_target_vector (targets across,
+   architectures down).  */
+
+static void
+display_info_table (first, last)
+     int first;
+     int last;
+{
+  extern bfd_target *bfd_target_vector[];
+  int t, a;
+  char *dummy_name;
+
+  /* Print heading of target names.  */
+  printf ("\n%*s", (int) LONGEST_ARCH, " ");
+  for (t = first; t < last && bfd_target_vector[t]; t++)
+    printf ("%s ", bfd_target_vector[t]->name);
+  putchar ('\n');
+
+  dummy_name = choose_temp_base ();
+  for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++)
+    if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0)
+      {
+       printf ("%*s ", (int) LONGEST_ARCH - 1,
+               bfd_printable_arch_mach (a, 0));
+       for (t = first; t < last && bfd_target_vector[t]; t++)
+         {
+           bfd_target *p = bfd_target_vector[t];
+           boolean ok = true;
+           bfd *abfd = bfd_openw (dummy_name, p->name);
+
+           if (abfd == NULL)
+             {
+               bfd_nonfatal (p->name);
+               ok = false;
+             }
+
+           if (ok)
+             {
+               if (! bfd_set_format (abfd, bfd_object))
+                 {
+                   if (bfd_get_error () != bfd_error_invalid_operation)
+                     bfd_nonfatal (p->name);
+                   ok = false;
+                 }
+             }
+
+           if (ok)
+             {
+               if (! bfd_set_arch_mach (abfd, a, 0))
+                 ok = false;
+             }
+
+           if (ok)
+             printf ("%s ", p->name);
+           else
+             {
+               int l = strlen (p->name);
+               while (l--)
+                 putchar ('-');
+               putchar (' ');
+             }
+         }
+       putchar ('\n');
+      }
+  unlink (dummy_name);
+  free (dummy_name);
+}
+
+/* Print tables of all the target-architecture combinations that
+   BFD has been configured to support.  */
+
+static void
+display_target_tables ()
+{
+  int t, columns;
+  extern bfd_target *bfd_target_vector[];
+  char *colum;
+
+  columns = 0;
+  colum = getenv ("COLUMNS");
+  if (colum != NULL)
+    columns = atoi (colum);
+  if (columns == 0)
+    columns = 80;
+
+  t = 0;
+  while (bfd_target_vector[t] != NULL)
+    {
+      int oldt = t, wid;
+
+      wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1;
+      ++t;
+      while (wid < columns && bfd_target_vector[t] != NULL)
+       {
+         int newwid;
+
+         newwid = wid + strlen (bfd_target_vector[t]->name) + 1;
+         if (newwid >= columns)
+           break;
+         wid = newwid;
+         ++t;
+       }
+      display_info_table (oldt, t);
+    }
+}
+
+static void
+display_info ()
+{
+  printf (_("BFD header file version %s\n"), BFD_VERSION);
+  display_target_list ();
+  display_target_tables ();
+}
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  char *target = default_target;
+  boolean seenflag = false;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = *argv;
+  xmalloc_set_program_name (program_name);
+
+  START_PROGRESS (program_name, 0);
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  while ((c = getopt_long (argc, argv, "pib:m:VCdDlfahrRtTxsSj:wE:",
+                          long_options, (int *) 0))
+        != EOF)
+    {
+      if (c != 'l' && c != OPTION_START_ADDRESS && c != OPTION_STOP_ADDRESS)
+       seenflag = true;
+      switch (c)
+       {
+       case 0:
+         break;                /* we've been given a long option */
+       case 'm':
+         machine = optarg;
+         break;
+       case 'j':
+         only = optarg;
+         break;
+       case 'l':
+         with_line_numbers = 1;
+         break;
+       case 'b':
+         target = optarg;
+         break;
+       case 'f':
+         dump_file_header = true;
+         break;
+       case 'i':
+         formats_info = true;
+         break;
+       case 'p':
+         dump_private_headers = 1;
+         break;
+       case 'x':
+         dump_private_headers = 1;
+         dump_symtab = 1;
+         dump_reloc_info = 1;
+         dump_file_header = true;
+         dump_ar_hdrs = 1;
+         dump_section_headers = 1;
+         break;
+       case 't':
+         dump_symtab = 1;
+         break;
+       case 'T':
+         dump_dynamic_symtab = 1;
+         break;
+       case 'C':
+         do_demangle = 1;
+         break;
+       case 'd':
+         disassemble = true;
+         break;
+       case 'D':
+         disassemble = disassemble_all = true;
+         break;
+       case 'S':
+         disassemble = true;
+         with_source_code = true;
+         break;
+       case 's':
+         dump_section_contents = 1;
+         break;
+       case 'r':
+         dump_reloc_info = 1;
+         break;
+       case 'R':
+         dump_dynamic_reloc_info = 1;
+         break;
+       case 'a':
+         dump_ar_hdrs = 1;
+         break;
+       case 'h':
+         dump_section_headers = 1;
+         break;
+       case 'H':
+         usage (stdout, 0);
+       case 'V':
+         show_version = 1;
+         break;
+       case 'w':
+         wide_output = 1;
+         break;
+       case OPTION_ADJUST_VMA:
+         adjust_section_vma = parse_vma (optarg, "--adjust-vma");
+         break;
+       case OPTION_START_ADDRESS:
+         start_address = parse_vma (optarg, "--start-address");
+         break;
+       case OPTION_STOP_ADDRESS:
+         stop_address = parse_vma (optarg, "--stop-address");
+         break;
+       case 'E':
+         if (strcmp (optarg, "B") == 0)
+           endian = BFD_ENDIAN_BIG;
+         else if (strcmp (optarg, "L") == 0)
+           endian = BFD_ENDIAN_LITTLE;
+         else
+           {
+             fprintf (stderr, _("%s: unrecognized -E option\n"), program_name);
+             usage (stderr, 1);
+           }
+         break;
+       case OPTION_ENDIAN:
+         if (strncmp (optarg, "big", strlen (optarg)) == 0)
+           endian = BFD_ENDIAN_BIG;
+         else if (strncmp (optarg, "little", strlen (optarg)) == 0)
+           endian = BFD_ENDIAN_LITTLE;
+         else
+           {
+             fprintf (stderr, _("%s: unrecognized --endian type `%s'\n"),
+                     program_name, optarg);
+             usage (stderr, 1);
+           }
+         break;
+       default:
+         usage (stderr, 1);
+       }
+    }
+
+  if (show_version)
+    print_version ("objdump");
+
+  if (seenflag == false)
+    usage (stderr, 1);
+
+  if (formats_info)
+    {
+      display_info ();
+    }
+  else
+    {
+      if (optind == argc)
+       display_file ("a.out", target);
+      else
+       for (; optind < argc;)
+         display_file (argv[optind++], target);
+    }
+
+  END_PROGRESS (program_name);
+
+  return 0;
+}
diff --git a/binutils/po/Make-in b/binutils/po/Make-in
new file mode 100644 (file)
index 0000000..0552db1
--- /dev/null
@@ -0,0 +1,251 @@
+# Makefile for program source directory in GNU NLS utilities package.
+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+#
+# This file file be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = $(prefix)/@DATADIRNAME@
+localedir = $(datadir)/locale
+gnulocaledir = $(prefix)/share/locale
+gettextsrcdir = $(prefix)/share/gettext/po
+subdir = po
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+
+CC = @CC@
+GENCAT = @GENCAT@
+GMSGFMT = PATH=../src:$$PATH @GMSGFMT@
+MSGFMT = @MSGFMT@
+XGETTEXT = PATH=../src:$$PATH @XGETTEXT@
+MSGMERGE = PATH=../src:$$PATH msgmerge
+
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+
+INCLUDES = -I.. -I$(top_srcdir)/intl
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+SOURCES = cat-id-tbl.c
+POFILES = @POFILES@
+GMOFILES = @GMOFILES@
+DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \
+stamp-cat-id $(POFILES) $(GMOFILES) $(SOURCES)
+
+POTFILES = \
+
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+INSTOBJEXT = @INSTOBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat
+
+.c.o:
+       $(COMPILE) $<
+
+.po.pox:
+       $(MAKE) $(PACKAGE).pot
+       $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
+
+.po.mo:
+       $(MSGFMT) -o $@ $<
+
+.po.gmo:
+       file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
+         && rm -f $$file && $(GMSGFMT) -o $$file $<
+
+.po.cat:
+       sed -f ../intl/po2msg.sed < $< > $*.msg \
+         && rm -f $@ && $(GENCAT) $@ $*.msg
+
+
+all: all-@USE_NLS@
+
+all-yes: $(CATALOGS) @MAINT@ $(PACKAGE).pot
+all-no:
+
+$(srcdir)/$(PACKAGE).pot: $(POTFILES)
+       $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
+         --add-comments --keyword=_ --keyword=N_ \
+         --files-from=$(srcdir)/POTFILES.in
+       rm -f $(srcdir)/$(PACKAGE).pot
+       mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot
+
+$(srcdir)/cat-id-tbl.c: stamp-cat-id; @:
+$(srcdir)/stamp-cat-id: $(PACKAGE).pot
+       rm -f cat-id-tbl.tmp
+       sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \
+               | sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp
+       if cmp -s cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; then \
+         rm cat-id-tbl.tmp; \
+       else \
+         echo cat-id-tbl.c changed; \
+         rm -f $(srcdir)/cat-id-tbl.c; \
+         mv cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; \
+       fi
+       cd $(srcdir) && rm -f stamp-cat-id && echo timestamp > stamp-cat-id
+
+
+install: install-exec install-data
+install-exec:
+install-info:
+install-data: install-data-@USE_NLS@
+install-data-no: all
+install-data-yes: all
+       if test -r $(MKINSTALLDIRS); then \
+         $(MKINSTALLDIRS) $(datadir); \
+       else \
+         $(top_srcdir)/mkinstalldirs $(datadir); \
+       fi
+       @catalogs='$(CATALOGS)'; \
+       for cat in $$catalogs; do \
+         cat=`basename $$cat`; \
+         case "$$cat" in \
+           *.gmo) destdir=$(gnulocaledir);; \
+           *)     destdir=$(localedir);; \
+         esac; \
+         lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+         dir=$$destdir/$$lang/LC_MESSAGES; \
+         if test -r $(MKINSTALLDIRS); then \
+           $(MKINSTALLDIRS) $$dir; \
+         else \
+           $(top_srcdir)/mkinstalldirs $$dir; \
+         fi; \
+         if test -r $$cat; then \
+           $(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
+           echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \
+         else \
+           $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
+           echo "installing $(srcdir)/$$cat as" \
+                "$$dir/$(PACKAGE)$(INSTOBJEXT)"; \
+         fi; \
+         if test -r $$cat.m; then \
+           $(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
+           echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
+         else \
+           if test -r $(srcdir)/$$cat.m ; then \
+             $(INSTALL_DATA) $(srcdir)/$$cat.m \
+               $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
+             echo "installing $(srcdir)/$$cat as" \
+                  "$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
+           else \
+             true; \
+           fi; \
+         fi; \
+       done
+       if test "$(PACKAGE)" = "gettext"; then \
+         if test -r $(MKINSTALLDIRS); then \
+           $(MKINSTALLDIRS) $(gettextsrcdir); \
+         else \
+           $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \
+         fi; \
+         $(INSTALL_DATA) $(srcdir)/Makefile.in.in \
+                         $(gettextsrcdir)/Makefile.in.in; \
+       else \
+         : ; \
+       fi
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+       catalogs='$(CATALOGS)'; \
+       for cat in $$catalogs; do \
+         cat=`basename $$cat`; \
+         lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+         rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
+         rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
+         rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
+         rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
+       done
+       rm -f $(gettextsrcdir)/po-Makefile.in.in
+
+check: all
+
+cat-id-tbl.o: ../intl/libgettext.h
+
+dvi info tags TAGS ID:
+
+mostlyclean:
+       rm -f core core.* *.pox $(PACKAGE).po *.old.po cat-id-tbl.tmp
+       rm -fr *.o
+
+clean: mostlyclean
+
+distclean: clean
+       rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m
+
+maintainer-clean: distclean
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+       rm -f $(GMOFILES)
+
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: update-po $(DISTFILES)
+       dists="$(DISTFILES)"; \
+       for file in $$dists; do \
+         ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+           || cp -p $(srcdir)/$$file $(distdir); \
+       done
+
+update-po: Makefile
+       $(MAKE) $(PACKAGE).pot
+       PATH=`pwd`/../src:$$PATH; \
+       cd $(srcdir); \
+       catalogs='$(CATALOGS)'; \
+       for cat in $$catalogs; do \
+         cat=`basename $$cat`; \
+         lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+         mv $$lang.po $$lang.old.po; \
+         echo "$$lang:"; \
+         if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \
+           rm -f $$lang.old.po; \
+         else \
+           echo "msgmerge for $$cat failed!"; \
+           rm -f $$lang.po; \
+           mv $$lang.old.po $$lang.po; \
+         fi; \
+       done
+
+POTFILES: POTFILES.in
+       ( if test 'x$(srcdir)' != 'x.'; then \
+           posrcprefix='$(top_srcdir)/'; \
+         else \
+           posrcprefix="../"; \
+         fi; \
+         rm -f $@-t $@ \
+           && (sed -e '/^#/d' -e '/^[  ]*$$/d' \
+                   -e "s@.*@   $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
+               | sed -e '$$s/\\$$//') > $@-t \
+           && chmod a-w $@-t \
+           && mv $@-t $@ )
+
+POTFILES.in: @MAINT@ ../Makefile
+       cd .. && $(MAKE) po/POTFILES.in
+
+Makefile: Make-in ../config.status POTFILES
+       cd .. \
+         && CONFIG_FILES=$(subdir)/Makefile.in:$(subdir)/Make-in \
+            CONFIG_HEADERS= $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/binutils/po/POTFILES.in b/binutils/po/POTFILES.in
new file mode 100644 (file)
index 0000000..47f3860
--- /dev/null
@@ -0,0 +1,52 @@
+readelf.c
+addr2line.c
+ar.c
+arsup.c
+arsup.h
+bucomm.c
+bucomm.h
+budbg.h
+coffdump.c
+coffgrok.c
+coffgrok.h
+debug.c
+debug.h
+dlltool.c
+dlltool.h
+dllwrap.c
+dyn-string.c
+dyn-string.h
+filemode.c
+ieee.c
+is-ranlib.c
+is-strip.c
+maybe-ranlib.c
+maybe-strip.c
+nlmconv.c
+nlmconv.h
+nm.c
+not-ranlib.c
+not-strip.c
+objcopy.c
+objdump.c
+prdbg.c
+rdcoff.c
+rddbg.c
+rename.c
+resbin.c
+rescoff.c
+resrc.c
+resres.c
+size.c
+srconv.c
+stabs.c
+strings.c
+sysdump.c
+version.c
+windres.c
+windres.h
+winduni.c
+winduni.h
+wrstabs.c
+testsuite/binutils-all/readelf.h
+testsuite/binutils-all/testprog.c
diff --git a/binutils/po/binutils.pot b/binutils/po/binutils.pot
new file mode 100644 (file)
index 0000000..beeb383
--- /dev/null
@@ -0,0 +1,3443 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 1999-04-26 10:11-0600\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+
+#: addr2line.c:76
+#, c-format
+msgid ""
+"Usage: %s [-CfsHV] [-b bfdname] [--target=bfdname]\n"
+"       [-e executable] [--exe=executable] [--demangle]\n"
+"       [--basenames] [--functions] [addr addr ...]\n"
+msgstr ""
+
+#: addr2line.c:83 ar.c:255 nlmconv.c:1141 nm.c:304 objcopy.c:318 objcopy.c:337
+#: objdump.c:236 readelf.c:1133 size.c:89 strings.c:512 windres.c:723
+msgid "Report bugs to bug-gnu-utils@gnu.org\n"
+msgstr ""
+
+#: addr2line.c:243
+#, c-format
+msgid "%s: can not get addresses from archive"
+msgstr ""
+
+#: ar.c:207
+#, c-format
+msgid "no entry %s in archive\n"
+msgstr ""
+
+#: ar.c:224
+#, c-format
+msgid ""
+"Usage: %s [-]{dmpqrstx}[abcilosSuvV] [member-name] archive-file file...\n"
+msgstr ""
+
+#: ar.c:226
+#, c-format
+msgid "       %s -M [<mri-script]\n"
+msgstr ""
+
+#: ar.c:227
+msgid " commands:\n"
+msgstr ""
+
+#: ar.c:228
+msgid "  d            - delete file(s) from the archive\n"
+msgstr ""
+
+#: ar.c:229
+msgid "  m[ab]        - move file(s) in the archive\n"
+msgstr ""
+
+#: ar.c:230
+msgid "  p            - print file(s) found in the archive\n"
+msgstr ""
+
+#: ar.c:231
+msgid "  q[f]         - quick append file(s) to the archive\n"
+msgstr ""
+
+#: ar.c:232
+msgid ""
+"  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"
+msgstr ""
+
+#: ar.c:233
+msgid "  t            - display contents of archive\n"
+msgstr ""
+
+#: ar.c:234
+msgid "  x[o]         - extract file(s) from the archive\n"
+msgstr ""
+
+#: ar.c:235
+msgid " command specific modifiers:\n"
+msgstr ""
+
+#: ar.c:236
+msgid "  [a]          - put file(s) after [member-name]\n"
+msgstr ""
+
+#: ar.c:237
+msgid "  [b]          - put file(s) before [member-name] (same as [i])\n"
+msgstr ""
+
+#: ar.c:238
+msgid "  [f]          - truncate inserted file names\n"
+msgstr ""
+
+#: ar.c:239
+msgid "  [o]          - preserve original dates\n"
+msgstr ""
+
+#: ar.c:240
+msgid ""
+"  [u]          - only replace files that are newer than current archive "
+"contents\n"
+msgstr ""
+
+#: ar.c:241
+msgid " generic modifiers:\n"
+msgstr ""
+
+#: ar.c:242
+msgid "  [c]          - do not warn if the library had to be created\n"
+msgstr ""
+
+#: ar.c:243
+msgid "  [s]          - create an archive index (cf. ranlib)\n"
+msgstr ""
+
+#: ar.c:244
+msgid "  [S]          - do not build a symbol table\n"
+msgstr ""
+
+#: ar.c:245
+msgid "  [v]          - be verbose\n"
+msgstr ""
+
+#: ar.c:246
+msgid "  [V]          - display the version number\n"
+msgstr ""
+
+#: ar.c:250
+#, c-format
+msgid "Usage: %s [-vV] archive\n"
+msgstr ""
+
+#: ar.c:431
+msgid "two different operation options specified"
+msgstr ""
+
+#: ar.c:500
+#, c-format
+msgid "%s: illegal option -- %c\n"
+msgstr ""
+
+#: ar.c:532
+msgid "no operation specified"
+msgstr ""
+
+#: ar.c:535
+msgid "`u' is only meaningful with the `r' option."
+msgstr ""
+
+#: ar.c:615
+#, c-format
+msgid "%s: internal error -- this option not implemented\n"
+msgstr ""
+
+#: ar.c:730 ar.c:782 ar.c:1212
+#, c-format
+msgid "internal stat error on %s"
+msgstr ""
+
+#: ar.c:734
+#, c-format
+msgid ""
+"\n"
+"<member %s>\n"
+"\n"
+msgstr ""
+
+#: ar.c:751 ar.c:819
+#, c-format
+msgid "%s is not a valid archive"
+msgstr ""
+
+#: ar.c:787
+#, c-format
+msgid "stat returns negative size for %s"
+msgstr ""
+
+#: ar.c:908
+#, c-format
+msgid "%s is not an archive"
+msgstr ""
+
+#: ar.c:915
+#, c-format
+msgid "%s: creating %s\n"
+msgstr ""
+
+#: ar.c:1110
+#, c-format
+msgid "No member named `%s'\n"
+msgstr ""
+
+#: ar.c:1162
+#, c-format
+msgid "%s: no entry %s in archive %s!\n"
+msgstr ""
+
+#: ar.c:1322
+#, c-format
+msgid "%s: no archive map to update"
+msgstr ""
+
+#: arsup.c:86
+#, c-format
+msgid "No entry %s in archive.\n"
+msgstr ""
+
+#: arsup.c:118
+#, c-format
+msgid "Can't open file %s\n"
+msgstr ""
+
+#: arsup.c:166
+#, c-format
+msgid "%s: Can't open output archive %s\n"
+msgstr ""
+
+#: arsup.c:178
+#, c-format
+msgid "%s: Can't open input archive %s\n"
+msgstr ""
+
+#: arsup.c:184
+#, c-format
+msgid "%s: file %s is not an archive\n"
+msgstr ""
+
+#: arsup.c:225
+#, c-format
+msgid "%s: no output archive specified yet\n"
+msgstr ""
+
+#: arsup.c:245 arsup.c:280 arsup.c:316 arsup.c:336 arsup.c:394
+#, c-format
+msgid "%s: no open output archive\n"
+msgstr ""
+
+#: arsup.c:253 arsup.c:354 arsup.c:374
+#, c-format
+msgid "%s: can't open file %s\n"
+msgstr ""
+
+#: arsup.c:301 arsup.c:370 arsup.c:449
+#, c-format
+msgid "%s: can't find module file %s\n"
+msgstr ""
+
+#: arsup.c:401
+#, c-format
+msgid "Current open archive is %s\n"
+msgstr ""
+
+#: arsup.c:428
+#, c-format
+msgid "%s: no open  archive\n"
+msgstr ""
+
+#: bucomm.c:139
+#, c-format
+msgid "can't set BFD default target to `%s': %s"
+msgstr ""
+
+#: bucomm.c:151
+#, c-format
+msgid "%s: Matching formats:"
+msgstr ""
+
+#: bucomm.c:168
+msgid "Supported targets:"
+msgstr ""
+
+#: bucomm.c:170
+#, c-format
+msgid "%s: supported targets:"
+msgstr ""
+
+#: bucomm.c:263
+#, c-format
+msgid "%s: bad number: %s"
+msgstr ""
+
+#: coffdump.c:94
+#, c-format
+msgid "#lines %d "
+msgstr ""
+
+#: coffdump.c:456 sysdump.c:719
+#, c-format
+msgid "%s: Print a human readable interpretation of a SYSROFF object file\n"
+msgstr ""
+
+#: coffdump.c:498 srconv.c:1940 sysdump.c:755
+#, c-format
+msgid "GNU %s version %s\n"
+msgstr ""
+
+#: coffdump.c:516 srconv.c:1977 sysdump.c:775
+#, c-format
+msgid "%s: no input file specified\n"
+msgstr ""
+
+#: debug.c:653
+msgid "debug_add_to_current_namespace: no current file"
+msgstr ""
+
+#: debug.c:736
+msgid "debug_start_source: no debug_set_filename call"
+msgstr ""
+
+#: debug.c:795
+msgid "debug_record_function: no debug_set_filename call"
+msgstr ""
+
+#: debug.c:851
+msgid "debug_record_parameter: no current function"
+msgstr ""
+
+#: debug.c:885
+msgid "debug_end_function: no current function"
+msgstr ""
+
+#: debug.c:891
+msgid "debug_end_function: some blocks were not closed"
+msgstr ""
+
+#: debug.c:921
+msgid "debug_start_block: no current block"
+msgstr ""
+
+#: debug.c:959
+msgid "debug_end_block: no current block"
+msgstr ""
+
+#: debug.c:966
+msgid "debug_end_block: attempt to close top level block"
+msgstr ""
+
+#: debug.c:992
+msgid "debug_record_line: no current unit"
+msgstr ""
+
+#. FIXME
+#: debug.c:1046
+msgid "debug_start_common_block: not implemented"
+msgstr ""
+
+#. FIXME
+#: debug.c:1058
+msgid "debug_end_common_block: not implemented"
+msgstr ""
+
+#. FIXME.
+#: debug.c:1152
+msgid "debug_record_label not implemented"
+msgstr ""
+
+#: debug.c:1178
+msgid "debug_record_variable: no current file"
+msgstr ""
+
+#: debug.c:1194
+msgid "debug_record_variable: no current block"
+msgstr ""
+
+#: debug.c:1764
+msgid "debug_make_undefined_type: unsupported kind"
+msgstr ""
+
+#: debug.c:1970
+msgid "debug_name_type: no current file"
+msgstr ""
+
+#: debug.c:2018
+msgid "debug_tag_type: no current file"
+msgstr ""
+
+#: debug.c:2026
+msgid "debug_tag_type: extra tag attempted"
+msgstr ""
+
+#: debug.c:2066
+#, c-format
+msgid "Warning: changing type size from %d to %d\n"
+msgstr ""
+
+#: debug.c:2090
+msgid "debug_find_named_type: no current compilation unit"
+msgstr ""
+
+#: debug.c:2197
+#, c-format
+msgid "debug_get_real_type: circular debug information for %s\n"
+msgstr ""
+
+#: debug.c:2663
+msgid "debug_write_type: illegal type encountered"
+msgstr ""
+
+#: dlltool.c:627 dlltool.c:646 dlltool.c:666
+#, c-format
+msgid "Internal error: Unknown machine type: %d\n"
+msgstr ""
+
+#: dlltool.c:700
+#, c-format
+msgid "Can't open def file: %s"
+msgstr ""
+
+#: dlltool.c:705
+#, c-format
+msgid "Processing def file: %s"
+msgstr ""
+
+#: dlltool.c:709
+msgid "Processed def file"
+msgstr ""
+
+#: dlltool.c:734
+#, c-format
+msgid "Syntax error in def file %s:%d\n"
+msgstr ""
+
+#: dlltool.c:767
+#, c-format
+msgid "NAME: %s base: %x"
+msgstr ""
+
+#: dlltool.c:770
+msgid "Can't have LIBRARY and NAME\n"
+msgstr ""
+
+#: dlltool.c:786
+#, c-format
+msgid "LIBRARY: %s base: %x"
+msgstr ""
+
+#: dlltool.c:789
+#, c-format
+msgid "%s: Can't have LIBRARY and NAME\n"
+msgstr ""
+
+#: dlltool.c:1044
+#, c-format
+msgid "wait: %s"
+msgstr ""
+
+#: dlltool.c:1049
+#, c-format
+msgid "subprocess got fatal signal %d"
+msgstr ""
+
+#: dlltool.c:1055
+#, c-format
+msgid "%s exited with status %d\n"
+msgstr ""
+
+#: dlltool.c:1087
+#, c-format
+msgid "Sucking in info from .drective section in %s\n"
+msgstr ""
+
+#: dlltool.c:1197
+#, c-format
+msgid "Excluding symbol: %s\n"
+msgstr ""
+
+#: dlltool.c:1292 dlltool.c:1303 nm.c:902 nm.c:913 objdump.c:379 objdump.c:396
+#, c-format
+msgid "%s: no symbols\n"
+msgstr ""
+
+#. FIXME: we ought to read in and block out the base relocations
+#: dlltool.c:1330
+#, c-format
+msgid "%s: Done reading %s\n"
+msgstr ""
+
+#: dlltool.c:1341
+#, c-format
+msgid "Unable to open object file: %s"
+msgstr ""
+
+#: dlltool.c:1344
+#, c-format
+msgid "Scanning object file %s"
+msgstr ""
+
+#: dlltool.c:1434
+msgid "Adding exports to output file"
+msgstr ""
+
+#: dlltool.c:1479
+msgid "Added exports to output file"
+msgstr ""
+
+#: dlltool.c:1587
+#, c-format
+msgid "Generating export file: %s\n"
+msgstr ""
+
+#: dlltool.c:1592
+#, c-format
+msgid "Unable to open temporary assembler file: %s"
+msgstr ""
+
+#: dlltool.c:1595
+#, c-format
+msgid "Opened temporary file: %s"
+msgstr ""
+
+#: dlltool.c:1828
+msgid "Generated exports file"
+msgstr ""
+
+#: dlltool.c:2081
+#, c-format
+msgid "bfd_open failed open stub file: %s"
+msgstr ""
+
+#: dlltool.c:2084
+#, c-format
+msgid "Creating stub file: %s"
+msgstr ""
+
+#: dlltool.c:2593
+#, c-format
+msgid "Can't open .lib file: %s"
+msgstr ""
+
+#: dlltool.c:2596
+#, c-format
+msgid "Creating library file: %s\n"
+msgstr ""
+
+#: dlltool.c:2652
+#, c-format
+msgid "cannot delete %s: %s\n"
+msgstr ""
+
+#: dlltool.c:2656
+msgid "Created lib file"
+msgstr ""
+
+#: dlltool.c:2757
+#, c-format
+msgid "Warning, ignoring duplicate EXPORT %s %d,%d\n"
+msgstr ""
+
+#: dlltool.c:2763
+#, c-format
+msgid "Error, duplicate EXPORT with oridinals: %s"
+msgstr ""
+
+#: dlltool.c:2890
+msgid "Processing definitions"
+msgstr ""
+
+#: dlltool.c:2928
+msgid "Processed definitions"
+msgstr ""
+
+#. xgetext:c-format
+#: dlltool.c:2939
+#, c-format
+msgid "Usage %s <options> <object-files>\n"
+msgstr ""
+
+#. xgetext:c-format
+#: dlltool.c:2941
+#, c-format
+msgid ""
+"   -m --machine <machine>    Create {arm, i386, ppc, thumb} DLL. [default: "
+"%s]\n"
+msgstr ""
+
+#: dlltool.c:2942
+msgid "   -e --output-exp <outname> Generate an export file.\n"
+msgstr ""
+
+#: dlltool.c:2943
+msgid "   -l --output-lib <outname> Generate an interface library.\n"
+msgstr ""
+
+#: dlltool.c:2944
+msgid "   -a --add-indirect         Add dll indirects to export file.\n"
+msgstr ""
+
+#: dlltool.c:2945
+msgid ""
+"   -D --dllname <name>       Name of input dll to put into interface lib.\n"
+msgstr ""
+
+#: dlltool.c:2946
+msgid "   -d --input-def <deffile>  Name of .def file to be read in.\n"
+msgstr ""
+
+#: dlltool.c:2947
+msgid "   -z --output-def <deffile> Name of .def file to be created.\n"
+msgstr ""
+
+#: dlltool.c:2948
+msgid "   --export-all-symbols      Export all symbols to .def\n"
+msgstr ""
+
+#: dlltool.c:2949
+msgid "   --no-export-all-symbols   Only export listed symbols\n"
+msgstr ""
+
+#: dlltool.c:2950
+msgid "   --exclude-symbols <list>  Don't export <list>\n"
+msgstr ""
+
+#: dlltool.c:2951
+msgid "   --no-default-excludes     Clear default exclude symbols\n"
+msgstr ""
+
+#: dlltool.c:2952
+msgid "   -b --base-file <basefile> Read linker generated base file.\n"
+msgstr ""
+
+#: dlltool.c:2953
+msgid "   -x --no-idata4            Don't generate idata$4 section.\n"
+msgstr ""
+
+#: dlltool.c:2954
+msgid "   -c --no-idata5            Don't generate idata$5 section.\n"
+msgstr ""
+
+#: dlltool.c:2955
+msgid ""
+"   -U --add-underscore       Add underscores to symbols in interface "
+"library.\n"
+msgstr ""
+
+#: dlltool.c:2956
+msgid "   -k --kill-at              Kill @<n> from exported names.\n"
+msgstr ""
+
+#: dlltool.c:2957
+msgid "   -A --add-stdcall-alias    Add aliases without @<n>.\n"
+msgstr ""
+
+#: dlltool.c:2958
+msgid "   -S --as <name>            Use <name> for assembler.\n"
+msgstr ""
+
+#: dlltool.c:2959
+msgid "   -f --as-flags <flags>     Pass <flags> to the assembler.\n"
+msgstr ""
+
+#: dlltool.c:2961
+msgid "   -i --interwork            Support ARM/Thumb interworking.\n"
+msgstr ""
+
+#: dlltool.c:2963
+msgid ""
+"   -n --no-delete            Keep temp files (repeat for extra "
+"preservation).\n"
+msgstr ""
+
+#: dlltool.c:2964
+msgid "   -v --verbose              Be verbose.\n"
+msgstr ""
+
+#: dlltool.c:2965
+msgid "   -V --version              Display the program version.\n"
+msgstr ""
+
+#: dlltool.c:2966
+msgid "   -h --help                 Display this information.\n"
+msgstr ""
+
+#: dlltool.c:3120
+#, c-format
+msgid "Unable to open base-file: %s"
+msgstr ""
+
+#: dlltool.c:3137
+#, c-format
+msgid "Machine '%s' not supported"
+msgstr ""
+
+#: ieee.c:316
+msgid "unexpected end of debugging information"
+msgstr ""
+
+#: ieee.c:411
+msgid "invalid number"
+msgstr ""
+
+#: ieee.c:470
+msgid "invalid string length"
+msgstr ""
+
+#: ieee.c:527 ieee.c:568
+msgid "expression stack overflow"
+msgstr ""
+
+#: ieee.c:547
+msgid "unsupported IEEE expression operator"
+msgstr ""
+
+#: ieee.c:562
+msgid "unknown section"
+msgstr ""
+
+#: ieee.c:583
+msgid "expression stack underflow"
+msgstr ""
+
+#: ieee.c:597
+msgid "expression stack mismatch"
+msgstr ""
+
+#: ieee.c:636
+msgid "unknown builtin type"
+msgstr ""
+
+#: ieee.c:781
+msgid "BCD float type not supported"
+msgstr ""
+
+#: ieee.c:927
+msgid "unexpected number"
+msgstr ""
+
+#: ieee.c:934
+msgid "unexpected record type"
+msgstr ""
+
+#: ieee.c:967
+msgid "blocks left on stack at end"
+msgstr ""
+
+#: ieee.c:1232
+msgid "unknown BB type"
+msgstr ""
+
+#: ieee.c:1241
+msgid "stack overflow"
+msgstr ""
+
+#: ieee.c:1266
+msgid "stack underflow"
+msgstr ""
+
+#: ieee.c:1380 ieee.c:1452 ieee.c:2151
+msgid "illegal variable index"
+msgstr ""
+
+#: ieee.c:1430
+msgid "illegal type index"
+msgstr ""
+
+#: ieee.c:1440 ieee.c:1477
+msgid "unknown TY code"
+msgstr ""
+
+#: ieee.c:1459
+msgid "undefined variable in TY"
+msgstr ""
+
+#. Pascal file name.  FIXME.
+#: ieee.c:1870
+msgid "Pascal file name not supported"
+msgstr ""
+
+#: ieee.c:1918
+msgid "unsupported qualifer"
+msgstr ""
+
+#: ieee.c:2189
+msgid "undefined variable in ATN"
+msgstr ""
+
+#: ieee.c:2232
+msgid "unknown ATN type"
+msgstr ""
+
+#. Reserved for FORTRAN common.
+#: ieee.c:2354
+msgid "unsupported ATN11"
+msgstr ""
+
+#. We have no way to record this information.  FIXME.
+#: ieee.c:2381
+msgid "unsupported ATN12"
+msgstr ""
+
+#: ieee.c:2441
+msgid "unexpected string in C++ misc"
+msgstr ""
+
+#: ieee.c:2454
+msgid "bad misc record"
+msgstr ""
+
+#: ieee.c:2497
+msgid "unrecognized C++ misc record"
+msgstr ""
+
+#: ieee.c:2614
+msgid "undefined C++ object"
+msgstr ""
+
+#: ieee.c:2648
+msgid "unrecognized C++ object spec"
+msgstr ""
+
+#: ieee.c:2684
+msgid "unsupported C++ object type"
+msgstr ""
+
+#: ieee.c:2694
+msgid "C++ base class not defined"
+msgstr ""
+
+#: ieee.c:2706 ieee.c:2811
+msgid "C++ object has no fields"
+msgstr ""
+
+#: ieee.c:2725
+msgid "C++ base class not found in container"
+msgstr ""
+
+#: ieee.c:2832
+msgid "C++ data member not found in container"
+msgstr ""
+
+#: ieee.c:2873 ieee.c:3023
+msgid "unknown C++ visibility"
+msgstr ""
+
+#: ieee.c:2907
+msgid "bad C++ field bit pos or size"
+msgstr ""
+
+#: ieee.c:2999
+msgid "bad type for C++ method function"
+msgstr ""
+
+#: ieee.c:3009
+msgid "no type information for C++ method function"
+msgstr ""
+
+#: ieee.c:3048
+msgid "C++ static virtual method"
+msgstr ""
+
+#: ieee.c:3143
+msgid "unrecognized C++ object overhead spec"
+msgstr ""
+
+#: ieee.c:3182
+msgid "undefined C++ vtable"
+msgstr ""
+
+#: ieee.c:3253
+msgid "C++ default values not in a function"
+msgstr ""
+
+#: ieee.c:3293
+msgid "unrecognized C++ default type"
+msgstr ""
+
+#: ieee.c:3324
+msgid "reference parameter is not a pointer"
+msgstr ""
+
+#: ieee.c:3409
+msgid "unrecognized C++ reference type"
+msgstr ""
+
+#: ieee.c:3491
+msgid "C++ reference not found"
+msgstr ""
+
+#: ieee.c:3499
+msgid "C++ reference is not pointer"
+msgstr ""
+
+#: ieee.c:3528 ieee.c:3536
+msgid "missing required ASN"
+msgstr ""
+
+#: ieee.c:3566 ieee.c:3574
+msgid "missing required ATN65"
+msgstr ""
+
+#: ieee.c:3588
+msgid "bad ATN65 record"
+msgstr ""
+
+#: ieee.c:4235
+msgid "IEEE numeric overflow: 0x"
+msgstr ""
+
+#: ieee.c:4281
+#, c-format
+msgid "IEEE string length overflow: %u\n"
+msgstr ""
+
+#: ieee.c:5315
+#, c-format
+msgid "IEEE unsupported integer type size %u\n"
+msgstr ""
+
+#: ieee.c:5351
+#, c-format
+msgid "IEEE unsupported float type size %u\n"
+msgstr ""
+
+#: ieee.c:5387
+#, c-format
+msgid "IEEE unsupported complex type size %u\n"
+msgstr ""
+
+#: nlmconv.c:275 srconv.c:1966
+#, c-format
+msgid "%s: input and output files must be different\n"
+msgstr ""
+
+#: nlmconv.c:325
+#, c-format
+msgid "%s: input file named both on command line and with INPUT\n"
+msgstr ""
+
+#: nlmconv.c:336
+#, c-format
+msgid "%s: no input file\n"
+msgstr ""
+
+#: nlmconv.c:366
+#, c-format
+msgid "%s: no name for output file\n"
+msgstr ""
+
+#: nlmconv.c:381
+#, c-format
+msgid "%s: warning:input and output formats are not compatible\n"
+msgstr ""
+
+#: nlmconv.c:411
+msgid "make .bss section"
+msgstr ""
+
+#: nlmconv.c:420
+msgid "make .nlmsections section"
+msgstr ""
+
+#: nlmconv.c:422
+msgid "set .nlmsections flags"
+msgstr ""
+
+#: nlmconv.c:450
+msgid "set .bss vma"
+msgstr ""
+
+#: nlmconv.c:457
+msgid "set .data size"
+msgstr ""
+
+#: nlmconv.c:638
+#, c-format
+msgid "%s: warning: symbol %s imported but not in import list\n"
+msgstr ""
+
+#: nlmconv.c:658
+msgid "set start address"
+msgstr ""
+
+#: nlmconv.c:707
+#, c-format
+msgid "%s: warning: START procedure %s not defined\n"
+msgstr ""
+
+#: nlmconv.c:710
+#, c-format
+msgid "%s: warning: EXIT procedure %s not defined\n"
+msgstr ""
+
+#: nlmconv.c:714
+#, c-format
+msgid "%s: warning: CHECK procedure %s not defined\n"
+msgstr ""
+
+#: nlmconv.c:736 nlmconv.c:928
+msgid "custom section"
+msgstr ""
+
+#: nlmconv.c:757 nlmconv.c:960
+msgid "help section"
+msgstr ""
+
+#: nlmconv.c:779 nlmconv.c:979
+msgid "message section"
+msgstr ""
+
+#: nlmconv.c:795 nlmconv.c:1012
+msgid "module section"
+msgstr ""
+
+#: nlmconv.c:815 nlmconv.c:1029
+msgid "rpc section"
+msgstr ""
+
+#: nlmconv.c:852
+#, c-format
+msgid "%s:%s: warning: shared libraries can not have uninitialized data\n"
+msgstr ""
+
+#: nlmconv.c:873 nlmconv.c:1049
+msgid "shared section"
+msgstr ""
+
+#: nlmconv.c:881
+#, c-format
+msgid "%s: warning: No version number given\n"
+msgstr ""
+
+#: nlmconv.c:922 nlmconv.c:954 nlmconv.c:973 nlmconv.c:1023 nlmconv.c:1043
+#, c-format
+msgid "%s:%s: read: %s\n"
+msgstr ""
+
+#: nlmconv.c:946
+#, c-format
+msgid "%s: warning: MAP and FULLMAP are not supported; try ld -M\n"
+msgstr ""
+
+#: nlmconv.c:1121
+#, c-format
+msgid "%s: Convert an object file into a NetWare Loadable Module\n"
+msgstr ""
+
+#: nlmconv.c:1133
+#, c-format
+msgid ""
+"Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n"
+"       [--input-target=bfdname] [--output-target=bfdname]\n"
+"       [--header-file=file] [--linker=linker] [--debug]\n"
+"       [--help] [--version]\n"
+"       [in-file [out-file]]\n"
+msgstr ""
+
+#: nlmconv.c:1173
+#, c-format
+msgid "%s: support not compiled in for %s\n"
+msgstr ""
+
+#: nlmconv.c:1216
+msgid "make section"
+msgstr ""
+
+#: nlmconv.c:1230
+msgid "set section size"
+msgstr ""
+
+#: nlmconv.c:1236
+msgid "set section alignment"
+msgstr ""
+
+#: nlmconv.c:1240
+msgid "set section flags"
+msgstr ""
+
+#: nlmconv.c:1251
+msgid "set .nlmsections size"
+msgstr ""
+
+#: nlmconv.c:1339 nlmconv.c:1347 nlmconv.c:1356 nlmconv.c:1361
+msgid "set .nlmsection contents"
+msgstr ""
+
+#: nlmconv.c:1864
+msgid "stub section sizes"
+msgstr ""
+
+#: nlmconv.c:1913
+msgid "writing stub"
+msgstr ""
+
+#: nlmconv.c:2003
+#, c-format
+msgid "%s: unresolved PC relative reloc against %s\n"
+msgstr ""
+
+#: nlmconv.c:2068
+#, c-format
+msgid "%s: overflow when adjusting relocation against %s\n"
+msgstr ""
+
+#: nlmconv.c:2191
+#, c-format
+msgid "%s: execution of %s failed: "
+msgstr ""
+
+#: nlmconv.c:2206
+#, c-format
+msgid "%s: Execution of %s failed\n"
+msgstr ""
+
+#: nm.c:292
+#, c-format
+msgid ""
+"Usage: %s [-aABCDglnopPrsuvV] [-t radix] [--radix=radix] [--target=bfdname]\n"
+"       [--debug-syms] [--extern-only] [--print-armap] [--print-file-name]\n"
+"       [--numeric-sort] [--no-sort] [--reverse-sort] [--size-sort]\n"
+"       [--undefined-only] [--portability] [-f {bsd,sysv,posix}]\n"
+"       [--format={bsd,sysv,posix}] [--demangle] [--no-demangle] [--dynamic]\n"
+"       [--defined-only] [--line-numbers]\n"
+"       [--version] [--help]\n"
+"       [file...]\n"
+msgstr ""
+
+#: nm.c:337
+#, c-format
+msgid "%s: %s: invalid radix\n"
+msgstr ""
+
+#: nm.c:363
+#, c-format
+msgid "%s: %s: invalid output format\n"
+msgstr ""
+
+#: nm.c:490
+#, c-format
+msgid "%s: data size %ld\n"
+msgstr ""
+
+#: nm.c:1281
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Undefined symbols from %s:\n"
+"\n"
+msgstr ""
+
+#: nm.c:1283
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Symbols from %s:\n"
+"\n"
+msgstr ""
+
+#: nm.c:1284 nm.c:1338
+msgid ""
+"Name                  Value   Class        Type         Size   Line  "
+"Section\n"
+"\n"
+msgstr ""
+
+#: nm.c:1335
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Undefined symbols from %s[%s]:\n"
+"\n"
+msgstr ""
+
+#: nm.c:1337
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Symbols from %s[%s]:\n"
+"\n"
+msgstr ""
+
+#: nm.c:1508
+msgid ""
+"\n"
+"Archive index:\n"
+msgstr ""
+
+#: objcopy.c:293
+#, c-format
+msgid ""
+"Usage: %s [-vVSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n"
+"       [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n"
+"       [--input-target=bfdname] [--output-target=bfdname] "
+"[--target=bfdname]\n"
+"       [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n"
+"       [--discard-locals] [--debugging] [--remove-section=section]\n"
+msgstr ""
+
+#: objcopy.c:300
+msgid ""
+"       [--gap-fill=val] [--pad-to=address] [--preserve-dates]\n"
+"       [--set-start=val] \n"
+"       [--change-start=incr] [--change-addresses=incr] \n"
+"       (--adjust-start   and  --adjust-vma are aliases for these two) \n"
+"       [--change-section-address=section{=,+,-}val]\n"
+"       (--adjust-section-vma is an alias for --change-section-address)\n"
+"       [--change-section-lma=section{=,+,-}val]\n"
+"       [--change-section-vma=section{=,+,-}val]\n"
+"       [--adjust-warnings] [--no-adjust-warnings]\n"
+"       [--change-warnings] [--no-change-warnings]\n"
+"       [--set-section-flags=section=flags] "
+"[--add-section=sectionname=filename]\n"
+"       [--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N "
+"symbol]\n"
+"       [--localize-symbol symbol] [-L symbol] [--weaken-symbol symbol]\n"
+"       [-W symbol] [--change-leading-char] [--remove-leading-char] "
+"[--weaken]\n"
+"       [--verbose] [--version] [--help] in-file [out-file]\n"
+msgstr ""
+
+#: objcopy.c:327
+#, c-format
+msgid ""
+"Usage: %s [-vVsSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n"
+"       [--input-target=bfdname] [--output-target=bfdname] "
+"[--target=bfdname]\n"
+"       [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n"
+"       [--discard-locals] [--keep-symbol symbol] [-K symbol]\n"
+"       [--strip-symbol symbol] [-N symbol] [--remove-section=section]\n"
+"       [-o file] [--preserve-dates] [--verbose] [--version] [--help] "
+"file...\n"
+msgstr ""
+
+#: objcopy.c:383
+#, c-format
+msgid "unrecognized section flag `%s'"
+msgstr ""
+
+#: objcopy.c:384
+msgid "supported flags: alloc, load, readonly, code, data, rom, contents"
+msgstr ""
+
+#: objcopy.c:623
+#, c-format
+msgid "copy from %s(%s) to %s(%s)\n"
+msgstr ""
+
+#: objcopy.c:642
+#, c-format
+msgid "Warning: Output file cannot represent architecture %s"
+msgstr ""
+
+#: objcopy.c:669
+#, c-format
+msgid "can't create section `%s': %s"
+msgstr ""
+
+#: objcopy.c:755
+#, c-format
+msgid "Can't fill gap after %s: %s"
+msgstr ""
+
+#: objcopy.c:780
+#, c-format
+msgid "Can't add padding to %s: %s"
+msgstr ""
+
+#: objcopy.c:916
+#, c-format
+msgid "%s: error copying private BFD data: %s"
+msgstr ""
+
+#: objcopy.c:950
+#, c-format
+msgid "cannot mkdir %s for archive copying (error: %s)"
+msgstr ""
+
+#: objcopy.c:1204
+#, c-format
+msgid "%s: section `%s': error in %s: %s"
+msgstr ""
+
+#: objcopy.c:1476
+#, c-format
+msgid "%s: can't create debugging section: %s"
+msgstr ""
+
+#: objcopy.c:1491
+#, c-format
+msgid "%s: can't set debugging section contents: %s"
+msgstr ""
+
+#: objcopy.c:1500
+#, c-format
+msgid "%s: don't know how to write debugging information for %s"
+msgstr ""
+
+#: objcopy.c:1605
+#, c-format
+msgid "%s: cannot stat: %s"
+msgstr ""
+
+#: objcopy.c:1655
+msgid "byte number must be non-negative"
+msgstr ""
+
+#: objcopy.c:1660
+msgid "interleave must be positive"
+msgstr ""
+
+#: objcopy.c:1729
+msgid "bad format for --add-section NAME=FILENAME"
+msgstr ""
+
+#: objcopy.c:1732
+#, c-format
+msgid "cannot stat: %s: %s"
+msgstr ""
+
+#: objcopy.c:1750
+#, c-format
+msgid "cannot open: %s: %s"
+msgstr ""
+
+#: objcopy.c:1754
+#, c-format
+msgid "%s: fread failed"
+msgstr ""
+
+#: objcopy.c:1791
+#, c-format
+msgid "bad format for %s"
+msgstr ""
+
+#: objcopy.c:1855
+#, c-format
+msgid "Warning: truncating gap-fill from 0x%s to 0x%x"
+msgstr ""
+
+#: objcopy.c:1879
+msgid "bad format for --set-section-flags"
+msgstr ""
+
+#: objcopy.c:1909
+msgid "byte number must be less than interleave"
+msgstr ""
+
+#: objcopy.c:1928
+#, c-format
+msgid "Cannot stat: %s: %s"
+msgstr ""
+
+#: objcopy.c:1968
+#, c-format
+msgid "Warning: --change-section-vma %s%c0x%s never used"
+msgstr ""
+
+#: objcopy.c:1981
+#, c-format
+msgid "Warning: --change-section-lma %s%c0x%s never used"
+msgstr ""
+
+#: objdump.c:219
+#, c-format
+msgid ""
+"Usage: %s [-ahifCdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n"
+"       [--archive-headers] [--target=bfdname] [--debugging] [--disassemble]\n"
+"       [--disassemble-all] [--disassemble-zeroes] [--file-headers]\n"
+"       [--section-headers] [--headers]\n"
+"       [--info] [--section=section-name] [--line-numbers] [--source]\n"
+msgstr ""
+
+#: objdump.c:226
+msgid ""
+"       [--architecture=machine] [--reloc] [--full-contents] [--stabs]\n"
+"       [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n"
+"       [--wide] [--version] [--help] [--private-headers]\n"
+"       [--start-address=addr] [--stop-address=addr]\n"
+"       [--prefix-addresses] [--[no-]show-raw-insn] [--demangle]\n"
+"       [--adjust-vma=offset] [-EB|-EL] [--endian={big|little}] objfile...\n"
+"at least one option besides -l (--line-numbers) must be given\n"
+msgstr ""
+
+#: objdump.c:361
+msgid "Sections:\n"
+msgstr ""
+
+#: objdump.c:363
+msgid "Idx Name          Size      VMA       LMA       File off  Algn\n"
+msgstr ""
+
+#: objdump.c:365
+msgid ""
+"Idx Name          Size      VMA               LMA               File off  "
+"Algn\n"
+msgstr ""
+
+#: objdump.c:414
+#, c-format
+msgid "%s: %s: not a dynamic object\n"
+msgstr ""
+
+#: objdump.c:431
+#, c-format
+msgid "%s: %s: No dynamic symbols\n"
+msgstr ""
+
+#: objdump.c:1131
+msgid "Out of virtual memory\n"
+msgstr ""
+
+#: objdump.c:1532
+#, c-format
+msgid "%s: Can't use supplied machine %s\n"
+msgstr ""
+
+#: objdump.c:1553
+#, c-format
+msgid "%s: Can't disassemble for architecture %s\n"
+msgstr ""
+
+#: objdump.c:1627
+#, c-format
+msgid "Disassembly of section %s:\n"
+msgstr ""
+
+#: objdump.c:1798
+#, c-format
+msgid ""
+"No %s section present\n"
+"\n"
+msgstr ""
+
+#: objdump.c:1805
+#, c-format
+msgid "%s: %s has no %s section\n"
+msgstr ""
+
+#: objdump.c:1818 objdump.c:1829
+#, c-format
+msgid "%s: Reading %s section of %s failed: %s\n"
+msgstr ""
+
+#: objdump.c:1871
+#, c-format
+msgid ""
+"Contents of %s section:\n"
+"\n"
+msgstr ""
+
+#: objdump.c:1971
+#, c-format
+msgid "architecture: %s, "
+msgstr ""
+
+#: objdump.c:1974
+#, c-format
+msgid "flags 0x%08x:\n"
+msgstr ""
+
+#: objdump.c:1987
+msgid ""
+"\n"
+"start address 0x"
+msgstr ""
+
+#: objdump.c:2030
+#, c-format
+msgid ""
+"\n"
+"%s:     file format %s\n"
+msgstr ""
+
+#: objdump.c:2071
+#, c-format
+msgid "%s: printing debugging information failed\n"
+msgstr ""
+
+#: objdump.c:2105
+#, c-format
+msgid "In archive %s:\n"
+msgstr ""
+
+#: objdump.c:2158
+#, c-format
+msgid "Contents of section %s:\n"
+msgstr ""
+
+#: objdump.c:2661
+#, c-format
+msgid "BFD header file version %s\n"
+msgstr ""
+
+#: objdump.c:2786
+#, c-format
+msgid "%s: unrecognized -E option\n"
+msgstr ""
+
+#: objdump.c:2797
+#, c-format
+msgid "%s: unrecognized --endian type `%s'\n"
+msgstr ""
+
+#: rdcoff.c:204
+#, c-format
+msgid "%s: parse_coff_type: Bad type code 0x%x\n"
+msgstr ""
+
+#: rdcoff.c:423 rdcoff.c:531 rdcoff.c:712
+#, c-format
+msgid "%s: bfd_coff_get_syment failed: %s\n"
+msgstr ""
+
+#: rdcoff.c:439 rdcoff.c:732
+#, c-format
+msgid "%s: bfd_coff_get_auxent failed: %s\n"
+msgstr ""
+
+#: rdcoff.c:798
+#, c-format
+msgid "%s: %ld: .bf without preceding function\n"
+msgstr ""
+
+#: rdcoff.c:848
+#, c-format
+msgid "%s: %ld: unexpected .ef\n"
+msgstr ""
+
+#: rddbg.c:87
+#, c-format
+msgid "%s: no recognized debugging information\n"
+msgstr ""
+
+#: rddbg.c:400
+msgid "Last stabs entries before error:\n"
+msgstr ""
+
+#: readelf.c:229 readelf.c:255
+#, c-format
+msgid "%s: Error: "
+msgstr ""
+
+#: readelf.c:241 readelf.c:270
+#, c-format
+msgid "%s: Warning: "
+msgstr ""
+
+#: readelf.c:300 readelf.c:325
+#, c-format
+msgid "Unhandled data length: %d\n"
+msgstr ""
+
+#: readelf.c:420
+msgid "Don't know about relocations on this machine architecture\n"
+msgstr ""
+
+#: readelf.c:426
+msgid ""
+"  Offset    Info  Type            Symbol's Value  Symbol's Name          "
+"Addend\n"
+msgstr ""
+
+#: readelf.c:429
+msgid "  Offset    Info  Type            Symbol's Value  Symbol's Name\n"
+msgstr ""
+
+#: readelf.c:533
+#, c-format
+msgid "unrecognised: %-7lx"
+msgstr ""
+
+#: readelf.c:551
+#, c-format
+msgid "<string table index %3ld>"
+msgstr ""
+
+#: readelf.c:703
+#, c-format
+msgid "Processor Specific: %lx"
+msgstr ""
+
+#: readelf.c:706
+#, c-format
+msgid "Operating System specific: %lx"
+msgstr ""
+
+#: readelf.c:708 readelf.c:961
+#, c-format
+msgid "<unknown>: %lx"
+msgstr ""
+
+#: readelf.c:722
+msgid "NONE (None)"
+msgstr ""
+
+#: readelf.c:723
+msgid "REL (Relocatable file)"
+msgstr ""
+
+#: readelf.c:724
+msgid "EXEC (Executable file)"
+msgstr ""
+
+#: readelf.c:725
+msgid "DYN (Shared object file)"
+msgstr ""
+
+#: readelf.c:726
+msgid "CORE (Core file)"
+msgstr ""
+
+#: readelf.c:730
+#, c-format
+msgid "Processor Specific: (%x)"
+msgstr ""
+
+#: readelf.c:732
+#, c-format
+msgid "OS Specific: (%x)"
+msgstr ""
+
+#: readelf.c:734 readelf.c:793 readelf.c:897 readelf.c:1072
+#, c-format
+msgid "<unknown>: %x"
+msgstr ""
+
+#: readelf.c:747
+msgid "None"
+msgstr ""
+
+#: readelf.c:894
+msgid "ELFDATA2LSB (little endian)"
+msgstr ""
+
+#: readelf.c:895
+msgid "ELFDATA2MSB (big endian)"
+msgstr ""
+
+#: readelf.c:1108
+msgid "Usage: readelf {options} elf-file(s)\n"
+msgstr ""
+
+#: readelf.c:1109
+msgid "  Options are:\n"
+msgstr ""
+
+#: readelf.c:1110
+msgid ""
+"  -a or --all               Equivalent to: -h -l -S -s -r -d -V --histogram\n"
+msgstr ""
+
+#: readelf.c:1111
+msgid "  -h or --file-header       Display the ELF file header\n"
+msgstr ""
+
+#: readelf.c:1112
+msgid "  -l or --program-headers or --segments\n"
+msgstr ""
+
+#: readelf.c:1113
+msgid "                            Display the program headers\n"
+msgstr ""
+
+#: readelf.c:1114
+msgid "  -S or --section-headers or --sections\n"
+msgstr ""
+
+#: readelf.c:1115
+msgid "                            Display the sections' header\n"
+msgstr ""
+
+#: readelf.c:1116
+msgid "  -e or --headers           Equivalent to: -h -l -S\n"
+msgstr ""
+
+#: readelf.c:1117
+msgid "  -s or --syms or --symbols Display the symbol table\n"
+msgstr ""
+
+#: readelf.c:1118
+msgid "  -r or --relocs            Display the relocations (if present)\n"
+msgstr ""
+
+#: readelf.c:1119
+msgid "  -d or --dynamic           Display the dynamic segment (if present)\n"
+msgstr ""
+
+#: readelf.c:1120
+msgid "  -V or --version-info      Display the version sections (if present)\n"
+msgstr ""
+
+#: readelf.c:1121
+msgid ""
+"  -D or --use-dynamic       Use the dynamic section info when displaying "
+"symbols\n"
+msgstr ""
+
+#: readelf.c:1122
+msgid "  -x <number> or --hex-dump=<number>\n"
+msgstr ""
+
+#: readelf.c:1123
+msgid "                            Dump the contents of section <number>\n"
+msgstr ""
+
+#: readelf.c:1124
+msgid "  -w[liapr] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges]\n"
+msgstr ""
+
+#: readelf.c:1125
+msgid ""
+"                            Display the contents of DWARF2 debug sections\n"
+msgstr ""
+
+#: readelf.c:1127
+msgid "  -i <number> or --instruction-dump=<number>\n"
+msgstr ""
+
+#: readelf.c:1128
+msgid ""
+"                            Disassemble the contents of section <number>\n"
+msgstr ""
+
+#: readelf.c:1130
+msgid "        --histogram         Display histogram of bucket list lengths\n"
+msgstr ""
+
+#: readelf.c:1131
+msgid "  -v or --version           Display the version number of readelf\n"
+msgstr ""
+
+#: readelf.c:1132
+msgid "  -H or --help              Display this information\n"
+msgstr ""
+
+#: readelf.c:1150
+msgid "Out of memory allocating dump request table."
+msgstr ""
+
+#: readelf.c:1274
+#, c-format
+msgid "Unrecognised debug option '%s'\n"
+msgstr ""
+
+#: readelf.c:1299
+#, c-format
+msgid "Invalid option '-%c'\n"
+msgstr ""
+
+#: readelf.c:1312
+msgid "Nothing to do.\n"
+msgstr ""
+
+#: readelf.c:1323 readelf.c:1336 readelf.c:2459
+msgid "none"
+msgstr ""
+
+#: readelf.c:1324
+msgid "ELF32"
+msgstr ""
+
+#: readelf.c:1325
+msgid "ELF64"
+msgstr ""
+
+#: readelf.c:1326 readelf.c:1339 readelf.c:1352
+msgid "<unknown>"
+msgstr ""
+
+#: readelf.c:1337
+msgid "2's compilment, little endian"
+msgstr ""
+
+#: readelf.c:1338
+msgid "2's compilment, big endian"
+msgstr ""
+
+#: readelf.c:1349
+msgid "UNIX - System V"
+msgstr ""
+
+#: readelf.c:1350
+msgid "UNIX - HP-UX"
+msgstr ""
+
+#: readelf.c:1351
+msgid "Standalone App"
+msgstr ""
+
+#: readelf.c:1366
+msgid "Not an ELF file - it has the wrong magic bytes at the start\n"
+msgstr ""
+
+#: readelf.c:1374
+msgid "ELF Header:\n"
+msgstr ""
+
+#: readelf.c:1375
+msgid "  Magic:   "
+msgstr ""
+
+#: readelf.c:1379
+#, c-format
+msgid "  Class:                             %s\n"
+msgstr ""
+
+#: readelf.c:1381 readelf.c:1397
+#, c-format
+msgid "  Data:                              %s\n"
+msgstr ""
+
+#: readelf.c:1383
+#, c-format
+msgid "  Version:                           %d %s\n"
+msgstr ""
+
+#: readelf.c:1387
+#, c-format
+msgid "  OS/ABI:                            %s\n"
+msgstr ""
+
+#: readelf.c:1389
+#, c-format
+msgid "  ABI Version:                       %d\n"
+msgstr ""
+
+#: readelf.c:1391
+#, c-format
+msgid "  Type:                              %s\n"
+msgstr ""
+
+#: readelf.c:1393
+#, c-format
+msgid "  Machine:                           %s\n"
+msgstr ""
+
+#: readelf.c:1395
+#, c-format
+msgid "  Version:                           0x%lx\n"
+msgstr ""
+
+#: readelf.c:1399
+#, c-format
+msgid "  Entry point address:               0x%lx\n"
+msgstr ""
+
+#: readelf.c:1401
+#, c-format
+msgid "  Start of program headers:          %ld (bytes into file)\n"
+msgstr ""
+
+#: readelf.c:1403
+#, c-format
+msgid "  Start of section headers:          %ld (bytes into file)\n"
+msgstr ""
+
+#: readelf.c:1405
+#, c-format
+msgid "  Flags:                             0x%lx%s\n"
+msgstr ""
+
+#: readelf.c:1408
+#, c-format
+msgid "  Size of this header:               %ld (bytes)\n"
+msgstr ""
+
+#: readelf.c:1410
+#, c-format
+msgid "  Size of program headers:           %ld (bytes)\n"
+msgstr ""
+
+#: readelf.c:1412
+#, c-format
+msgid "  Number of program headers:         %ld\n"
+msgstr ""
+
+#: readelf.c:1414
+#, c-format
+msgid "  Size of section headers:           %ld (bytes)\n"
+msgstr ""
+
+#: readelf.c:1416
+#, c-format
+msgid "  Number of section headers:         %ld\n"
+msgstr ""
+
+#: readelf.c:1418
+#, c-format
+msgid "  Section header string table index: %ld\n"
+msgstr ""
+
+#: readelf.c:1428
+msgid "Not a 32 bit ELF file\n"
+msgstr ""
+
+#: readelf.c:1448
+msgid ""
+"\n"
+"There are no program headers in this file.\n"
+msgstr ""
+
+#: readelf.c:1454
+#, c-format
+msgid ""
+"\n"
+"Elf file is %s\n"
+msgstr ""
+
+#: readelf.c:1455
+#, c-format
+msgid "Entry point 0x%lx\n"
+msgstr ""
+
+#: readelf.c:1456
+#, c-format
+msgid "There are %d program headers, starting at offset %lx:\n"
+msgstr ""
+
+#: readelf.c:1469 readelf.c:1619 readelf.c:1662 readelf.c:2018 readelf.c:2142
+#: readelf.c:3043 readelf.c:3057
+msgid "Out of memory\n"
+msgstr ""
+
+#: readelf.c:1492
+#, c-format
+msgid ""
+"\n"
+"Program Header%s:\n"
+msgstr ""
+
+#: readelf.c:1494
+msgid ""
+"  Type        Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"
+msgstr ""
+
+#: readelf.c:1529
+msgid "more than one dynamic segment\n"
+msgstr ""
+
+#: readelf.c:1537
+msgid "Unable to find program interpreter name\n"
+msgstr ""
+
+#: readelf.c:1544
+#, c-format
+msgid ""
+"\n"
+"      [Requesting program interpreter: %s]"
+msgstr ""
+
+#: readelf.c:1562
+msgid ""
+"\n"
+" Section to Segment mapping:\n"
+msgstr ""
+
+#: readelf.c:1563
+msgid "  Segment Sections...\n"
+msgstr ""
+
+#: readelf.c:1697
+msgid ""
+"\n"
+"There are no sections in this file.\n"
+msgstr ""
+
+#: readelf.c:1703
+#, c-format
+msgid "There are %d section headers, starting at offset %lx:\n"
+msgstr ""
+
+#: readelf.c:1737
+msgid "File contains multiple dynamic symbol tables\n"
+msgstr ""
+
+#: readelf.c:1750
+msgid "File contains multiple dynamic string tables\n"
+msgstr ""
+
+#: readelf.c:1777
+#, c-format
+msgid ""
+"\n"
+"Section Header%s:\n"
+msgstr ""
+
+#: readelf.c:1779
+msgid ""
+"  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk "
+"Inf Al\n"
+msgstr ""
+
+#: readelf.c:1844
+#, c-format
+msgid ""
+"\n"
+"Relocation section at offset 0x%lx contains %ld bytes:\n"
+msgstr ""
+
+#: readelf.c:1851
+msgid ""
+"\n"
+"There are no dynamic relocations in this file.\n"
+msgstr ""
+
+#: readelf.c:1877
+msgid ""
+"\n"
+"Relocation section "
+msgstr ""
+
+#: readelf.c:1884
+#, c-format
+msgid " at offset 0x%lx contains %lu entries:\n"
+msgstr ""
+
+#: readelf.c:1910
+msgid ""
+"\n"
+"There are no relocations in this file.\n"
+msgstr ""
+
+#: readelf.c:1998
+msgid ""
+"\n"
+"There is no dynamic segment in this file.\n"
+msgstr ""
+
+#: readelf.c:2056
+msgid "Unable to seek to end of file!"
+msgstr ""
+
+#: readelf.c:2062
+msgid "Unable to determine the number of symbols to load\n"
+msgstr ""
+
+#: readelf.c:2092
+msgid "Unable to seek to end of file\n"
+msgstr ""
+
+#: readelf.c:2098
+msgid "Unable to determine the length of the dynamic string table\n"
+msgstr ""
+
+#: readelf.c:2159
+#, c-format
+msgid ""
+"\n"
+"Dynamic segment at offset 0x%x contains %d entries:\n"
+msgstr ""
+
+#: readelf.c:2162
+msgid "  Tag        Type                         Name/Value\n"
+msgstr ""
+
+#: readelf.c:2169
+#, c-format
+msgid "  0x%-8.8lx (%s)%*s"
+msgstr ""
+
+#: readelf.c:2182
+msgid "Auxiliary library"
+msgstr ""
+
+#: readelf.c:2184
+msgid "Filter library"
+msgstr ""
+
+#: readelf.c:2196 readelf.c:2217 readelf.c:2243
+msgid "Flags:"
+msgstr ""
+
+#: readelf.c:2198 readelf.c:2219 readelf.c:2245
+msgid " None\n"
+msgstr ""
+
+#: readelf.c:2348
+#, c-format
+msgid "Shared library: [%s]"
+msgstr ""
+
+#: readelf.c:2353
+msgid " program interpreter\n"
+msgstr ""
+
+#: readelf.c:2357
+#, c-format
+msgid "Library soname: [%s]\n"
+msgstr ""
+
+#: readelf.c:2361
+#, c-format
+msgid "Library rpath: [%s]\n"
+msgstr ""
+
+#: readelf.c:2413
+#, c-format
+msgid "Not needed object: [%s]\n"
+msgstr ""
+
+#: readelf.c:2505
+#, c-format
+msgid ""
+"\n"
+"Version definition section '%s' contains %ld entries:\n"
+msgstr ""
+
+#: readelf.c:2508
+msgid "  Addr: 0x"
+msgstr ""
+
+#: readelf.c:2510 readelf.c:2699
+#, c-format
+msgid "  Offset: %#08lx  Link: %lx (%s)\n"
+msgstr ""
+
+#: readelf.c:2540
+#, c-format
+msgid "  %#06x: Rev: %d  Flags: %s"
+msgstr ""
+
+#: readelf.c:2543
+#, c-format
+msgid "  Index: %d  Cnt: %d  "
+msgstr ""
+
+#: readelf.c:2554
+#, c-format
+msgid "Name: %s\n"
+msgstr ""
+
+#: readelf.c:2556
+#, c-format
+msgid "Name index: %ld\n"
+msgstr ""
+
+#: readelf.c:2571
+#, c-format
+msgid "  %#06x: Parent %d: %s\n"
+msgstr ""
+
+#: readelf.c:2574
+#, c-format
+msgid "  %#06x: Parent %d, name index: %ld\n"
+msgstr ""
+
+#: readelf.c:2593
+#, c-format
+msgid ""
+"\n"
+"Version needs section '%s' contains %ld entries:\n"
+msgstr ""
+
+#: readelf.c:2596
+msgid " Addr: 0x"
+msgstr ""
+
+#: readelf.c:2598
+#, c-format
+msgid "  Offset: %#08lx  Link to section: %ld (%s)\n"
+msgstr ""
+
+#: readelf.c:2624
+#, c-format
+msgid "  %#06x: Version: %d"
+msgstr ""
+
+#: readelf.c:2627
+#, c-format
+msgid "  File: %s"
+msgstr ""
+
+#: readelf.c:2629
+#, c-format
+msgid "  File: %lx"
+msgstr ""
+
+#: readelf.c:2631
+#, c-format
+msgid "  Cnt: %d\n"
+msgstr ""
+
+#: readelf.c:2649
+#, c-format
+msgid "  %#06x: Name: %s"
+msgstr ""
+
+#: readelf.c:2652
+#, c-format
+msgid "  %#06x: Name index: %lx"
+msgstr ""
+
+#: readelf.c:2655
+#, c-format
+msgid "  Flags: %s  Version: %d\n"
+msgstr ""
+
+#: readelf.c:2694
+#, c-format
+msgid ""
+"\n"
+"Version symbols section '%s' contains %d entries:\n"
+msgstr ""
+
+#: readelf.c:2697
+msgid " Addr: "
+msgstr ""
+
+#: readelf.c:2726
+msgid "   0 (*local*)    "
+msgstr ""
+
+#: readelf.c:2730
+msgid "   1 (*global*)   "
+msgstr ""
+
+#: readelf.c:2953
+msgid ""
+"\n"
+"No version information found in this file.\n"
+msgstr ""
+
+#: readelf.c:2966
+msgid "LOCAL"
+msgstr ""
+
+#: readelf.c:2967
+msgid "GLOBAL"
+msgstr ""
+
+#: readelf.c:2968
+msgid "WEAK"
+msgstr ""
+
+#: readelf.c:2971 readelf.c:2995
+#, c-format
+msgid "<processor specific>: %d"
+msgstr ""
+
+#: readelf.c:2973 readelf.c:2997
+#, c-format
+msgid "<OS specific>: %d"
+msgstr ""
+
+#: readelf.c:2975 readelf.c:2999
+#, c-format
+msgid "<unknown>: %d"
+msgstr ""
+
+#: readelf.c:2988
+msgid "NOTYPE"
+msgstr ""
+
+#: readelf.c:2989
+msgid "OBJECT"
+msgstr ""
+
+#: readelf.c:2990
+msgid "FUNC"
+msgstr ""
+
+#: readelf.c:2991
+msgid "SECTION"
+msgstr ""
+
+#: readelf.c:2992
+msgid "FILE"
+msgstr ""
+
+#: readelf.c:3049
+msgid "Unable to read in dynamic data\n"
+msgstr ""
+
+#: readelf.c:3091
+msgid "Unable to seek to start of dynamic information"
+msgstr ""
+
+#: readelf.c:3097
+msgid "Failed to read in number of buckets\n"
+msgstr ""
+
+#: readelf.c:3103
+msgid "Failed to read in number of chains\n"
+msgstr ""
+
+#: readelf.c:3123
+msgid ""
+"\n"
+"Symbol table for image:\n"
+msgstr ""
+
+#: readelf.c:3124
+msgid "  Num Buc:    Value  Size   Type   Bind Ot Ndx Name\n"
+msgstr ""
+
+#: readelf.c:3169
+#, c-format
+msgid ""
+"\n"
+"Symbol table '%s' contains %lu entries:\n"
+msgstr ""
+
+#: readelf.c:3172
+msgid "  Num:    Value  Size Type    Bind   Ot  Ndx Name\n"
+msgstr ""
+
+#: readelf.c:3291
+msgid "bad dynamic symbol"
+msgstr ""
+
+#: readelf.c:3350
+msgid ""
+"\n"
+"Dynamic symbol information is not available for displaying symbols.\n"
+msgstr ""
+
+#: readelf.c:3362
+#, c-format
+msgid ""
+"\n"
+"Histogram for bucket list length (total of %d buckets):\n"
+msgstr ""
+
+#: readelf.c:3364
+msgid " Length  Number     %% of total  Coverage\n"
+msgstr ""
+
+#: readelf.c:3369 readelf.c:3388 readelf.c:5271 readelf.c:5461
+msgid "Out of memory"
+msgstr ""
+
+#: readelf.c:3434
+#, c-format
+msgid ""
+"\n"
+"Dynamic info segment at offset 0x%lx contains %d entries:\n"
+msgstr ""
+
+#: readelf.c:3437
+msgid " Num: Name                           BoundTo     Flags\n"
+msgstr ""
+
+#: readelf.c:3485
+#, c-format
+msgid ""
+"\n"
+"Assembly dump of section %s\n"
+msgstr ""
+
+#: readelf.c:3508
+#, c-format
+msgid ""
+"\n"
+"Section '%s' has no data to dump.\n"
+msgstr ""
+
+#: readelf.c:3513
+#, c-format
+msgid ""
+"\n"
+"Hex dump of section '%s':\n"
+msgstr ""
+
+#: readelf.c:3663
+msgid "badly formed extended line op encountered!"
+msgstr ""
+
+#: readelf.c:3670
+#, c-format
+msgid "  Extended opcode %d: "
+msgstr ""
+
+#: readelf.c:3675
+msgid ""
+"End of Sequence\n"
+"\n"
+msgstr ""
+
+#: readelf.c:3682
+#, c-format
+msgid "set Address to 0x%lx\n"
+msgstr ""
+
+#: readelf.c:3687
+msgid "  define new File Table entry\n"
+msgstr ""
+
+#: readelf.c:3688 readelf.c:3806
+msgid "  Entry\tDir\tTime\tSize\tName\n"
+msgstr ""
+
+#: readelf.c:3690
+#, c-format
+msgid "   %d\t"
+msgstr ""
+
+#: readelf.c:3693 readelf.c:3695 readelf.c:3697 readelf.c:3818 readelf.c:3820
+#: readelf.c:3822
+#, c-format
+msgid "%lu\t"
+msgstr ""
+
+#: readelf.c:3698
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+msgstr ""
+
+#: readelf.c:3702
+#, c-format
+msgid "UNKNOWN: length %d\n"
+msgstr ""
+
+#: readelf.c:3724
+#, c-format
+msgid ""
+"\n"
+"Dump of debug contents of section %s:\n"
+"\n"
+msgstr ""
+
+#: readelf.c:3736
+msgid "The line info appears to be corrupt - the section is too small\n"
+msgstr ""
+
+#: readelf.c:3744
+msgid "Only DWARF version 2 line info is currently supported.\n"
+msgstr ""
+
+#: readelf.c:3759
+#, c-format
+msgid "  Length:                      %ld\n"
+msgstr ""
+
+#: readelf.c:3760
+#, c-format
+msgid "  DWARF Version:               %d\n"
+msgstr ""
+
+#: readelf.c:3761
+#, c-format
+msgid "  Prolgue Length:              %d\n"
+msgstr ""
+
+#: readelf.c:3762
+#, c-format
+msgid "  Minimum Instruction Length:  %d\n"
+msgstr ""
+
+#: readelf.c:3763
+#, c-format
+msgid "  Initial value of 'is_stmt':  %d\n"
+msgstr ""
+
+#: readelf.c:3764
+#, c-format
+msgid "  Line Base:                   %d\n"
+msgstr ""
+
+#: readelf.c:3765
+#, c-format
+msgid "  Line Range:                  %d\n"
+msgstr ""
+
+#: readelf.c:3766
+#, c-format
+msgid "  Opcode Base:                 %d\n"
+msgstr ""
+
+#: readelf.c:3775
+msgid ""
+"\n"
+" Opcodes:\n"
+msgstr ""
+
+#: readelf.c:3778
+#, c-format
+msgid "  Opcode %d has %d args\n"
+msgstr ""
+
+#: readelf.c:3784
+msgid ""
+"\n"
+" The Directory Table is empty.\n"
+msgstr ""
+
+#: readelf.c:3787
+msgid ""
+"\n"
+" The Directory Table:\n"
+msgstr ""
+
+#: readelf.c:3791
+#, c-format
+msgid "  %s\n"
+msgstr ""
+
+#: readelf.c:3802
+msgid ""
+"\n"
+" The File Name Table is empty.\n"
+msgstr ""
+
+#: readelf.c:3805
+msgid ""
+"\n"
+" The File Name Table:\n"
+msgstr ""
+
+#: readelf.c:3813
+#, c-format
+msgid "  %d\t"
+msgstr ""
+
+#: readelf.c:3824
+#, c-format
+msgid "%s\n"
+msgstr ""
+
+#. Now display the statements.
+#: readelf.c:3832
+msgid ""
+"\n"
+" Line Number Statements:\n"
+msgstr ""
+
+#: readelf.c:3850
+msgid "  Copy\n"
+msgstr ""
+
+#: readelf.c:3857
+#, c-format
+msgid "  Advance PC by %d to %lx\n"
+msgstr ""
+
+#: readelf.c:3865
+#, c-format
+msgid "  Advance Line by %d to %d\n"
+msgstr ""
+
+#: readelf.c:3872
+#, c-format
+msgid "  Set File Name to entry %d in the File Name Table\n"
+msgstr ""
+
+#: readelf.c:3880
+#, c-format
+msgid "  Set column to %d\n"
+msgstr ""
+
+#: readelf.c:3887
+#, c-format
+msgid "  Set is_stmt to %d\n"
+msgstr ""
+
+#: readelf.c:3892
+msgid "  Set basic block\n"
+msgstr ""
+
+#: readelf.c:3899
+#, c-format
+msgid "  Advance PC by constant %d to 0x%lx\n"
+msgstr ""
+
+#: readelf.c:3907
+#, c-format
+msgid "  Advance PC by fixed size amount %d to 0x%lx\n"
+msgstr ""
+
+#: readelf.c:3915
+#, c-format
+msgid "  Special opcode %d: advance Address by %d to 0x%lx"
+msgstr ""
+
+#: readelf.c:3919
+#, c-format
+msgid " and Line by %d to %d\n"
+msgstr ""
+
+#: readelf.c:3942 readelf.c:4361
+#, c-format
+msgid ""
+"Contents of the %s section:\n"
+"\n"
+msgstr ""
+
+#: readelf.c:3961
+msgid "Only DWARF 2 pubnames are currently supported"
+msgstr ""
+
+#: readelf.c:3965
+#, c-format
+msgid "  Length:                              %ld\n"
+msgstr ""
+
+#: readelf.c:3967
+#, c-format
+msgid "  Version:                             %d\n"
+msgstr ""
+
+#: readelf.c:3969
+#, c-format
+msgid "  Offset into .debug_info section:     %ld\n"
+msgstr ""
+
+#: readelf.c:3971
+#, c-format
+msgid "  Size of area in .debug_info section: %ld\n"
+msgstr ""
+
+#: readelf.c:3974
+msgid ""
+"\n"
+"    Offset\tName\n"
+msgstr ""
+
+#: readelf.c:4056
+#, c-format
+msgid "Unknown TAG value: %lx"
+msgstr ""
+
+#: readelf.c:4151
+#, c-format
+msgid "Unknown AT value: %lx"
+msgstr ""
+
+#: readelf.c:4188
+#, c-format
+msgid "Unknown FORM value: %lx"
+msgstr ""
+
+#: readelf.c:4367
+msgid "  Number TAG\n"
+msgstr ""
+
+#: readelf.c:4373
+#, c-format
+msgid "   %ld      %s    [%s]\n"
+msgstr ""
+
+#: readelf.c:4376
+msgid "has children"
+msgstr ""
+
+#: readelf.c:4376
+msgid "no children"
+msgstr ""
+
+#: readelf.c:4380
+#, c-format
+msgid "    %-18s %s\n"
+msgstr ""
+
+#: readelf.c:4399
+#, c-format
+msgid " %lu byte block: "
+msgstr ""
+
+#: readelf.c:4568
+msgid "(User defined location op)"
+msgstr ""
+
+#: readelf.c:4570
+msgid "(Unknown location op)"
+msgstr ""
+
+#: readelf.c:4687
+#, c-format
+msgid "Unable to handle FORM: %d"
+msgstr ""
+
+#: readelf.c:4691
+#, c-format
+msgid "Unrecognised form: %d"
+msgstr ""
+
+#: readelf.c:4704
+msgid "(not inlined)"
+msgstr ""
+
+#: readelf.c:4705
+msgid "(inlined)"
+msgstr ""
+
+#: readelf.c:4706
+msgid "(declared as inline but ignored)"
+msgstr ""
+
+#: readelf.c:4707
+msgid "(declared as inline and inlined)"
+msgstr ""
+
+#: readelf.c:4708
+#, c-format
+msgid "  (Unknown inline attribute value: %lx)"
+msgstr ""
+
+#: readelf.c:4838 readelf.c:4962
+#, c-format
+msgid ""
+"The section %s contains:\n"
+"\n"
+msgstr ""
+
+#: readelf.c:4860
+msgid "Only version 2 DWARF debug information is currently supported.\n"
+msgstr ""
+
+#: readelf.c:4864
+msgid "  Compilation Unit:\n"
+msgstr ""
+
+#: readelf.c:4865
+#, c-format
+msgid "   Length:        %ld\n"
+msgstr ""
+
+#: readelf.c:4866
+#, c-format
+msgid "   Version:       %d\n"
+msgstr ""
+
+#: readelf.c:4867
+#, c-format
+msgid "   Abbrev Offset: %ld\n"
+msgstr ""
+
+#: readelf.c:4868
+#, c-format
+msgid "   Pointer Size:  %d\n"
+msgstr ""
+
+#: readelf.c:4888
+msgid "Unable to locate .debug_abbrev section!\n"
+msgstr ""
+
+#: readelf.c:4928
+#, c-format
+msgid "Unable to locate entry %d in the abbreviation table\n"
+msgstr ""
+
+#: readelf.c:4933
+#, c-format
+msgid " <%d><%x>: Abbrev Number: %d (%s)\n"
+msgstr ""
+
+#: readelf.c:4980
+#, c-format
+msgid "  Length:                   %ld\n"
+msgstr ""
+
+#: readelf.c:4981
+#, c-format
+msgid "  Version:                  %d\n"
+msgstr ""
+
+#: readelf.c:4982
+#, c-format
+msgid "  Offset into .debug_info:  %lx\n"
+msgstr ""
+
+#: readelf.c:4983
+#, c-format
+msgid "  Pointer Size:             %d\n"
+msgstr ""
+
+#: readelf.c:4984
+#, c-format
+msgid "  Segment Size:             %d\n"
+msgstr ""
+
+#: readelf.c:4986
+msgid ""
+"\n"
+"    Address  Length\n"
+msgstr ""
+
+#: readelf.c:5021
+#, c-format
+msgid "Displaying the debug contents of section %s is not yet supported.\n"
+msgstr ""
+
+#: readelf.c:5063
+#, c-format
+msgid ""
+"\n"
+"Section '%s' has no debugging data.\n"
+msgstr ""
+
+#: readelf.c:5079
+#, c-format
+msgid "Unrecognised debug section: %s\n"
+msgstr ""
+
+#: readelf.c:5118
+msgid "Some sections were not dumped because they do not exist!\n"
+msgstr ""
+
+#: readelf.c:5293
+#, c-format
+msgid ""
+"\n"
+"Section '%s' contains %d entries:\n"
+msgstr ""
+
+#: readelf.c:5454
+msgid "conflict list with without table"
+msgstr ""
+
+#: readelf.c:5482
+#, c-format
+msgid ""
+"\n"
+"Section '.conflict' contains %d entries:\n"
+msgstr ""
+
+#: readelf.c:5483
+msgid "  Num:    Index       Value  Name"
+msgstr ""
+
+#: readelf.c:5560
+#, c-format
+msgid "Cannot stat input file %s.\n"
+msgstr ""
+
+#: readelf.c:5567
+#, c-format
+msgid "Input file %s not found.\n"
+msgstr ""
+
+#: readelf.c:5573
+#, c-format
+msgid "%s: Failed to read file header\n"
+msgstr ""
+
+#: readelf.c:5587
+#, c-format
+msgid ""
+"\n"
+"File: %s\n"
+msgstr ""
+
+#: rename.c:121
+#, c-format
+msgid "%s: cannot set time: %s"
+msgstr ""
+
+#. We have to clean up here.
+#: rename.c:160 rename.c:193
+#, c-format
+msgid "%s: rename: %s"
+msgstr ""
+
+#: rename.c:201
+#, c-format
+msgid "%s: simple_copy: %s"
+msgstr ""
+
+#: resbin.c:130
+#, c-format
+msgid "%s: not enough binary data"
+msgstr ""
+
+#: resbin.c:149
+msgid "null terminated unicode string"
+msgstr ""
+
+#: resbin.c:179 resbin.c:185
+msgid "resource ID"
+msgstr ""
+
+#: resbin.c:229
+msgid "cursor"
+msgstr ""
+
+#: resbin.c:263 resbin.c:270
+msgid "menu header"
+msgstr ""
+
+#: resbin.c:280
+msgid "menuex header"
+msgstr ""
+
+#: resbin.c:284
+msgid "menuex offset"
+msgstr ""
+
+#: resbin.c:291
+#, c-format
+msgid "unsupported menu version %d"
+msgstr ""
+
+#: resbin.c:319 resbin.c:334 resbin.c:400
+msgid "menuitem header"
+msgstr ""
+
+#: resbin.c:430
+msgid "menuitem"
+msgstr ""
+
+#: resbin.c:471 resbin.c:499
+msgid "dialog header"
+msgstr ""
+
+#: resbin.c:489
+#, c-format
+msgid "unexpected dialog signature %d"
+msgstr ""
+
+#: resbin.c:531
+msgid "dialog font point size"
+msgstr ""
+
+#: resbin.c:539
+msgid "dialogex font information"
+msgstr ""
+
+#: resbin.c:564 resbin.c:582
+msgid "dialog control"
+msgstr ""
+
+#: resbin.c:574
+msgid "dialogex control"
+msgstr ""
+
+#: resbin.c:603
+msgid "dialog control end"
+msgstr ""
+
+#: resbin.c:615
+msgid "dialog control data"
+msgstr ""
+
+#: resbin.c:658
+msgid "stringtable string length"
+msgstr ""
+
+#: resbin.c:668
+msgid "stringtable string"
+msgstr ""
+
+#: resbin.c:701
+msgid "fontdir header"
+msgstr ""
+
+#: resbin.c:714
+msgid "fontdir"
+msgstr ""
+
+#: resbin.c:730
+msgid "fontdir device name"
+msgstr ""
+
+#: resbin.c:736
+msgid "fontdir face name"
+msgstr ""
+
+#: resbin.c:779
+msgid "accelerator"
+msgstr ""
+
+#: resbin.c:843
+msgid "group cursor header"
+msgstr ""
+
+#: resbin.c:847
+#, c-format
+msgid "unexpected group cursor type %d"
+msgstr ""
+
+#: resbin.c:862
+msgid "group cursor"
+msgstr ""
+
+#: resbin.c:901
+msgid "group icon header"
+msgstr ""
+
+#: resbin.c:905
+#, c-format
+msgid "unexpected group icon type %d"
+msgstr ""
+
+#: resbin.c:920
+msgid "group icon"
+msgstr ""
+
+#: resbin.c:991 resbin.c:1210
+msgid "unexpected version string"
+msgstr ""
+
+#: resbin.c:1025
+#, c-format
+msgid "version length %d does not match resource length %lu"
+msgstr ""
+
+#: resbin.c:1029
+#, c-format
+msgid "unexpected version type %d"
+msgstr ""
+
+#: resbin.c:1041
+#, c-format
+msgid "unexpected fixed version information length %d"
+msgstr ""
+
+#: resbin.c:1044
+msgid "fixed version info"
+msgstr ""
+
+#: resbin.c:1048
+#, c-format
+msgid "unexpected fixed version signature %lu"
+msgstr ""
+
+#: resbin.c:1052
+#, c-format
+msgid "unexpected fixed version info version %lu"
+msgstr ""
+
+#: resbin.c:1081
+msgid "version var info"
+msgstr ""
+
+#: resbin.c:1098
+#, c-format
+msgid "unexpected stringfileinfo value length %d"
+msgstr ""
+
+#: resbin.c:1108
+#, c-format
+msgid "unexpected version stringtable value length %d"
+msgstr ""
+
+#: resbin.c:1142
+#, c-format
+msgid "unexpected version string length %d != %d + %d"
+msgstr ""
+
+#: resbin.c:1153
+#, c-format
+msgid "unexpected version string length %d < %d"
+msgstr ""
+
+#: resbin.c:1170
+#, c-format
+msgid "unexpected varfileinfo value length %d"
+msgstr ""
+
+#: resbin.c:1189
+msgid "version varfileinfo"
+msgstr ""
+
+#: resbin.c:1204
+#, c-format
+msgid "unexpected version value length %d"
+msgstr ""
+
+#: rescoff.c:128
+msgid "filename required for COFF input"
+msgstr ""
+
+#: rescoff.c:145
+#, c-format
+msgid "%s: %s: no resource section\n"
+msgstr ""
+
+#: rescoff.c:154
+msgid "can't read resource section"
+msgstr ""
+
+#: rescoff.c:180
+#, c-format
+msgid "%s: %s: address out of bounds"
+msgstr ""
+
+#: rescoff.c:199
+msgid "directory"
+msgstr ""
+
+#: rescoff.c:227
+msgid "named directory entry"
+msgstr ""
+
+#: rescoff.c:236
+msgid "directory entry name"
+msgstr ""
+
+#: rescoff.c:256
+msgid "named subdirectory"
+msgstr ""
+
+#: rescoff.c:264
+msgid "named resource"
+msgstr ""
+
+#: rescoff.c:279
+msgid "ID directory entry"
+msgstr ""
+
+#: rescoff.c:296
+msgid "ID subdirectory"
+msgstr ""
+
+#: rescoff.c:304
+msgid "ID resource"
+msgstr ""
+
+#: rescoff.c:330
+msgid "resource type unknown"
+msgstr ""
+
+#: rescoff.c:333
+msgid "data entry"
+msgstr ""
+
+#: rescoff.c:341
+msgid "resource data"
+msgstr ""
+
+#: rescoff.c:346
+msgid "resource data size"
+msgstr ""
+
+#: rescoff.c:441
+msgid "filename required for COFF output"
+msgstr ""
+
+#: rescoff.c:729
+msgid "can't get BFD_RELOC_RVA relocation type"
+msgstr ""
+
+#: resrc.c:150
+#, c-format
+msgid "can't popen `%s': %s"
+msgstr ""
+
+#: resrc.c:163
+#, c-format
+msgid "%s: warning: preprocessor failed\n"
+msgstr ""
+
+#: resrc.c:208
+#, c-format
+msgid "%s: unexpected EOF"
+msgstr ""
+
+#: resrc.c:265
+#, c-format
+msgid "%s: read of %lu returned %lu"
+msgstr ""
+
+#: resrc.c:307 resrc.c:538 resrc.c:811 resrc.c:965
+#, c-format
+msgid "stat failed on bitmap file `%s': %s"
+msgstr ""
+
+#: resrc.c:360
+#, c-format
+msgid "cursor file `%s' does not contain cursor data"
+msgstr ""
+
+#: resrc.c:392 resrc.c:682
+#, c-format
+msgid "%s: fseek to %lu failed: %s"
+msgstr ""
+
+#: resrc.c:651
+#, c-format
+msgid "icon file `%s' does not contain icon data"
+msgstr ""
+
+#: resrc.c:1170
+#, c-format
+msgid "can't open `%s' for output: %s"
+msgstr ""
+
+#: size.c:79
+#, c-format
+msgid ""
+"Usage: %s [-ABdoxV] [--format=berkeley|sysv] [--radix=8|10|16]\n"
+"       [--target=bfdname] [--version] [--help] [file...]\n"
+msgstr ""
+
+#: size.c:83
+msgid "default is --format=berkeley\n"
+msgstr ""
+
+#: size.c:85
+msgid "default is --format=sysv\n"
+msgstr ""
+
+#: size.c:139
+#, c-format
+msgid "invalid argument to --format: %s\n"
+msgstr ""
+
+#: size.c:166
+#, c-format
+msgid "Invalid radix: %s\n"
+msgstr ""
+
+#: srconv.c:1879
+#, c-format
+msgid "Usage: %s [-dhVq] in-file [out-file]\n"
+msgstr ""
+
+#: srconv.c:1886
+#, c-format
+msgid "%s: Convert a COFF object file into a SYSROFF object file\n"
+msgstr ""
+
+#: srconv.c:2024
+#, c-format
+msgid "%s: unable to open output file %s\n"
+msgstr ""
+
+#: stabs.c:349 stabs.c:1762
+msgid "numeric overflow"
+msgstr ""
+
+#: stabs.c:360
+#, c-format
+msgid "Bad stab: %s\n"
+msgstr ""
+
+#: stabs.c:370
+#, c-format
+msgid "Warning: %s: %s\n"
+msgstr ""
+
+#: stabs.c:492
+msgid "N_LBRAC not within function\n"
+msgstr ""
+
+#: stabs.c:531
+msgid "Too many N_RBRACs\n"
+msgstr ""
+
+#: stabs.c:780
+msgid "unknown C++ encoded name"
+msgstr ""
+
+#. Complain and keep going, so compilers can invent new
+#. cross-reference types.
+#: stabs.c:1306
+msgid "unrecognized cross reference type"
+msgstr ""
+
+#. Does this actually ever happen?  Is that why we are worrying
+#. about dealing with it rather than just calling error_type?
+#: stabs.c:1854
+msgid "missing index type"
+msgstr ""
+
+#: stabs.c:2181
+msgid "unknown virtual character for baseclass"
+msgstr ""
+
+#: stabs.c:2199
+msgid "unknown visibility character for baseclass"
+msgstr ""
+
+#: stabs.c:2391
+msgid "unnamed $vb type"
+msgstr ""
+
+#: stabs.c:2397
+msgid "unrecognized C++ abbreviation"
+msgstr ""
+
+#: stabs.c:2477
+msgid "unknown visibility character for field"
+msgstr ""
+
+#: stabs.c:2733
+msgid "const/volatile indicator missing"
+msgstr ""
+
+#: stabs.c:2973
+#, c-format
+msgid "No mangling for \"%s\"\n"
+msgstr ""
+
+#: stabs.c:3286
+msgid "Undefined N_EXCL"
+msgstr ""
+
+#: stabs.c:3374
+#, c-format
+msgid "Type file number %d out of range\n"
+msgstr ""
+
+#: stabs.c:3379
+#, c-format
+msgid "Type index number %d out of range\n"
+msgstr ""
+
+#: stabs.c:3466
+#, c-format
+msgid "Unrecognized XCOFF type %d\n"
+msgstr ""
+
+#: stabs.c:3765
+#, c-format
+msgid "bad mangled name `%s'\n"
+msgstr ""
+
+#: stabs.c:3861
+msgid "no argument types in mangled string\n"
+msgstr ""
+
+#: strings.c:159
+#, c-format
+msgid "%s: invalid number %s\n"
+msgstr ""
+
+#: strings.c:494
+#, c-format
+msgid "%s: invalid integer argument %s\n"
+msgstr ""
+
+#: strings.c:505
+#, c-format
+msgid ""
+"Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n"
+"       [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n"
+"       [--target=bfdname] [--help] [--version] file...\n"
+msgstr ""
+
+#: sysdump.c:712
+#, c-format
+msgid "Usage: %s [-hV] in-file\n"
+msgstr ""
+
+#: sysdump.c:783
+#, c-format
+msgid "%s: cannot open input file %s\n"
+msgstr ""
+
+#: version.c:39
+msgid "Copyright 1997, 1998, 1999 Free Software Foundation, Inc.\n"
+msgstr ""
+
+#: version.c:40
+msgid ""
+"This program is free software; you may redistribute it under the terms of\n"
+"the GNU General Public License.  This program has absolutely no warranty.\n"
+msgstr ""
+
+#: windres.c:228
+#, c-format
+msgid "can't open %s `%s': %s"
+msgstr ""
+
+#: windres.c:407
+msgid ": expected to be a directory\n"
+msgstr ""
+
+#: windres.c:419
+msgid ": expected to be a leaf\n"
+msgstr ""
+
+#: windres.c:428
+#, c-format
+msgid "%s: warning: "
+msgstr ""
+
+#: windres.c:430
+msgid ": duplicate value\n"
+msgstr ""
+
+#: windres.c:593
+#, c-format
+msgid "%s: unknown format type `%s'\n"
+msgstr ""
+
+#: windres.c:594
+#, c-format
+msgid "%s: supported formats:"
+msgstr ""
+
+#. Otherwise, we give up.
+#: windres.c:681
+#, c-format
+msgid "can not determine type of file `%s'; use the -I option"
+msgstr ""
+
+#: windres.c:695
+#, c-format
+msgid "Usage: %s [options] [input-file] [output-file]\n"
+msgstr ""
+
+#: windres.c:697
+msgid ""
+"Options:\n"
+"  -i FILE, --input FILE       Name input file\n"
+"  -o FILE, --output FILE      Name output file\n"
+"  -I FORMAT, --input-format FORMAT\n"
+"                              Specify input format\n"
+"  -O FORMAT, --output-format FORMAT\n"
+"                              Specify output format\n"
+"  -F TARGET, --target TARGET  Specify COFF target\n"
+"  --preprocessor PROGRAM      Program to use to preprocess rc file\n"
+"  --include-dir DIR           Include directory when preprocessing rc file\n"
+"  --define SYM[=VAL]          Define SYM when preprocessing rc file\n"
+"  --language VAL              Set language when reading rc file\n"
+msgstr ""
+
+#: windres.c:711
+msgid "  --yydebug                   Turn on parser debugging\n"
+msgstr ""
+
+#: windres.c:714
+msgid ""
+"  --help                      Print this help message\n"
+"  --version                   Print version information\n"
+msgstr ""
+
+#: windres.c:717
+msgid ""
+"FORMAT is one of rc, res, or coff, and is deduced from the file name\n"
+"extension if not specified.  A single file name is an input file.\n"
+"No input-file is stdin, default rc.  No output-file is stdout, default rc.\n"
+msgstr ""
+
+#: windres.c:918
+msgid "no resources"
+msgstr ""
+
+#: wrstabs.c:366 wrstabs.c:2028
+#, c-format
+msgid "string_hash_lookup failed: %s\n"
+msgstr ""
+
+#: wrstabs.c:666
+#, c-format
+msgid "stab_int_type: bad size %u\n"
+msgstr ""
+
+#: wrstabs.c:1468
+#, c-format
+msgid "%s: warning: unknown size for field `%s' in struct\n"
+msgstr ""
diff --git a/binutils/prdbg.c b/binutils/prdbg.c
new file mode 100644 (file)
index 0000000..958cbd2
--- /dev/null
@@ -0,0 +1,1862 @@
+/* prdbg.c -- Print out generic debugging information.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file prints out the generic debugging information, by
+   supplying a set of routines to debug_write.  */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* This is the structure we use as a handle for these routines.  */
+
+struct pr_handle
+{
+  /* File to print information to.  */
+  FILE *f;
+  /* Current indentation level.  */
+  unsigned int indent;
+  /* Type stack.  */
+  struct pr_stack *stack;
+  /* Parameter number we are about to output.  */
+  int parameter;
+};
+
+/* The type stack.  */
+
+struct pr_stack
+{
+  /* Next element on the stack.  */
+  struct pr_stack *next;
+  /* This element.  */
+  char *type;
+  /* Current visibility of fields if this is a class.  */
+  enum debug_visibility visibility;
+  /* Name of the current method we are handling.  */
+  const char *method;
+};
+
+static void indent PARAMS ((struct pr_handle *));
+static boolean push_type PARAMS ((struct pr_handle *, const char *));
+static boolean prepend_type PARAMS ((struct pr_handle *, const char *));
+static boolean append_type PARAMS ((struct pr_handle *, const char *));
+static boolean substitute_type PARAMS ((struct pr_handle *, const char *));
+static boolean indent_type PARAMS ((struct pr_handle *));
+static char *pop_type PARAMS ((struct pr_handle *));
+static void print_vma PARAMS ((bfd_vma, char *, boolean, boolean));
+static boolean pr_fix_visibility
+  PARAMS ((struct pr_handle *, enum debug_visibility));
+
+static boolean pr_start_compilation_unit PARAMS ((PTR, const char *));
+static boolean pr_start_source PARAMS ((PTR, const char *));
+static boolean pr_empty_type PARAMS ((PTR));
+static boolean pr_void_type PARAMS ((PTR));
+static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean));
+static boolean pr_float_type PARAMS ((PTR, unsigned int));
+static boolean pr_complex_type PARAMS ((PTR, unsigned int));
+static boolean pr_bool_type PARAMS ((PTR, unsigned int));
+static boolean pr_enum_type
+  PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static boolean pr_pointer_type PARAMS ((PTR));
+static boolean pr_function_type PARAMS ((PTR, int, boolean));
+static boolean pr_reference_type PARAMS ((PTR));
+static boolean pr_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+static boolean pr_array_type
+  PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
+static boolean pr_set_type PARAMS ((PTR, boolean));
+static boolean pr_offset_type PARAMS ((PTR));
+static boolean pr_method_type PARAMS ((PTR, boolean, int, boolean));
+static boolean pr_const_type PARAMS ((PTR));
+static boolean pr_volatile_type PARAMS ((PTR));
+static boolean pr_start_struct_type
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
+static boolean pr_struct_field
+  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static boolean pr_end_struct_type PARAMS ((PTR));
+static boolean pr_start_class_type
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+          boolean));
+static boolean pr_class_static_member
+  PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static boolean pr_class_baseclass
+  PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
+static boolean pr_class_start_method PARAMS ((PTR, const char *));
+static boolean pr_class_method_variant
+  PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
+          bfd_vma, boolean));
+static boolean pr_class_static_method_variant
+  PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
+static boolean pr_class_end_method PARAMS ((PTR));
+static boolean pr_end_class_type PARAMS ((PTR));
+static boolean pr_typedef_type PARAMS ((PTR, const char *));
+static boolean pr_tag_type
+  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static boolean pr_typdef PARAMS ((PTR, const char *));
+static boolean pr_tag PARAMS ((PTR, const char *));
+static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean pr_float_constant PARAMS ((PTR, const char *, double));
+static boolean pr_typed_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean pr_variable
+  PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static boolean pr_start_function PARAMS ((PTR, const char *, boolean));
+static boolean pr_function_parameter
+  PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static boolean pr_start_block PARAMS ((PTR, bfd_vma));
+static boolean pr_end_block PARAMS ((PTR, bfd_vma));
+static boolean pr_end_function PARAMS ((PTR));
+static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
+static const struct debug_write_fns pr_fns =
+{
+  pr_start_compilation_unit,
+  pr_start_source,
+  pr_empty_type,
+  pr_void_type,
+  pr_int_type,
+  pr_float_type,
+  pr_complex_type,
+  pr_bool_type,
+  pr_enum_type,
+  pr_pointer_type,
+  pr_function_type,
+  pr_reference_type,
+  pr_range_type,
+  pr_array_type,
+  pr_set_type,
+  pr_offset_type,
+  pr_method_type,
+  pr_const_type,
+  pr_volatile_type,
+  pr_start_struct_type,
+  pr_struct_field,
+  pr_end_struct_type,
+  pr_start_class_type,
+  pr_class_static_member,
+  pr_class_baseclass,
+  pr_class_start_method,
+  pr_class_method_variant,
+  pr_class_static_method_variant,
+  pr_class_end_method,
+  pr_end_class_type,
+  pr_typedef_type,
+  pr_tag_type,
+  pr_typdef,
+  pr_tag,
+  pr_int_constant,
+  pr_float_constant,
+  pr_typed_constant,
+  pr_variable,
+  pr_start_function,
+  pr_function_parameter,
+  pr_start_block,
+  pr_end_block,
+  pr_end_function,
+  pr_lineno
+};
+\f
+/* Print out the generic debugging information recorded in dhandle.  */
+
+boolean
+print_debugging_info (f, dhandle)
+     FILE *f;
+     PTR dhandle;
+{
+  struct pr_handle info;
+
+  info.f = f;
+  info.indent = 0;
+  info.stack = NULL;
+  info.parameter = 0;
+
+  return debug_write (dhandle, &pr_fns, (PTR) &info);
+}
+\f
+/* Indent to the current indentation level.  */
+
+static void
+indent (info)
+     struct pr_handle *info;
+{
+  unsigned int i;
+
+  for (i = 0; i < info->indent; i++)
+    putc (' ', info->f);
+}
+
+/* Push a type on the type stack.  */
+
+static boolean
+push_type (info, type)
+     struct pr_handle *info;
+     const char *type;
+{
+  struct pr_stack *n;
+
+  if (type == NULL)
+    return false;
+
+  n = (struct pr_stack *) xmalloc (sizeof *n);
+  memset (n, 0, sizeof *n);
+
+  n->type = xstrdup (type);
+  n->visibility = DEBUG_VISIBILITY_IGNORE;
+  n->method = NULL;
+  n->next = info->stack;
+  info->stack = n;
+
+  return true;
+}
+
+/* Prepend a string onto the type on the top of the type stack.  */
+
+static boolean
+prepend_type (info, s)
+     struct pr_handle *info;
+     const char *s;
+{
+  char *n;
+
+  assert (info->stack != NULL);
+
+  n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
+  sprintf (n, "%s%s", s, info->stack->type);
+  free (info->stack->type);
+  info->stack->type = n;
+
+  return true;
+}
+
+/* Append a string to the type on the top of the type stack.  */
+
+static boolean
+append_type (info, s)
+     struct pr_handle *info;
+     const char *s;
+{
+  unsigned int len;
+
+  if (s == NULL)
+    return false;
+
+  assert (info->stack != NULL);
+
+  len = strlen (info->stack->type);
+  info->stack->type = (char *) xrealloc (info->stack->type,
+                                        len + strlen (s) + 1);
+  strcpy (info->stack->type + len, s);
+
+  return true;
+}
+
+/* We use an underscore to indicate where the name should go in a type
+   string.  This function substitutes a string for the underscore.  If
+   there is no underscore, the name follows the type.  */
+
+static boolean
+substitute_type (info, s)
+     struct pr_handle *info;
+     const char *s;
+{
+  char *u;
+
+  assert (info->stack != NULL);
+
+  u = strchr (info->stack->type, '|');
+  if (u != NULL)
+    {
+      char *n;
+
+      n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
+
+      memcpy (n, info->stack->type, u - info->stack->type);
+      strcpy (n + (u - info->stack->type), s);
+      strcat (n, u + 1);
+
+      free (info->stack->type);
+      info->stack->type = n;
+
+      return true;
+    }
+
+  if (strchr (s, '|') != NULL
+      && (strchr (info->stack->type, '{') != NULL
+         || strchr (info->stack->type, '(') != NULL))
+    {
+      if (! prepend_type (info, "(")
+         || ! append_type (info, ")"))
+       return false;
+    }
+
+  if (*s == '\0')
+    return true;
+
+  return (append_type (info, " ")
+         && append_type (info, s));
+}
+
+/* Indent the type at the top of the stack by appending spaces.  */
+
+static boolean
+indent_type (info)
+     struct pr_handle *info;
+{
+  unsigned int i;
+
+  for (i = 0; i < info->indent; i++)
+    {
+      if (! append_type (info, " "))
+       return false;
+    }
+
+  return true;
+}
+
+/* Pop a type from the type stack.  */
+
+static char *
+pop_type (info)
+     struct pr_handle *info;
+{
+  struct pr_stack *o;
+  char *ret;
+
+  assert (info->stack != NULL);
+
+  o = info->stack;
+  info->stack = o->next;
+  ret = o->type;
+  free (o);
+
+  return ret;
+}
+
+/* Print a VMA value into a string.  */
+
+static void
+print_vma (vma, buf, unsignedp, hexp)
+     bfd_vma vma;
+     char *buf;
+     boolean unsignedp;
+     boolean hexp;
+{
+  if (sizeof (vma) <= sizeof (unsigned long))
+    {
+      if (hexp)
+       sprintf (buf, "0x%lx", (unsigned long) vma);
+      else if (unsignedp)
+       sprintf (buf, "%lu", (unsigned long) vma);
+      else
+       sprintf (buf, "%ld", (long) vma);
+    }
+  else
+    {
+      buf[0] = '0';
+      buf[1] = 'x';
+      sprintf_vma (buf + 2, vma);
+    }
+}
+\f
+/* Start a new compilation unit.  */
+
+static boolean
+pr_start_compilation_unit (p, filename)
+     PTR p;
+     const char *filename;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  assert (info->indent == 0);
+
+  fprintf (info->f, "%s:\n", filename);
+
+  return true;
+}
+
+/* Start a source file within a compilation unit.  */
+
+static boolean
+pr_start_source (p, filename)
+     PTR p;
+     const char *filename;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  assert (info->indent == 0);
+
+  fprintf (info->f, " %s:\n", filename);
+
+  return true;
+}
+
+/* Push an empty type onto the type stack.  */
+
+static boolean
+pr_empty_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  return push_type (info, "<undefined>");
+}
+
+/* Push a void type onto the type stack.  */
+
+static boolean
+pr_void_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  return push_type (info, "void");
+}
+
+/* Push an integer type onto the type stack.  */
+
+static boolean
+pr_int_type (p, size, unsignedp)
+     PTR p;
+     unsigned int size;
+     boolean unsignedp;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[10];
+
+  sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8);
+  return push_type (info, ab);
+}
+
+/* Push a floating type onto the type stack.  */
+
+static boolean
+pr_float_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[10];
+
+  if (size == 4)
+    return push_type (info, "float");
+  else if (size == 8)
+    return push_type (info, "double");
+
+  sprintf (ab, "float%d", size * 8);
+  return push_type (info, ab);
+}
+
+/* Push a complex type onto the type stack.  */
+
+static boolean
+pr_complex_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  if (! pr_float_type (p, size))
+    return false;
+
+  return prepend_type (info, "complex ");
+}
+
+/* Push a boolean type onto the type stack.  */
+
+static boolean
+pr_bool_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[10];
+
+  sprintf (ab, "bool%d", size * 8);
+
+  return push_type (info, ab);
+}
+
+/* Push an enum type onto the type stack.  */
+
+static boolean
+pr_enum_type (p, tag, names, values)
+     PTR p;
+     const char *tag;
+     const char **names;
+     bfd_signed_vma *values;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  unsigned int i;
+  bfd_signed_vma val;
+
+  if (! push_type (info, "enum "))
+    return false;
+  if (tag != NULL)
+    {
+      if (! append_type (info, tag)
+         || ! append_type (info, " "))
+       return false;
+    }
+  if (! append_type (info, "{ "))
+    return false;
+
+  if (names == NULL)
+    {
+      if (! append_type (info, "/* undefined */"))
+       return false;
+    }
+  else
+    {
+      val = 0;
+      for (i = 0; names[i] != NULL; i++)
+       {
+         if (i > 0)
+           {
+             if (! append_type (info, ", "))
+               return false;
+           }
+
+         if (! append_type (info, names[i]))
+           return false;
+
+         if (values[i] != val)
+           {
+             char ab[20];
+
+             print_vma (values[i], ab, false, false);
+             if (! append_type (info, " = ")
+                 || ! append_type (info, ab))
+               return false;
+             val = values[i];
+           }
+
+         ++val;
+       }
+    }
+
+  return append_type (info, " }");
+}
+
+/* Turn the top type on the stack into a pointer.  */
+
+static boolean
+pr_pointer_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *s;
+
+  assert (info->stack != NULL);
+
+  s = strchr (info->stack->type, '|');
+  if (s != NULL && s[1] == '[')
+    return substitute_type (info, "(*|)");
+  return substitute_type (info, "*|");
+}
+
+/* Turn the top type on the stack into a function returning that type.  */
+
+static boolean
+pr_function_type (p, argcount, varargs)
+     PTR p;
+     int argcount;
+     boolean varargs;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char **arg_types;
+  unsigned int len;
+  char *s;
+
+  assert (info->stack != NULL);
+
+  len = 10;
+
+  if (argcount <= 0)
+    {
+      arg_types = NULL;
+      len += 15;
+    }
+  else
+    {
+      int i;
+
+      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
+      for (i = argcount - 1; i >= 0; i--)
+       {
+         if (! substitute_type (info, ""))
+           return false;
+         arg_types[i] = pop_type (info);
+         if (arg_types[i] == NULL)
+           return false;
+         len += strlen (arg_types[i]) + 2;
+       }
+      if (varargs)
+       len += 5;
+    }
+
+  /* Now the return type is on the top of the stack.  */
+
+  s = (char *) xmalloc (len);
+  strcpy (s, "(|) (");
+
+  if (argcount < 0)
+    strcat (s, "/* unknown */");
+  else
+    {
+      int i;
+
+      for (i = 0; i < argcount; i++)
+       {
+         if (i > 0)
+           strcat (s, ", ");
+         strcat (s, arg_types[i]);
+       }
+      if (varargs)
+       {
+         if (i > 0)
+           strcat (s, ", ");
+         strcat (s, "...");
+       }
+      if (argcount > 0)
+       free (arg_types);
+    }
+
+  strcat (s, ")");
+
+  if (! substitute_type (info, s))
+    return false;
+
+  free (s);
+
+  return true;
+}
+
+/* Turn the top type on the stack into a reference to that type.  */
+
+static boolean
+pr_reference_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  assert (info->stack != NULL);
+
+  return substitute_type (info, "&|");
+}
+
+/* Make a range type.  */
+
+static boolean
+pr_range_type (p, lower, upper)
+     PTR p;
+     bfd_signed_vma lower;
+     bfd_signed_vma upper;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char abl[20], abu[20];
+
+  assert (info->stack != NULL);
+
+  if (! substitute_type (info, ""))
+    return false;
+
+  print_vma (lower, abl, false, false);
+  print_vma (upper, abu, false, false);
+
+  return (prepend_type (info, "range (")
+         && append_type (info, "):")
+         && append_type (info, abl)
+         && append_type (info, ":")
+         && append_type (info, abu));
+}
+
+/* Make an array type.  */
+
+/*ARGSUSED*/
+static boolean
+pr_array_type (p, lower, upper, stringp)
+     PTR p;
+     bfd_signed_vma lower;
+     bfd_signed_vma upper;
+     boolean stringp;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *range_type;
+  char abl[20], abu[20], ab[50];
+
+  range_type = pop_type (info);
+  if (range_type == NULL)
+    return false;
+
+  if (lower == 0)
+    {
+      if (upper == -1)
+       sprintf (ab, "|[]");
+      else
+       {
+         print_vma (upper + 1, abu, false, false);
+         sprintf (ab, "|[%s]", abu);
+       }
+    }
+  else
+    {
+      print_vma (lower, abl, false, false);
+      print_vma (upper, abu, false, false);
+      sprintf (ab, "|[%s:%s]", abl, abu);
+    }
+
+  if (! substitute_type (info, ab))
+    return false;
+
+  if (strcmp (range_type, "int") != 0)
+    {
+      if (! append_type (info, ":")
+         || ! append_type (info, range_type))
+       return false;
+    }
+
+  if (stringp)
+    {
+      if (! append_type (info, " /* string */"))
+       return false;
+    }
+
+  return true;
+}
+
+/* Make a set type.  */
+
+/*ARGSUSED*/
+static boolean
+pr_set_type (p, bitstringp)
+     PTR p;
+     boolean bitstringp;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  if (! substitute_type (info, ""))
+    return false;
+
+  if (! prepend_type (info, "set { ")
+      || ! append_type (info, " }"))
+    return false;
+
+  if (bitstringp)
+    {
+      if (! append_type (info, "/* bitstring */"))
+       return false;
+    }
+
+  return true;
+}
+
+/* Make an offset type.  */
+
+static boolean
+pr_offset_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+
+  if (! substitute_type (info, ""))
+    return false;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  return (substitute_type (info, "")
+         && prepend_type (info, " ")
+         && prepend_type (info, t)
+         && append_type (info, "::|"));
+}
+
+/* Make a method type.  */
+
+static boolean
+pr_method_type (p, domain, argcount, varargs)
+     PTR p;
+     boolean domain;
+     int argcount;
+     boolean varargs;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  unsigned int len;
+  char *domain_type;
+  char **arg_types;
+  char *s;
+
+  len = 10;
+
+  if (! domain)
+    domain_type = NULL;
+  else
+    {
+      if (! substitute_type (info, ""))
+       return false;
+      domain_type = pop_type (info);
+      if (domain_type == NULL)
+       return false;
+      if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0
+         && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
+       domain_type += sizeof "class " - 1;
+      else if (strncmp (domain_type, "union class ",
+                       sizeof "union class ") == 0
+              && (strchr (domain_type + sizeof "union class " - 1, ' ')
+                  == NULL))
+       domain_type += sizeof "union class " - 1;
+      len += strlen (domain_type);
+    }
+
+  if (argcount <= 0)
+    {
+      arg_types = NULL;
+      len += 15;
+    }
+  else
+    {
+      int i;
+
+      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
+      for (i = argcount - 1; i >= 0; i--)
+       {
+         if (! substitute_type (info, ""))
+           return false;
+         arg_types[i] = pop_type (info);
+         if (arg_types[i] == NULL)
+           return false;
+         len += strlen (arg_types[i]) + 2;
+       }
+      if (varargs)
+       len += 5;
+    }
+
+  /* Now the return type is on the top of the stack.  */
+
+  s = (char *) xmalloc (len);
+  if (! domain)
+    *s = '\0';
+  else
+    strcpy (s, domain_type);
+  strcat (s, "::| (");
+
+  if (argcount < 0)
+    strcat (s, "/* unknown */");
+  else
+    {
+      int i;
+
+      for (i = 0; i < argcount; i++)
+       {
+         if (i > 0)
+           strcat (s, ", ");
+         strcat (s, arg_types[i]);
+       }
+      if (varargs)
+       {
+         if (i > 0)
+           strcat (s, ", ");
+         strcat (s, "...");
+       }
+      if (argcount > 0)
+       free (arg_types);
+    }
+
+  strcat (s, ")");
+
+  if (! substitute_type (info, s))
+    return false;
+
+  free (s);
+
+  return true;
+}
+
+/* Make a const qualified type.  */
+
+static boolean
+pr_const_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  return substitute_type (info, "const |");
+}
+
+/* Make a volatile qualified type.  */
+
+static boolean
+pr_volatile_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  return substitute_type (info, "volatile |");
+}
+
+/* Start accumulating a struct type.  */
+
+static boolean
+pr_start_struct_type (p, tag, id, structp, size)
+     PTR p;
+     const char *tag;
+     unsigned int id;
+     boolean structp;
+     unsigned int size;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  info->indent += 2;
+
+  if (! push_type (info, structp ? "struct " : "union "))
+    return false;
+  if (tag != NULL)
+    {
+      if (! append_type (info, tag))
+       return false;
+    }
+  else
+    {
+      char idbuf[20];
+
+      sprintf (idbuf, "%%anon%u", id);
+      if (! append_type (info, idbuf))
+       return false;
+    }
+
+  if (! append_type (info, " {"))
+    return false;
+  if (size != 0 || tag != NULL)
+    {
+      char ab[30];
+
+      if (! append_type (info, " /*"))
+       return false;
+
+      if (size != 0)
+       {
+         sprintf (ab, " size %u", size);
+         if (! append_type (info, ab))
+           return false;
+       }
+      if (tag != NULL)
+       {
+         sprintf (ab, " id %u", id);
+         if (! append_type (info, ab))
+           return false;
+       }
+      if (! append_type (info, " */"))
+       return false;
+    }
+  if (! append_type (info, "\n"))
+    return false;
+
+  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
+
+  return indent_type (info);
+}
+
+/* Output the visibility of a field in a struct.  */
+
+static boolean
+pr_fix_visibility (info, visibility)
+     struct pr_handle *info;
+     enum debug_visibility visibility;
+{
+  const char *s;
+  char *t;
+  unsigned int len;
+
+  assert (info->stack != NULL);
+
+  if (info->stack->visibility == visibility)
+    return true;
+
+  assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
+
+  switch (visibility)
+    {
+    case DEBUG_VISIBILITY_PUBLIC:
+      s = "public";
+      break;
+    case DEBUG_VISIBILITY_PRIVATE:
+      s = "private";
+      break;
+    case DEBUG_VISIBILITY_PROTECTED:
+      s = "protected";
+      break;
+    case DEBUG_VISIBILITY_IGNORE:
+      s = "/* ignore */";
+      break;
+    default:
+      abort ();
+      return false;
+    }
+
+  /* Trim off a trailing space in the struct string, to make the
+     output look a bit better, then stick on the visibility string.  */
+
+  t = info->stack->type;
+  len = strlen (t);
+  assert (t[len - 1] == ' ');
+  t[len - 1] = '\0';
+
+  if (! append_type (info, s)
+      || ! append_type (info, ":\n")
+      || ! indent_type (info))
+    return false;
+
+  info->stack->visibility = visibility;
+
+  return true;
+}
+
+/* Add a field to a struct type.  */
+
+static boolean
+pr_struct_field (p, name, bitpos, bitsize, visibility)
+     PTR p;
+     const char *name;
+     bfd_vma bitpos;
+     bfd_vma bitsize;
+     enum debug_visibility visibility;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[20];
+  char *t;
+
+  if (! substitute_type (info, name))
+    return false;
+
+  if (! append_type (info, "; /* "))
+    return false;
+
+  if (bitsize != 0)
+    {
+      print_vma (bitsize, ab, true, false);
+      if (! append_type (info, "bitsize ")
+         || ! append_type (info, ab)
+         || ! append_type (info, ", "))
+       return false;
+    }
+
+  print_vma (bitpos, ab, true, false);
+  if (! append_type (info, "bitpos ")
+      || ! append_type (info, ab)
+      || ! append_type (info, " */\n")
+      || ! indent_type (info))
+    return false;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  if (! pr_fix_visibility (info, visibility))
+    return false;
+
+  return append_type (info, t);
+}
+
+/* Finish a struct type.  */
+
+static boolean
+pr_end_struct_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *s;
+
+  assert (info->stack != NULL);
+  assert (info->indent >= 2);
+
+  info->indent -= 2;
+
+  /* Change the trailing indentation to have a close brace.  */
+  s = info->stack->type + strlen (info->stack->type) - 2;
+  assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0');
+
+  *s++ = '}';
+  *s = '\0';
+
+  return true;
+}
+
+/* Start a class type.  */
+
+static boolean
+pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+     PTR p;
+     const char *tag;
+     unsigned int id;
+     boolean structp;
+     unsigned int size;
+     boolean vptr;
+     boolean ownvptr;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *tv = NULL;
+
+  info->indent += 2;
+
+  if (vptr && ! ownvptr)
+    {
+      tv = pop_type (info);
+      if (tv == NULL)
+       return false;
+    }
+
+  if (! push_type (info, structp ? "class " : "union class "))
+    return false;
+  if (tag != NULL)
+    {
+      if (! append_type (info, tag))
+       return false;
+    }
+  else
+    {
+      char idbuf[20];
+
+      sprintf (idbuf, "%%anon%u", id);
+      if (! append_type (info, idbuf))
+       return false;
+    }
+
+  if (! append_type (info, " {"))
+    return false;
+  if (size != 0 || vptr || ownvptr || tag != NULL)
+    {
+      if (! append_type (info, " /*"))
+       return false;
+
+      if (size != 0)
+       {
+         char ab[20];
+
+         sprintf (ab, "%u", size);
+         if (! append_type (info, " size ")
+             || ! append_type (info, ab))
+           return false;
+       }
+
+      if (vptr)
+       {
+         if (! append_type (info, " vtable "))
+           return false;
+         if (ownvptr)
+           {
+             if (! append_type (info, "self "))
+               return false;
+           }
+         else
+           {
+             if (! append_type (info, tv)
+                 || ! append_type (info, " "))
+               return false;
+           }
+       }
+
+      if (tag != NULL)
+       {
+         char ab[30];
+
+         sprintf (ab, " id %u", id);
+         if (! append_type (info, ab))
+           return false;
+       }
+
+      if (! append_type (info, " */"))
+       return false;
+    }
+
+  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
+
+  return (append_type (info, "\n")
+         && indent_type (info));
+}
+
+/* Add a static member to a class.  */
+
+static boolean
+pr_class_static_member (p, name, physname, visibility)
+     PTR p;
+     const char *name;
+     const char *physname;
+     enum debug_visibility visibility;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+
+  if (! substitute_type (info, name))
+    return false;
+
+  if (! prepend_type (info, "static ")
+      || ! append_type (info, "; /* ")
+      || ! append_type (info, physname)
+      || ! append_type (info, " */\n")
+      || ! indent_type (info))
+    return false;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  if (! pr_fix_visibility (info, visibility))
+    return false;
+
+  return append_type (info, t);
+}
+
+/* Add a base class to a class.  */
+
+static boolean
+pr_class_baseclass (p, bitpos, virtual, visibility)
+     PTR p;
+     bfd_vma bitpos;
+     boolean virtual;
+     enum debug_visibility visibility;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+  const char *prefix;
+  char ab[20];
+  char *s, *l, *n;
+
+  assert (info->stack != NULL && info->stack->next != NULL);
+
+  if (! substitute_type (info, ""))
+    return false;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  if (strncmp (t, "class ", sizeof "class " - 1) == 0)
+    t += sizeof "class " - 1;
+
+  /* Push it back on to take advantage of the prepend_type and
+     append_type routines.  */
+  if (! push_type (info, t))
+    return false;
+
+  if (virtual)
+    {
+      if (! prepend_type (info, "virtual "))
+       return false;
+    }
+
+  switch (visibility)
+    {
+    case DEBUG_VISIBILITY_PUBLIC:
+      prefix = "public ";
+      break;
+    case DEBUG_VISIBILITY_PROTECTED:
+      prefix = "protected ";
+      break;
+    case DEBUG_VISIBILITY_PRIVATE:
+      prefix = "private ";
+      break;
+    default:
+      prefix = "/* unknown visibility */ ";
+      break;
+    }
+
+  if (! prepend_type (info, prefix))
+    return false;
+
+  if (bitpos != 0)
+    {
+      print_vma (bitpos, ab, true, false);
+      if (! append_type (info, " /* bitpos ")
+         || ! append_type (info, ab)
+         || ! append_type (info, " */"))
+       return false;
+    }
+
+  /* Now the top of the stack is something like "public A / * bitpos
+     10 * /".  The next element on the stack is something like "class
+     xx { / * size 8 * /\n...".  We want to substitute the top of the
+     stack in before the {.  */
+  s = strchr (info->stack->next->type, '{');
+  assert (s != NULL);
+  --s;
+
+  /* If there is already a ':', then we already have a baseclass, and
+     we must append this one after a comma.  */
+  for (l = info->stack->next->type; l != s; l++)
+    if (*l == ':')
+      break;
+  if (! prepend_type (info, l == s ? " : " : ", "))
+    return false;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
+  memcpy (n, info->stack->type, s - info->stack->type);
+  strcpy (n + (s - info->stack->type), t);
+  strcat (n, s);
+
+  free (info->stack->type);
+  info->stack->type = n;
+
+  free (t);
+
+  return true;
+}
+
+/* Start adding a method to a class.  */
+
+static boolean
+pr_class_start_method (p, name)
+     PTR p;
+     const char *name;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  assert (info->stack != NULL);
+  info->stack->method = name;
+  return true;
+}
+
+/* Add a variant to a method.  */
+
+static boolean
+pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset,
+                        context)
+     PTR p;
+     const char *physname;
+     enum debug_visibility visibility;
+     boolean constp;
+     boolean volatilep;
+     bfd_vma voffset;
+     boolean context;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *method_type;
+  char *context_type;
+
+  assert (info->stack != NULL);
+  assert (info->stack->next != NULL);
+
+  /* Put the const and volatile qualifiers on the type.  */
+  if (volatilep)
+    {
+      if (! append_type (info, " volatile"))
+       return false;
+    }
+  if (constp)
+    {
+      if (! append_type (info, " const"))
+       return false;
+    }
+
+  /* Stick the name of the method into its type.  */
+  if (! substitute_type (info,
+                        (context
+                         ? info->stack->next->next->method
+                         : info->stack->next->method)))
+    return false;
+
+  /* Get the type.  */
+  method_type = pop_type (info);
+  if (method_type == NULL)
+    return false;
+
+  /* Pull off the context type if there is one.  */
+  if (! context)
+    context_type = NULL;
+  else
+    {
+      context_type = pop_type (info);
+      if (context_type == NULL)
+       return false;
+    }
+
+  /* Now the top of the stack is the class.  */
+
+  if (! pr_fix_visibility (info, visibility))
+    return false;
+
+  if (! append_type (info, method_type)
+      || ! append_type (info, " /* ")
+      || ! append_type (info, physname)
+      || ! append_type (info, " "))
+    return false;
+  if (context || voffset != 0)
+    {
+      char ab[20];
+
+      if (context)
+       {
+         if (! append_type (info, "context ")
+             || ! append_type (info, context_type)
+             || ! append_type (info, " "))
+           return false;
+       }
+      print_vma (voffset, ab, true, false);
+      if (! append_type (info, "voffset ")
+         || ! append_type (info, ab))
+       return false;
+    }
+
+  return (append_type (info, " */;\n")
+         && indent_type (info));
+}
+
+/* Add a static variant to a method.  */
+
+static boolean
+pr_class_static_method_variant (p, physname, visibility, constp, volatilep)
+     PTR p;
+     const char *physname;
+     enum debug_visibility visibility;
+     boolean constp;
+     boolean volatilep;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *method_type;
+
+  assert (info->stack != NULL);
+  assert (info->stack->next != NULL);
+  assert (info->stack->next->method != NULL);
+
+  /* Put the const and volatile qualifiers on the type.  */
+  if (volatilep)
+    {
+      if (! append_type (info, " volatile"))
+       return false;
+    }
+  if (constp)
+    {
+      if (! append_type (info, " const"))
+       return false;
+    }
+
+  /* Mark it as static.  */
+  if (! prepend_type (info, "static "))
+    return false;
+
+  /* Stick the name of the method into its type.  */
+  if (! substitute_type (info, info->stack->next->method))
+    return false;
+
+  /* Get the type.  */
+  method_type = pop_type (info);
+  if (method_type == NULL)
+    return false;
+
+  /* Now the top of the stack is the class.  */
+
+  if (! pr_fix_visibility (info, visibility))
+    return false;
+
+  return (append_type (info, method_type)
+         && append_type (info, " /* ")
+         && append_type (info, physname)
+         && append_type (info, " */;\n")
+         && indent_type (info));
+}
+
+/* Finish up a method.  */
+
+static boolean
+pr_class_end_method (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  info->stack->method = NULL;
+  return true;
+}
+
+/* Finish up a class.  */
+
+static boolean
+pr_end_class_type (p)
+     PTR p;
+{
+  return pr_end_struct_type (p);
+}
+
+/* Push a type on the stack using a typedef name.  */
+
+static boolean
+pr_typedef_type (p, name)
+     PTR p;
+     const char *name;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  return push_type (info, name);
+}
+
+/* Push a type on the stack using a tag name.  */
+
+static boolean
+pr_tag_type (p, name, id, kind)
+     PTR p;
+     const char *name;
+     unsigned int id;
+     enum debug_type_kind kind;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  const char *t, *tag;
+  char idbuf[20];
+
+  switch (kind)
+    {
+    case DEBUG_KIND_STRUCT:
+      t = "struct ";
+      break;
+    case DEBUG_KIND_UNION:
+      t = "union ";
+      break;
+    case DEBUG_KIND_ENUM:
+      t = "enum ";
+      break;
+    case DEBUG_KIND_CLASS:
+      t = "class ";
+      break;
+    case DEBUG_KIND_UNION_CLASS:
+      t = "union class ";
+      break;
+    default:
+      abort ();
+      return false;
+    }
+
+  if (! push_type (info, t))
+    return false;
+  if (name != NULL)
+    tag = name;
+  else
+    {
+      sprintf (idbuf, "%%anon%u", id);
+      tag = idbuf;
+    }
+
+  if (! append_type (info, tag))
+    return false;
+  if (name != NULL && kind != DEBUG_KIND_ENUM)
+    {
+      sprintf (idbuf, " /* id %u */", id);
+      if (! append_type (info, idbuf))
+       return false;
+    }
+
+  return true;
+}
+
+/* Output a typedef.  */
+
+static boolean
+pr_typdef (p, name)
+     PTR p;
+     const char *name;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *s;
+
+  if (! substitute_type (info, name))
+    return false;
+
+  s = pop_type (info);
+  if (s == NULL)
+    return false;
+
+  indent (info);
+  fprintf (info->f, "typedef %s;\n", s);
+
+  free (s);
+
+  return true;
+}
+
+/* Output a tag.  The tag should already be in the string on the
+   stack, so all we have to do here is print it out.  */
+
+/*ARGSUSED*/
+static boolean
+pr_tag (p, name)
+     PTR p;
+     const char *name;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  indent (info);
+  fprintf (info->f, "%s;\n", t);
+
+  free (t);
+
+  return true;
+}
+
+/* Output an integer constant.  */
+
+static boolean
+pr_int_constant (p, name, val)
+     PTR p;
+     const char *name;
+     bfd_vma val;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[20];
+
+  indent (info);
+  print_vma (val, ab, false, false);
+  fprintf (info->f, "const int %s = %s;\n", name, ab);
+  return true;
+}
+
+/* Output a floating point constant.  */
+
+static boolean
+pr_float_constant (p, name, val)
+     PTR p;
+     const char *name;
+     double val;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  indent (info);
+  fprintf (info->f, "const double %s = %g;\n", name, val);
+  return true;
+}
+
+/* Output a typed constant.  */
+
+static boolean
+pr_typed_constant (p, name, val)
+     PTR p;
+     const char *name;
+     bfd_vma val;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+  char ab[20];
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  indent (info);
+  print_vma (val, ab, false, false);
+  fprintf (info->f, "const %s %s = %s;\n", t, name, ab);
+
+  free (t);
+
+  return true;
+}
+
+/* Output a variable.  */
+
+static boolean
+pr_variable (p, name, kind, val)
+     PTR p;
+     const char *name;
+     enum debug_var_kind kind;
+     bfd_vma val;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+  char ab[20];
+
+  if (! substitute_type (info, name))
+    return false;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  indent (info);
+  switch (kind)
+    {
+    case DEBUG_STATIC:
+    case DEBUG_LOCAL_STATIC:
+      fprintf (info->f, "static ");
+      break;
+    case DEBUG_REGISTER:
+      fprintf (info->f, "register ");
+      break;
+    default:
+      break;
+    }
+  print_vma (val, ab, true, true);
+  fprintf (info->f, "%s /* %s */;\n", t, ab);
+
+  free (t);
+
+  return true;
+}
+
+/* Start outputting a function.  */
+
+static boolean
+pr_start_function (p, name, global)
+     PTR p;
+     const char *name;
+     boolean global;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+
+  if (! substitute_type (info, name))
+    return false;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  indent (info);
+  if (! global)
+    fprintf (info->f, "static ");
+  fprintf (info->f, "%s (", t);
+
+  info->parameter = 1;
+
+  return true;
+}
+
+/* Output a function parameter.  */
+
+static boolean
+pr_function_parameter (p, name, kind, val)
+     PTR p;
+     const char *name;
+     enum debug_parm_kind kind;
+     bfd_vma val;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
+  char ab[20];
+
+  if (kind == DEBUG_PARM_REFERENCE
+      || kind == DEBUG_PARM_REF_REG)
+    {
+      if (! pr_reference_type (p))
+       return false;
+    }
+
+  if (! substitute_type (info, name))
+    return false;
+
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  if (info->parameter != 1)
+    fprintf (info->f, ", ");
+
+  if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
+    fprintf (info->f, "register ");
+
+  print_vma (val, ab, true, true);
+  fprintf (info->f, "%s /* %s */", t, ab);
+
+  free (t);
+
+  ++info->parameter;
+
+  return true;
+}
+
+/* Start writing out a block.  */
+
+static boolean
+pr_start_block (p, addr)
+     PTR p;
+     bfd_vma addr;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[20];
+
+  if (info->parameter > 0)
+    {
+      fprintf (info->f, ")\n");
+      info->parameter = 0;
+    }
+
+  indent (info);
+  print_vma (addr, ab, true, true);
+  fprintf (info->f, "{ /* %s */\n", ab);
+
+  info->indent += 2;
+
+  return true;
+}
+
+/* Write out line number information.  */
+
+static boolean
+pr_lineno (p, filename, lineno, addr)
+     PTR p;
+     const char *filename;
+     unsigned long lineno;
+     bfd_vma addr;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[20];
+
+  indent (info);
+  print_vma (addr, ab, true, true);
+  fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab);
+
+  return true;
+}
+
+/* Finish writing out a block.  */
+
+static boolean
+pr_end_block (p, addr)
+     PTR p;
+     bfd_vma addr;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+  char ab[20];
+
+  info->indent -= 2;
+
+  indent (info);
+  print_vma (addr, ab, true, true);
+  fprintf (info->f, "} /* %s */\n", ab);
+
+  return true;
+}
+
+/* Finish writing out a function.  */
+
+/*ARGSUSED*/
+static boolean
+pr_end_function (p)
+     PTR p;
+{
+  return true;
+}
diff --git a/binutils/ranlib.1 b/binutils/ranlib.1
new file mode 100644 (file)
index 0000000..7efb5c8
--- /dev/null
@@ -0,0 +1,83 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH ranlib 1 "5 November 1991" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+ranlib \- generate index to archive.
+
+.SH SYNOPSIS
+.hy 0
+.na
+.B ranlib \c
+.RB "[\|" \-v | \-V "\|]"
+.I archive\c
+\&
+.ad b
+.hy 1
+.SH DESCRIPTION
+.B ranlib
+generates an index to the contents of an archive, and
+stores it in the archive.  The index lists each symbol defined by a
+member of an archive that is a relocatable object file.  
+.PP
+You may use
+.RB ` "nm \-s" '
+or
+.RB ` "nm \-\-print-armap" '
+to list this index.
+.PP
+An archive with such an index speeds up linking to the library, and
+allows routines in the library to call each other without regard to
+their placement in the archive.
+.PP
+The GNU
+.B ranlib
+program is another form of GNU
+.BR ar ;
+running
+.B ranlib
+is completely equivalent to executing
+.RB ` "ar \-s" '.
+
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number of
+.B ranlib
+and exit.
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'"
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (October 1991); 
+.BR ar "(" 1 "),"
+.BR nm "(" 1 ")."
+
+
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/ranlib.sh b/binutils/ranlib.sh
new file mode 100755 (executable)
index 0000000..2b6fbc4
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+# A simple ranlib script, to use less disk space than a ranlib program.
+ar s $1
diff --git a/binutils/rclex.l b/binutils/rclex.l
new file mode 100644 (file)
index 0000000..06a6607
--- /dev/null
@@ -0,0 +1,465 @@
+%{ /* rclex.l -- lexer for Windows rc files parser  */
+/* Copyright 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This is a lex input file which generates a lexer used by the
+   Windows rc file parser.  It basically just recognized a bunch of
+   keywords.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "windres.h"
+#include "rcparse.h"
+
+#include <ctype.h>
+#include <assert.h>
+
+/* Whether we are in rcdata mode, in which we returns the lengths of
+   strings.  */
+
+static int rcdata_mode;
+
+/* List of allocated strings.  */
+
+struct alloc_string
+{
+  struct alloc_string *next;
+  char *s;
+};
+
+static struct alloc_string *strings;
+
+/* Local functions.  */
+
+static void cpp_line PARAMS ((const char *));
+static char *handle_quotes PARAMS ((const char *, unsigned long *));
+static char *get_string PARAMS ((int));
+
+%}
+
+%%
+
+"BEGIN"                        { return BEG; }
+"{"                    { return BEG; }
+"END"                  { return END; }
+"}"                    { return END; }
+"ACCELERATORS"         { return ACCELERATORS; }
+"VIRTKEY"              { return VIRTKEY; }
+"ASCII"                        { return ASCII; }
+"NOINVERT"             { return NOINVERT; }
+"SHIFT"                        { return SHIFT; }
+"CONTROL"              { return CONTROL; }
+"ALT"                  { return ALT; }
+"BITMAP"               { return BITMAP; }
+"CURSOR"               { return CURSOR; }
+"DIALOG"               { return DIALOG; }
+"DIALOGEX"             { return DIALOGEX; }
+"EXSTYLE"              { return EXSTYLE; }
+"CAPTION"              { return CAPTION; }
+"CLASS"                        { return CLASS; }
+"STYLE"                        { return STYLE; }
+"AUTO3STATE"           { return AUTO3STATE; }
+"AUTOCHECKBOX"         { return AUTOCHECKBOX; }
+"AUTORADIOBUTTON"      { return AUTORADIOBUTTON; }
+"CHECKBOX"             { return CHECKBOX; }
+"COMBOBOX"             { return COMBOBOX; }
+"CTEXT"                        { return CTEXT; }
+"DEFPUSHBUTTON"                { return DEFPUSHBUTTON; }
+"EDITTEXT"             { return EDITTEXT; }
+"GROUPBOX"             { return GROUPBOX; }
+"LISTBOX"              { return LISTBOX; }
+"LTEXT"                        { return LTEXT; }
+"PUSHBOX"              { return PUSHBOX; }
+"PUSHBUTTON"           { return PUSHBUTTON; }
+"RADIOBUTTON"          { return RADIOBUTTON; }
+"RTEXT"                        { return RTEXT; }
+"SCROLLBAR"            { return SCROLLBAR; }
+"STATE3"               { return STATE3; }
+"USERBUTTON"           { return USERBUTTON; }
+"BEDIT"                        { return BEDIT; }
+"HEDIT"                        { return HEDIT; }
+"IEDIT"                        { return IEDIT; }
+"FONT"                 { return FONT; }
+"ICON"                 { return ICON; }
+"LANGUAGE"             { return LANGUAGE; }
+"CHARACTERISTICS"      { return CHARACTERISTICS; }
+"VERSION"              { return VERSIONK; }
+"MENU"                 { return MENU; }
+"MENUEX"               { return MENUEX; }
+"MENUITEM"             { return MENUITEM; }
+"SEPARATOR"            { return SEPARATOR; }
+"POPUP"                        { return POPUP; }
+"CHECKED"              { return CHECKED; }
+"GRAYED"               { return GRAYED; }
+"HELP"                 { return HELP; }
+"INACTIVE"             { return INACTIVE; }
+"MENUBARBREAK"         { return MENUBARBREAK; }
+"MENUBREAK"            { return MENUBREAK; }
+"MESSAGETABLE"         { return MESSAGETABLE; }
+"RCDATA"               { return RCDATA; }
+"STRINGTABLE"          { return STRINGTABLE; }
+"VERSIONINFO"          { return VERSIONINFO; }
+"FILEVERSION"          { return FILEVERSION; }
+"PRODUCTVERSION"       { return PRODUCTVERSION; }
+"FILEFLAGSMASK"                { return FILEFLAGSMASK; }
+"FILEFLAGS"            { return FILEFLAGS; }
+"FILEOS"               { return FILEOS; }
+"FILETYPE"             { return FILETYPE; }
+"FILESUBTYPE"          { return FILESUBTYPE; }
+"VALUE"                        { return VALUE; }
+"MOVEABLE"             { return MOVEABLE; }
+"FIXED"                        { return FIXED; }
+"PURE"                 { return PURE; }
+"IMPURE"               { return IMPURE; }
+"PRELOAD"              { return PRELOAD; }
+"LOADONCALL"           { return LOADONCALL; }
+"DISCARDABLE"          { return DISCARDABLE; }
+"NOT"                  { return NOT; }
+
+"BLOCK"[ \t\n]*"\""[^\#\n]*"\"" {
+                         char *s, *send;
+
+                         /* This is a hack to let us parse version
+                             information easily.  */
+
+                         s = strchr (yytext, '"');
+                         ++s;
+                         send = strchr (s, '"');
+                         if (strncmp (s, "StringFileInfo",
+                                      sizeof "StringFileInfo" - 1) == 0
+                             && s + sizeof "StringFileInfo" - 1 == send)
+                           return BLOCKSTRINGFILEINFO;
+                         else if (strncmp (s, "VarFileInfo",
+                                           sizeof "VarFileInfo" - 1) == 0
+                                  && s + sizeof "VarFileInfo" - 1 == send)
+                           return BLOCKVARFILEINFO;
+                         else
+                           {
+                             char *r;
+
+                             r = get_string (send - s + 1);
+                             strncpy (r, s, send - s);
+                             r[send - s] = '\0';
+                             yylval.s = r;
+                             return BLOCK;
+                           }
+                       }
+
+"#"[^\n]*              {
+                         cpp_line (yytext);
+                       }
+
+[0-9][x0-9A-Fa-f]*L    {
+                         yylval.i.val = strtoul (yytext, 0, 0);
+                         yylval.i.dword = 1;
+                         return NUMBER;
+                       }
+
+[0-9][x0-9A-Fa-f]*     {
+                         yylval.i.val = strtoul (yytext, 0, 0);
+                         yylval.i.dword = 0;
+                         return NUMBER;
+                       }
+
+("\""[^\"\n]*"\""[ \t]*)+ {
+                         char *s;
+                         unsigned long length;
+
+                         s = handle_quotes (yytext, &length);
+                         if (! rcdata_mode)
+                           {
+                             yylval.s = s;
+                             return QUOTEDSTRING;
+                           }
+                         else
+                           {
+                             yylval.ss.length = length;
+                             yylval.ss.s = s;
+                             return SIZEDSTRING;
+                           }
+                       }
+
+[A-Za-z][^ ,\t\r\n]*   {
+                         char *s;
+
+                         /* I rejected comma in a string in order to
+                            handle VIRTKEY, CONTROL in an accelerator
+                            resource.  This means that an unquoted
+                            file name can not contain a comma.  I
+                            don't know what rc permits.  */
+
+                         s = get_string (strlen (yytext) + 1);
+                         strcpy (s, yytext);
+                         yylval.s = s;
+                         return STRING;
+                       }
+
+[\n]                   { ++rc_lineno; }
+[ \t\r]+               { /* ignore whitespace */ }
+.                      { return *yytext; }
+
+%%
+#ifndef yywrap
+/* This is needed for some versions of lex.  */
+int yywrap ()
+{
+  return 1;
+}
+#endif
+
+/* Handle a C preprocessor line.  */
+
+static void
+cpp_line (s)
+     const char *s;
+{
+  int line;
+  char *send, *fn;
+
+  ++s;
+  while (isspace ((unsigned char) *s))
+    ++s;
+  
+  line = strtol (s, &send, 0);
+  if (*send != '\0' && ! isspace ((unsigned char) *send))
+    return;
+
+  /* Subtract 1 because we are about to count the newline.  */
+  rc_lineno = line - 1;
+
+  s = send;
+  while (isspace ((unsigned char) *s))
+    ++s;
+
+  if (*s != '"')
+    return;
+
+  ++s;
+  send = strchr (s, '"');
+  if (send == NULL)
+    return;
+
+  fn = (char *) xmalloc (send - s + 1);
+  strncpy (fn, s, send - s);
+  fn[send - s] = '\0';
+
+  free (rc_filename);
+  rc_filename = fn;
+}
+
+/* Handle a quoted string.  The quotes are stripped.  A pair of quotes
+   in a string are turned into a single quote.  Adjacent strings are
+   merged separated by whitespace are merged, as in C.  */
+
+static char *
+handle_quotes (input, len)
+     const char *input;
+     unsigned long *len;
+{
+  char *ret, *s;
+  const char *t;
+  int ch;
+
+  ret = get_string (strlen (input) + 1);
+
+  s = ret;
+  t = input;
+  if (*t == '"')
+    ++t;
+  while (*t != '\0')
+    {
+      if (*t == '\\')
+       {
+         ++t;
+         switch (*t)
+           {
+           case '\0':
+             rcparse_warning ("backslash at end of string");
+             break;
+
+           case '\"':
+             rcparse_warning ("use \"\" to put \" in a string");
+             break;
+
+           case 'a':
+             *s++ = ESCAPE_A;
+             ++t;
+             break;
+
+           case 'b':
+             *s++ = ESCAPE_B;
+             ++t;
+             break;
+
+           case 'f':
+             *s++ = ESCAPE_F;
+             ++t;
+             break;
+
+           case 'n':
+             *s++ = ESCAPE_N;
+             ++t;
+             break;
+
+           case 'r':
+             *s++ = ESCAPE_R;
+             ++t;
+             break;
+
+           case 't':
+             *s++ = ESCAPE_T;
+             ++t;
+             break;
+
+           case 'v':
+             *s++ = ESCAPE_V;
+             ++t;
+             break;
+
+           case '\\':
+             *s++ = *t++;
+             break;
+
+           case '0': case '1': case '2': case '3':
+           case '4': case '5': case '6': case '7':
+             ch = *t - '0';
+             ++t;
+             if (*t >= '0' && *t <= '7')
+               {
+                 ch = (ch << 3) | (*t - '0');
+                 ++t;
+                 if (*t >= '0' && *t <= '7')
+                   {
+                     ch = (ch << 3) | (*t - '0');
+                     ++t;
+                   }
+               }
+             *s++ = ch;
+             break;
+
+           case 'x':
+             ++t;
+             ch = 0;
+             while (1)
+               {
+                 if (*t >= '0' && *t <= '9')
+                   ch = (ch << 4) | (*t - '0');
+                 else if (*t >= 'a' && *t <= 'f')
+                   ch = (ch << 4) | (*t - 'a');
+                 else if (*t >= 'A' && *t <= 'F')
+                   ch = (ch << 4) | (*t - 'A');
+                 else
+                   break;
+                 ++t;
+               }
+             *s++ = ch;
+             break;
+
+           default:
+             rcparse_warning ("unrecognized escape sequence");
+             *s++ = '\\';
+             *s++ = *t++;
+             break;
+           }
+       }
+      else if (*t != '"')
+       *s++ = *t++;
+      else if (t[1] == '\0')
+       break;
+      else if (t[1] == '"')
+       {
+         *s++ = '"';
+         t += 2;
+       }
+      else
+       {
+         ++t;
+         assert (isspace ((unsigned char) *t));
+         while (isspace ((unsigned char) *t))
+           ++t;
+         if (*t == '\0')
+           break;
+         assert (*t == '"');
+         ++t;
+       }
+    }
+
+  *s = '\0';
+
+  *len = s - ret;
+
+  return ret;
+}
+
+/* Allocate a string of a given length.  */
+
+static char *
+get_string (len)
+     int len;
+{
+  struct alloc_string *as;
+
+  as = (struct alloc_string *) xmalloc (sizeof *as);
+  as->s = xmalloc (len);
+
+  as->next = strings;
+  strings = as->next;
+
+  return as->s;
+}
+
+/* Discard all the strings we have allocated.  The parser calls this
+   when it no longer needs them.  */
+
+void
+rcparse_discard_strings ()
+{
+  struct alloc_string *as;
+
+  as = strings;
+  while (as != NULL)
+    {
+      struct alloc_string *n;
+
+      free (as->s);
+      n = as->next;
+      free (as);
+      as = n;
+    }
+
+  strings = NULL;
+}
+
+/* Enter rcdata mode.  */
+
+void
+rcparse_rcdata ()
+{
+  rcdata_mode = 1;
+}
+
+/* Go back to normal mode from rcdata mode.  */
+
+void
+rcparse_normal ()
+{
+  rcdata_mode = 0;
+}
diff --git a/binutils/rcparse.y b/binutils/rcparse.y
new file mode 100644 (file)
index 0000000..67079a5
--- /dev/null
@@ -0,0 +1,1617 @@
+%{ /* rcparse.y -- parser for Windows rc files
+   Copyright 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This is a parser for Windows rc files.  It is based on the parser
+   by Gunther Ebert <gunther.ebert@ixos-leipzig.de>.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "windres.h"
+
+#include <ctype.h>
+
+/* The current language.  */
+
+static unsigned short language;
+
+/* The resource information during a sub statement.  */
+
+static struct res_res_info sub_res_info;
+
+/* Dialog information.  This is built by the nonterminals styles and
+   controls.  */
+
+static struct dialog dialog;
+
+/* This is used when building a style.  It is modified by the
+   nonterminal styleexpr.  */
+
+static unsigned long style;
+
+/* These are used when building a control.  They are set before using
+   control_params.  */
+
+static unsigned long base_style;
+static unsigned long default_style;
+static unsigned long class;
+
+%}
+
+%union
+{
+  struct accelerator acc;
+  struct accelerator *pacc;
+  struct dialog_control *dialog_control;
+  struct menuitem *menuitem;
+  struct
+  {
+    struct rcdata_item *first;
+    struct rcdata_item *last;
+  } rcdata;
+  struct rcdata_item *rcdata_item;
+  struct stringtable_data *stringtable;
+  struct fixed_versioninfo *fixver;
+  struct ver_info *verinfo;
+  struct ver_stringinfo *verstring;
+  struct ver_varinfo *vervar;
+  struct res_id id;
+  struct res_res_info res_info;
+  struct
+  {
+    unsigned short on;
+    unsigned short off;
+  } memflags;
+  struct
+  {
+    unsigned long val;
+    /* Nonzero if this number was explicitly specified as long.  */
+    int dword;
+  } i;
+  unsigned long il;
+  unsigned short is;
+  const char *s;
+  struct
+  {
+    unsigned long length;
+    const char *s;
+  } ss;
+};
+
+%token BEG END
+%token ACCELERATORS VIRTKEY ASCII NOINVERT SHIFT CONTROL ALT
+%token BITMAP
+%token CURSOR
+%token DIALOG DIALOGEX EXSTYLE CAPTION CLASS STYLE
+%token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX COMBOBOX CTEXT
+%token DEFPUSHBUTTON EDITTEXT GROUPBOX LISTBOX LTEXT PUSHBOX PUSHBUTTON
+%token RADIOBUTTON RTEXT SCROLLBAR STATE3 USERBUTTON
+%token BEDIT HEDIT IEDIT
+%token FONT
+%token ICON
+%token LANGUAGE CHARACTERISTICS VERSIONK
+%token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE
+%token MENUBARBREAK MENUBREAK
+%token MESSAGETABLE
+%token RCDATA
+%token STRINGTABLE
+%token VERSIONINFO FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS
+%token FILEOS FILETYPE FILESUBTYPE BLOCKSTRINGFILEINFO BLOCKVARFILEINFO
+%token VALUE
+%token <s> BLOCK
+%token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE
+%token NOT
+%token <s> QUOTEDSTRING STRING
+%token <i> NUMBER
+%token <ss> SIZEDSTRING
+
+%type <pacc> acc_entries
+%type <acc> acc_entry acc_event
+%type <dialog_control> control control_params
+%type <menuitem> menuitems menuitem menuexitems menuexitem
+%type <rcdata> optrcdata_data optrcdata_data_int rcdata_data
+%type <rcdata_item> opt_control_data
+%type <fixver> fixedverinfo
+%type <verinfo> verblocks
+%type <verstring> vervals
+%type <vervar> vertrans
+%type <res_info> suboptions memflags_move_discard memflags_move
+%type <memflags> memflag
+%type <id> id
+%type <il> exstyle parennumber
+%type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr
+%type <is> acc_options acc_option menuitem_flags menuitem_flag
+%type <s> optstringc file_name
+%type <i> sizednumexpr sizedposnumexpr
+
+%left '|'
+%left '^'
+%left '&'
+%left '+' '-'
+%left '*' '/' '%'
+%right '~' NEG
+
+%%
+
+input:
+         /* empty */
+       | input newcmd accelerator
+       | input newcmd bitmap
+       | input newcmd cursor
+       | input newcmd dialog
+       | input newcmd font
+       | input newcmd icon
+       | input newcmd language
+       | input newcmd menu
+       | input newcmd menuex
+       | input newcmd messagetable
+       | input newcmd rcdata
+       | input newcmd stringtable
+       | input newcmd user
+       | input newcmd versioninfo
+       ;
+
+newcmd:
+         /* empty */
+         {
+           rcparse_discard_strings ();
+         }
+       ;
+
+/* Accelerator resources.  */
+
+accelerator:
+         id ACCELERATORS suboptions BEG acc_entries END
+         {
+           define_accelerator ($1, &$3, $5);
+         }
+       ;
+
+acc_entries:
+         /* empty */
+         {
+           $$ = NULL;
+         }
+       | acc_entries acc_entry
+         {
+           struct accelerator *a;
+
+           a = (struct accelerator *) res_alloc (sizeof *a);
+           *a = $2;
+           if ($1 == NULL)
+             $$ = a;
+           else
+             {
+               struct accelerator **pp;
+
+               for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
+                 ;
+               *pp = a;
+               $$ = $1;
+             }
+         }
+       ;
+
+acc_entry:
+         acc_event cposnumexpr
+         {
+           $$ = $1;
+           $$.id = $2;
+         }
+       | acc_event cposnumexpr ',' acc_options
+         {
+           $$ = $1;
+           $$.id = $2;
+           $$.flags |= $4;
+           if (($$.flags & ACC_VIRTKEY) == 0
+               && ($$.flags & (ACC_SHIFT | ACC_CONTROL | ACC_ALT)) != 0)
+             rcparse_warning (_("inappropriate modifiers for non-VIRTKEY"));
+         }
+       ;
+
+acc_event:
+         QUOTEDSTRING
+         {
+           const char *s = $1;
+           char ch;
+
+           $$.next = NULL;
+           $$.id = 0;
+           ch = *s;
+           if (ch != '^')
+             $$.flags = 0;
+           else
+             {
+               $$.flags = ACC_CONTROL | ACC_VIRTKEY;
+               ++s;
+               ch = *s;
+               ch = toupper ((unsigned char) ch);
+             }
+           $$.key = ch;
+           if (s[1] != '\0')
+             rcparse_warning (_("accelerator should only be one character"));
+         }
+       | posnumexpr
+         {
+           $$.next = NULL;
+           $$.flags = 0;
+           $$.id = 0;
+           $$.key = $1;
+         }
+       ;
+
+acc_options:
+         acc_option
+         {
+           $$ = $1;
+         }
+       | acc_options ',' acc_option
+         {
+           $$ = $1 | $3;
+         }
+       /* I've had one report that the comma is optional.  */
+       | acc_options acc_option
+         {
+           $$ = $1 | $2;
+         }
+       ;
+
+acc_option:
+         VIRTKEY
+         {
+           $$ = ACC_VIRTKEY;
+         }
+       | ASCII
+         {
+           /* This is just the absence of VIRTKEY.  */
+           $$ = 0;
+         }
+       | NOINVERT
+         {
+           $$ = ACC_NOINVERT;
+         }
+       | SHIFT
+         {
+           $$ = ACC_SHIFT;
+         }
+       | CONTROL
+         {
+           $$ = ACC_CONTROL;
+         }
+       | ALT
+         {
+           $$ = ACC_ALT;
+         }
+       ;
+
+/* Bitmap resources.  */
+
+bitmap:
+         id BITMAP memflags_move file_name
+         {
+           define_bitmap ($1, &$3, $4);
+         }
+       ;
+
+/* Cursor resources.  */
+
+cursor:
+         id CURSOR memflags_move_discard file_name
+         {
+           define_cursor ($1, &$3, $4);
+         }
+       ;
+
+/* Dialog resources.  */
+
+dialog:
+         id DIALOG memflags_move exstyle posnumexpr cnumexpr cnumexpr
+           cnumexpr
+           {
+             memset (&dialog, 0, sizeof dialog);
+             dialog.x = $5;
+             dialog.y = $6;
+             dialog.width = $7;
+             dialog.height = $8;
+             dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
+             dialog.exstyle = $4;
+             dialog.menu.named = 1;
+             dialog.class.named = 1;
+             dialog.font = NULL;
+             dialog.ex = NULL;
+             dialog.controls = NULL;
+             sub_res_info = $3;
+           }
+           styles BEG controls END
+         {
+           define_dialog ($1, &sub_res_info, &dialog);
+         }
+       | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
+           cnumexpr
+           {
+             memset (&dialog, 0, sizeof dialog);
+             dialog.x = $5;
+             dialog.y = $6;
+             dialog.width = $7;
+             dialog.height = $8;
+             dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
+             dialog.exstyle = $4;
+             dialog.menu.named = 1;
+             dialog.class.named = 1;
+             dialog.font = NULL;
+             dialog.ex = ((struct dialog_ex *)
+                          res_alloc (sizeof (struct dialog_ex)));
+             memset (dialog.ex, 0, sizeof (struct dialog_ex));
+             dialog.controls = NULL;
+             sub_res_info = $3;
+           }
+           styles BEG controls END
+         {
+           define_dialog ($1, &sub_res_info, &dialog);
+         }
+       | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
+           cnumexpr cnumexpr
+           {
+             memset (&dialog, 0, sizeof dialog);
+             dialog.x = $5;
+             dialog.y = $6;
+             dialog.width = $7;
+             dialog.height = $8;
+             dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
+             dialog.exstyle = $4;
+             dialog.menu.named = 1;
+             dialog.class.named = 1;
+             dialog.font = NULL;
+             dialog.ex = ((struct dialog_ex *)
+                          res_alloc (sizeof (struct dialog_ex)));
+             memset (dialog.ex, 0, sizeof (struct dialog_ex));
+             dialog.ex->help = $9;
+             dialog.controls = NULL;
+             sub_res_info = $3;
+           }
+           styles BEG controls END
+         {
+           define_dialog ($1, &sub_res_info, &dialog);
+         }
+       ;
+
+exstyle:
+         /* empty */
+         {
+           $$ = 0;
+         }
+       | EXSTYLE '=' numexpr
+         {
+           $$ = $3;
+         }
+       ;
+
+styles:
+         /* empty */
+       | styles CAPTION QUOTEDSTRING
+         {
+           unicode_from_ascii ((int *) NULL, &dialog.caption, $3);
+         }
+       | styles CLASS id
+         {
+           dialog.class = $3;
+         }
+       | styles STYLE
+           { style = dialog.style; }
+           styleexpr
+         {
+           dialog.style = style;
+         }
+       | styles EXSTYLE numexpr
+         {
+           dialog.exstyle = $3;
+         }
+       | styles FONT numexpr ',' QUOTEDSTRING
+         {
+           dialog.style |= DS_SETFONT;
+           dialog.pointsize = $3;
+           unicode_from_ascii ((int *) NULL, &dialog.font, $5);
+         }
+       | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr
+         {
+           dialog.style |= DS_SETFONT;
+           dialog.pointsize = $3;
+           unicode_from_ascii ((int *) NULL, &dialog.font, $5);
+           if (dialog.ex == NULL)
+             rcparse_warning (_("extended FONT requires DIALOGEX"));
+           else
+             {
+               dialog.ex->weight = $6;
+               dialog.ex->italic = $7;
+             }
+         }
+       | styles MENU id
+         {
+           dialog.menu = $3;
+         }
+       | styles CHARACTERISTICS numexpr
+         {
+           sub_res_info.characteristics = $3;
+         }
+       | styles LANGUAGE numexpr cnumexpr
+         {
+           sub_res_info.language = $3 | ($4 << 8);
+         }
+       | styles VERSIONK numexpr
+         {
+           sub_res_info.version = $3;
+         }
+       ;
+
+controls:
+         /* empty */
+       | controls control
+         {
+           struct dialog_control **pp;
+
+           for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next)
+             ;
+           *pp = $2;
+         }
+       ;
+
+control:
+         AUTO3STATE
+           {
+             default_style = BS_AUTO3STATE | WS_TABSTOP;
+             base_style = BS_AUTO3STATE;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | AUTOCHECKBOX
+           {
+             default_style = BS_AUTOCHECKBOX | WS_TABSTOP;
+             base_style = BS_AUTOCHECKBOX;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | AUTORADIOBUTTON
+           {
+             default_style = BS_AUTORADIOBUTTON | WS_TABSTOP;
+             base_style = BS_AUTORADIOBUTTON;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | BEDIT
+           {
+             default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
+             base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
+             class = CTL_EDIT;
+           }
+           control_params
+         {
+           $$ = $3;
+           if (dialog.ex == NULL)
+             rcparse_warning (_("IEDIT requires DIALOGEX"));
+           res_string_to_id (&$$->class, "BEDIT");
+         }
+       | CHECKBOX
+           {
+             default_style = BS_CHECKBOX | WS_TABSTOP;
+             base_style = BS_CHECKBOX | WS_TABSTOP;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | COMBOBOX
+           {
+             default_style = CBS_SIMPLE | WS_TABSTOP;
+             base_style = 0;
+             class = CTL_COMBOBOX;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | CONTROL optstringc numexpr cnumexpr control_styleexpr cnumexpr
+           cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
+         {
+           $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
+           if ($11 != NULL)
+             {
+               if (dialog.ex == NULL)
+                 rcparse_warning (_("control data requires DIALOGEX"));
+               $$->data = $11;
+             }
+         }
+       | CONTROL optstringc numexpr cnumexpr control_styleexpr cnumexpr
+           cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
+         {
+           $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
+           if (dialog.ex == NULL)
+             rcparse_warning (_("help ID requires DIALOGEX"));
+           $$->help = $11;
+           $$->data = $12;
+         }
+       | CONTROL optstringc numexpr ',' QUOTEDSTRING control_styleexpr
+           cnumexpr cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
+         {
+           $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11);
+           if ($12 != NULL)
+             {
+               if (dialog.ex == NULL)
+                 rcparse_warning ("control data requires DIALOGEX");
+               $$->data = $12;
+             }
+           $$->class.named = 1;
+           unicode_from_ascii(&$$->class.u.n.length, &$$->class.u.n.name, $5);
+         }
+       | CONTROL optstringc numexpr ',' QUOTEDSTRING control_styleexpr
+           cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
+         {
+           $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11);
+           if (dialog.ex == NULL)
+             rcparse_warning ("help ID requires DIALOGEX");
+           $$->help = $12;
+           $$->data = $13;
+           $$->class.named = 1;
+           unicode_from_ascii(&$$->class.u.n.length, &$$->class.u.n.name, $5);
+         }
+       | CTEXT
+           {
+             default_style = SS_CENTER | WS_GROUP;
+             base_style = SS_CENTER;
+             class = CTL_STATIC;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | DEFPUSHBUTTON
+           {
+             default_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
+             base_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | EDITTEXT
+           {
+             default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
+             base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
+             class = CTL_EDIT;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | GROUPBOX
+           {
+             default_style = BS_GROUPBOX;
+             base_style = BS_GROUPBOX;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | HEDIT
+           {
+             default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
+             base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
+             class = CTL_EDIT;
+           }
+           control_params
+         {
+           $$ = $3;
+           if (dialog.ex == NULL)
+             rcparse_warning (_("IEDIT requires DIALOGEX"));
+           res_string_to_id (&$$->class, "HEDIT");
+         }
+       | ICON optstringc numexpr cnumexpr cnumexpr opt_control_data
+         {
+           $$ = define_control ($2, $3, $4, $5, 0, 0, CTL_STATIC,
+                                SS_ICON | WS_CHILD | WS_VISIBLE, 0);
+           if ($6 != NULL)
+             {
+               if (dialog.ex == NULL)
+                 rcparse_warning (_("control data requires DIALOGEX"));
+               $$->data = $6;
+             }
+         }
+       | ICON optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
+           icon_styleexpr optcnumexpr opt_control_data
+         {
+           $$ = define_control ($2, $3, $4, $5, $6, $7, CTL_STATIC,
+                                style, $9);
+           if ($10 != NULL)
+             {
+               if (dialog.ex == NULL)
+                 rcparse_warning (_("control data requires DIALOGEX"));
+               $$->data = $10;
+             }
+         }
+       | ICON optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
+           icon_styleexpr cnumexpr cnumexpr opt_control_data
+         {
+           $$ = define_control ($2, $3, $4, $5, $6, $7, CTL_STATIC,
+                                style, $9);
+           if (dialog.ex == NULL)
+             rcparse_warning (_("help ID requires DIALOGEX"));
+           $$->help = $10;
+           $$->data = $11;
+         }
+       | IEDIT
+           {
+             default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
+             base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
+             class = CTL_EDIT;
+           }
+           control_params
+         {
+           $$ = $3;
+           if (dialog.ex == NULL)
+             rcparse_warning (_("IEDIT requires DIALOGEX"));
+           res_string_to_id (&$$->class, "IEDIT");
+         }
+       | LISTBOX
+           {
+             default_style = LBS_NOTIFY | WS_BORDER;
+             base_style = LBS_NOTIFY | WS_BORDER;
+             class = CTL_LISTBOX;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | LTEXT
+           {
+             default_style = SS_LEFT | WS_GROUP;
+             base_style = SS_LEFT;
+             class = CTL_STATIC;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | PUSHBOX
+           {
+             default_style = BS_PUSHBOX | WS_TABSTOP;
+             base_style = BS_PUSHBOX;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | PUSHBUTTON
+           {
+             default_style = BS_PUSHBUTTON | WS_TABSTOP;
+             base_style = BS_PUSHBUTTON | WS_TABSTOP;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | RADIOBUTTON
+           {
+             default_style = BS_RADIOBUTTON | WS_TABSTOP;
+             base_style = BS_RADIOBUTTON;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | RTEXT
+           {
+             default_style = SS_RIGHT | WS_GROUP;
+             base_style = SS_RIGHT;
+             class = CTL_STATIC;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | SCROLLBAR
+           {
+             default_style = SBS_HORZ;
+             base_style = 0;
+             class = CTL_SCROLLBAR;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | STATE3
+           {
+             default_style = BS_3STATE | WS_TABSTOP;
+             base_style = BS_3STATE;
+             class = CTL_BUTTON;
+           }
+           control_params
+         {
+           $$ = $3;
+         }
+       | USERBUTTON QUOTEDSTRING ',' numexpr ',' numexpr ',' numexpr ','
+           numexpr ',' numexpr ',' 
+           { style = WS_CHILD | WS_VISIBLE; }
+           styleexpr optcnumexpr
+         {
+           $$ = define_control ($2, $4, $6, $8, $10, $12, CTL_BUTTON,
+                                style, $16);
+         }
+       ;
+
+/* Parameters for a control.  The static variables DEFAULT_STYLE,
+   BASE_STYLE, and CLASS must be initialized before this nonterminal
+   is used.  DEFAULT_STYLE is the style to use if no style expression
+   is specified.  BASE_STYLE is the base style to use if a style
+   expression is specified; the style expression modifies the base
+   style.  CLASS is the class of the control.  */
+
+control_params:
+         optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
+           opt_control_data
+         {
+           $$ = define_control ($1, $2, $3, $4, $5, $6, class,
+                                default_style | WS_CHILD | WS_VISIBLE, 0);
+           if ($7 != NULL)
+             {
+               if (dialog.ex == NULL)
+                 rcparse_warning (_("control data requires DIALOGEX"));
+               $$->data = $7;
+             }
+         }
+       | optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
+           control_params_styleexpr optcnumexpr opt_control_data
+         {
+           $$ = define_control ($1, $2, $3, $4, $5, $6, class, style, $8);
+           if ($9 != NULL)
+             {
+               if (dialog.ex == NULL)
+                 rcparse_warning (_("control data requires DIALOGEX"));
+               $$->data = $9;
+             }
+         }
+       | optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr
+           control_params_styleexpr cnumexpr cnumexpr opt_control_data
+         {
+           $$ = define_control ($1, $2, $3, $4, $5, $6, class, style, $8);
+           if (dialog.ex == NULL)
+             rcparse_warning (_("help ID requires DIALOGEX"));
+           $$->help = $9;
+           $$->data = $10;
+         }
+       ;
+
+optstringc:
+         /* empty */
+         {
+           $$ = NULL;
+         }
+       | QUOTEDSTRING ','
+         {
+           $$ = $1;
+         }
+       ;
+
+opt_control_data:
+         /* empty */
+         {
+           $$ = NULL;
+         }
+       | BEG optrcdata_data END
+         {
+           $$ = $2.first;
+         }
+       ;
+
+/* These only exist to parse a reduction out of a common case.  */
+
+control_styleexpr:
+         ','
+         { style = WS_CHILD | WS_VISIBLE; }
+         styleexpr
+       ;
+
+icon_styleexpr:
+         ','
+         { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
+         styleexpr
+       ;
+
+control_params_styleexpr:
+         ','
+         { style = base_style | WS_CHILD | WS_VISIBLE; }
+         styleexpr
+       ;
+
+/* Font resources.  */
+
+font:
+         id FONT memflags_move_discard file_name
+         {
+           define_font ($1, &$3, $4);
+         }
+       ;
+
+/* Icon resources.  */
+
+icon:
+         id ICON memflags_move_discard file_name
+         {
+           define_icon ($1, &$3, $4);
+         }
+       ;
+
+/* Language command.  This changes the static variable language, which
+   affects all subsequent resources.  */
+
+language:
+         LANGUAGE numexpr cnumexpr
+         {
+           language = $2 | ($3 << 8);
+         }
+       ;
+
+/* Menu resources.  */
+
+menu:
+         id MENU suboptions BEG menuitems END
+         {
+           define_menu ($1, &$3, $5);
+         }
+       ;
+
+menuitems:
+         /* empty */
+         {
+           $$ = NULL;
+         }
+       | menuitems menuitem
+         {
+           if ($1 == NULL)
+             $$ = $2;
+           else
+             {
+               struct menuitem **pp;
+
+               for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
+                 ;
+               *pp = $2;
+               $$ = $1;
+             }
+         }
+       ;
+
+menuitem:
+         MENUITEM QUOTEDSTRING cnumexpr menuitem_flags
+         {
+           $$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
+         }
+       | MENUITEM SEPARATOR
+         {
+           $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
+         }
+       | POPUP QUOTEDSTRING menuitem_flags BEG menuitems END
+         {
+           $$ = define_menuitem ($2, 0, $3, 0, 0, $5);
+         }
+       ;
+
+menuitem_flags:
+         /* empty */
+         {
+           $$ = 0;
+         }
+       | menuitem_flags ',' menuitem_flag
+         {
+           $$ = $1 | $3;
+         }
+       | menuitem_flags menuitem_flag
+         {
+           $$ = $1 | $2;
+         }
+       ;
+
+menuitem_flag:
+         CHECKED
+         {
+           $$ = MENUITEM_CHECKED;
+         }
+       | GRAYED
+         {
+           $$ = MENUITEM_GRAYED;
+         }
+       | HELP
+         {
+           $$ = MENUITEM_HELP;
+         }
+       | INACTIVE
+         {
+           $$ = MENUITEM_INACTIVE;
+         }
+       | MENUBARBREAK
+         {
+           $$ = MENUITEM_MENUBARBREAK;
+         }
+       | MENUBREAK
+         {
+           $$ = MENUITEM_MENUBREAK;
+         }
+       ;
+
+/* Menuex resources.  */
+
+menuex:
+         id MENUEX suboptions BEG menuexitems END
+         {
+           define_menu ($1, &$3, $5);
+         }
+       ;
+
+menuexitems:
+         /* empty */
+         {
+           $$ = NULL;
+         }
+       | menuexitems menuexitem
+         {
+           if ($1 == NULL)
+             $$ = $2;
+           else
+             {
+               struct menuitem **pp;
+
+               for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
+                 ;
+               *pp = $2;
+               $$ = $1;
+             }
+         }
+       ;
+
+menuexitem:
+         MENUITEM QUOTEDSTRING
+         {
+           $$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
+         }
+       | MENUITEM QUOTEDSTRING cnumexpr
+         {
+           $$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
+         }
+       | MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr
+         {
+           $$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
+         }
+       | MENUITEM SEPARATOR
+         {
+           $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
+         }
+       | POPUP QUOTEDSTRING BEG menuexitems END
+         {
+           $$ = define_menuitem ($2, 0, 0, 0, 0, $4);
+         }
+       | POPUP QUOTEDSTRING cnumexpr BEG menuexitems END
+         {
+           $$ = define_menuitem ($2, $3, 0, 0, 0, $5);
+         }
+       | POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END
+         {
+           $$ = define_menuitem ($2, $3, $4, 0, 0, $6);
+         }
+       | POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr
+           BEG menuexitems END
+         {
+           $$ = define_menuitem ($2, $3, $4, $5, $6, $8);
+         }
+       ;
+
+/* Messagetable resources.  */
+
+messagetable:
+         id MESSAGETABLE memflags_move file_name
+         {
+           define_messagetable ($1, &$3, $4);
+         }
+       ;
+
+/* Rcdata resources.  */
+
+rcdata:
+         id RCDATA suboptions BEG optrcdata_data END
+         {
+           define_rcdata ($1, &$3, $5.first);
+         }
+       ;
+
+/* We use a different lexing algorithm, because rcdata strings may
+   contain embedded null bytes, and we need to know the length to use.  */
+
+optrcdata_data:
+         {
+           rcparse_rcdata ();
+         }
+         optrcdata_data_int
+         {
+           rcparse_normal ();
+           $$ = $2;
+         }
+       ;
+
+optrcdata_data_int:
+         /* empty */
+         {
+           $$.first = NULL;
+           $$.last = NULL;
+         }
+       | rcdata_data
+         {
+           $$ = $1;
+         }
+       ;
+
+rcdata_data:
+         SIZEDSTRING
+         {
+           struct rcdata_item *ri;
+
+           ri = define_rcdata_string ($1.s, $1.length);
+           $$.first = ri;
+           $$.last = ri;
+         }
+       | sizednumexpr
+         {
+           struct rcdata_item *ri;
+
+           ri = define_rcdata_number ($1.val, $1.dword);
+           $$.first = ri;
+           $$.last = ri;
+         }
+       | rcdata_data ',' SIZEDSTRING
+         {
+           struct rcdata_item *ri;
+
+           ri = define_rcdata_string ($3.s, $3.length);
+           $$.first = $1.first;
+           $1.last->next = ri;
+           $$.last = ri;
+         }
+       | rcdata_data ',' sizednumexpr
+         {
+           struct rcdata_item *ri;
+
+           ri = define_rcdata_number ($3.val, $3.dword);
+           $$.first = $1.first;
+           $1.last->next = ri;
+           $$.last = ri;
+         }
+       ;
+
+/* Stringtable resources.  */
+
+stringtable:
+         STRINGTABLE suboptions BEG 
+           { sub_res_info = $2; }
+           string_data END
+       ;
+
+string_data:
+         /* empty */
+       | string_data numexpr QUOTEDSTRING
+         {
+           define_stringtable (&sub_res_info, $2, $3);
+         }
+       | string_data numexpr ',' QUOTEDSTRING
+         {
+           define_stringtable (&sub_res_info, $2, $4);
+         }
+       ;
+
+/* User defined resources.  We accept general suboptions in the
+   file_name case to keep the parser happy.  */
+
+user:
+         id id suboptions BEG optrcdata_data END
+         {
+           define_user_data ($1, $2, &$3, $5.first);
+         }
+       | id id suboptions file_name
+         {
+           define_user_file ($1, $2, &$3, $4);
+         }
+       ;
+
+/* Versioninfo resources.  */
+
+versioninfo:
+         id VERSIONINFO fixedverinfo BEG verblocks END
+         {
+           define_versioninfo ($1, language, $3, $5);
+         }
+       ;
+
+fixedverinfo:
+         /* empty */
+         {
+           $$ = ((struct fixed_versioninfo *)
+                 res_alloc (sizeof (struct fixed_versioninfo)));
+           memset ($$, 0, sizeof (struct fixed_versioninfo));
+         }
+       | fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr
+         {
+           $1->file_version_ms = ($3 << 16) | $4;
+           $1->file_version_ls = ($5 << 16) | $6;
+           $$ = $1;
+         }
+       | fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr
+         {
+           $1->product_version_ms = ($3 << 16) | $4;
+           $1->product_version_ls = ($5 << 16) | $6;
+           $$ = $1;
+         }
+       | fixedverinfo FILEFLAGSMASK numexpr
+         {
+           $1->file_flags_mask = $3;
+           $$ = $1;
+         }
+       | fixedverinfo FILEFLAGS numexpr
+         {
+           $1->file_flags = $3;
+           $$ = $1;
+         }
+       | fixedverinfo FILEOS numexpr
+         {
+           $1->file_os = $3;
+           $$ = $1;
+         }
+       | fixedverinfo FILETYPE numexpr
+         {
+           $1->file_type = $3;
+           $$ = $1;
+         }
+       | fixedverinfo FILESUBTYPE numexpr
+         {
+           $1->file_subtype = $3;
+           $$ = $1;
+         }
+       ;
+
+/* To handle verblocks successfully, the lexer handles BLOCK
+   specially.  A BLOCK "StringFileInfo" is returned as
+   BLOCKSTRINGFILEINFO.  A BLOCK "VarFileInfo" is returned as
+   BLOCKVARFILEINFO.  A BLOCK with some other string returns BLOCK
+   with the string as the value.  */
+
+verblocks:
+         /* empty */
+         {
+           $$ = NULL;
+         }
+       | verblocks BLOCKSTRINGFILEINFO BEG BLOCK BEG vervals END END
+         {
+           $$ = append_ver_stringfileinfo ($1, $4, $6);
+         }
+       | verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END
+         {
+           $$ = append_ver_varfileinfo ($1, $5, $6);
+         }
+       ;
+
+vervals:
+         /* empty */
+         {
+           $$ = NULL;
+         }
+       | vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING
+         {
+           $$ = append_verval ($1, $3, $5);
+         }
+       ;
+
+vertrans:
+         /* empty */
+         {
+           $$ = NULL;
+         }
+       | vertrans cnumexpr cnumexpr
+         {
+           $$ = append_vertrans ($1, $2, $3);
+         }
+       ;
+
+/* A resource ID.  */
+
+id:
+         posnumexpr
+         {
+           $$.named = 0;
+           $$.u.id = $1;
+         }
+       | STRING
+         {
+           char *copy, *s;
+
+           /* It seems that resource ID's are forced to upper case.  */
+           copy = xstrdup ($1);
+           for (s = copy; *s != '\0'; s++)
+             if (islower ((unsigned char) *s))
+               *s = toupper ((unsigned char) *s);
+           res_string_to_id (&$$, copy);
+           free (copy);
+         }
+       ;
+
+/* Generic suboptions.  These may appear before the BEGIN in any
+   multiline statement.  */
+
+suboptions:
+         /* empty */
+         {
+           memset (&$$, 0, sizeof (struct res_res_info));
+           $$.language = language;
+           /* FIXME: Is this the right default?  */
+           $$.memflags = MEMFLAG_MOVEABLE;
+         }
+       | suboptions memflag
+         {
+           $$ = $1;
+           $$.memflags |= $2.on;
+           $$.memflags &=~ $2.off;
+         }
+       | suboptions CHARACTERISTICS numexpr
+         {
+           $$ = $1;
+           $$.characteristics = $3;
+         }
+       | suboptions LANGUAGE numexpr cnumexpr
+         {
+           $$ = $1;
+           $$.language = $3 | ($4 << 8);
+         }
+       | suboptions VERSIONK numexpr
+         {
+           $$ = $1;
+           $$.version = $3;
+         }
+       ;
+
+/* Memory flags which default to MOVEABLE and DISCARDABLE.  */
+
+memflags_move_discard:
+         /* empty */
+         {
+           memset (&$$, 0, sizeof (struct res_res_info));
+           $$.language = language;
+           $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
+         }
+       | memflags_move_discard memflag
+         {
+           $$ = $1;
+           $$.memflags |= $2.on;
+           $$.memflags &=~ $2.off;
+         }
+       ;
+
+/* Memory flags which default to MOVEABLE.  */
+
+memflags_move:
+         /* empty */
+         {
+           memset (&$$, 0, sizeof (struct res_res_info));
+           $$.language = language;
+           $$.memflags = MEMFLAG_MOVEABLE;
+         }
+       | memflags_move memflag
+         {
+           $$ = $1;
+           $$.memflags |= $2.on;
+           $$.memflags &=~ $2.off;
+         }
+       ;
+
+/* Memory flags.  This returns a struct with two integers, because we
+   sometimes want to set bits and we sometimes want to clear them.  */
+
+memflag:
+         MOVEABLE
+         {
+           $$.on = MEMFLAG_MOVEABLE;
+           $$.off = 0;
+         }
+       | FIXED
+         {
+           $$.on = 0;
+           $$.off = MEMFLAG_MOVEABLE;
+         }
+       | PURE
+         {
+           $$.on = MEMFLAG_PURE;
+           $$.off = 0;
+         }
+       | IMPURE
+         {
+           $$.on = 0;
+           $$.off = MEMFLAG_PURE;
+         }
+       | PRELOAD
+         {
+           $$.on = MEMFLAG_PRELOAD;
+           $$.off = 0;
+         }
+       | LOADONCALL
+         {
+           $$.on = 0;
+           $$.off = MEMFLAG_PRELOAD;
+         }
+       | DISCARDABLE
+         {
+           $$.on = MEMFLAG_DISCARDABLE;
+           $$.off = 0;
+         }
+       ;
+
+/* A file name.  */
+
+file_name:
+         QUOTEDSTRING
+         {
+           $$ = $1;
+         }
+       | STRING
+         {
+           $$ = $1;
+         }
+       ;
+
+/* A style expression.  This changes the static variable STYLE.  We do
+   it this way because rc appears to permit a style to be set to
+   something like
+       WS_GROUP | NOT WS_TABSTOP
+   to mean that a default of WS_TABSTOP should be removed.  Anything
+   which wants to accept a style must first set STYLE to the default
+   value.  The styleexpr nonterminal will change STYLE as specified by
+   the user.  Note that we do not accept arbitrary expressions here,
+   just numbers separated by '|'.  */
+
+styleexpr:
+         parennumber
+         {
+           style |= $1;
+         }
+       | NOT parennumber
+         {
+           style &=~ $2;
+         }
+       | styleexpr '|' parennumber
+         {
+           style |= $3;
+         }
+       | styleexpr '|' NOT parennumber
+         {
+           style &=~ $4;
+         }
+       ;
+
+parennumber:
+         NUMBER
+         {
+           $$ = $1.val;
+         }
+       | '(' numexpr ')'
+         {
+           $$ = $2;
+         }
+       ;
+
+/* An optional expression with a leading comma.  */
+
+optcnumexpr:
+         /* empty */
+         {
+           $$ = 0;
+         }
+       | cnumexpr
+         {
+           $$ = $1;
+         }
+       ;
+
+/* An expression with a leading comma.  */
+
+cnumexpr:
+         ',' numexpr
+         {
+           $$ = $2;
+         }
+       ;
+
+/* A possibly negated numeric expression.  */
+
+numexpr:
+         sizednumexpr
+         {
+           $$ = $1.val;
+         }
+       ;
+
+/* A possibly negated expression with a size.  */
+
+sizednumexpr:
+         NUMBER
+         {
+           $$ = $1;
+         }
+       | '(' sizednumexpr ')'
+         {
+           $$ = $2;
+         }
+       | '~' sizednumexpr %prec '~'
+         {
+           $$.val = ~ $2.val;
+           $$.dword = $2.dword;
+         }
+       | '-' sizednumexpr %prec NEG
+         {
+           $$.val = - $2.val;
+           $$.dword = $2.dword;
+         }
+       | sizednumexpr '*' sizednumexpr
+         {
+           $$.val = $1.val * $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizednumexpr '/' sizednumexpr
+         {
+           $$.val = $1.val / $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizednumexpr '%' sizednumexpr
+         {
+           $$.val = $1.val % $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizednumexpr '+' sizednumexpr
+         {
+           $$.val = $1.val + $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizednumexpr '-' sizednumexpr
+         {
+           $$.val = $1.val - $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizednumexpr '&' sizednumexpr
+         {
+           $$.val = $1.val & $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizednumexpr '^' sizednumexpr
+         {
+           $$.val = $1.val ^ $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizednumexpr '|' sizednumexpr
+         {
+           $$.val = $1.val | $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       ;
+
+/* An expression with a leading comma which does not use unary
+   negation.  */
+
+cposnumexpr:
+         ',' posnumexpr
+         {
+           $$ = $2;
+         }
+       ;
+
+/* An expression which does not use unary negation.  */
+
+posnumexpr:
+         sizedposnumexpr
+         {
+           $$ = $1.val;
+         }
+       ;
+
+/* An expression which does not use unary negation.  We separate unary
+   negation to avoid parsing conflicts when two numeric expressions
+   appear consecutively.  */
+
+sizedposnumexpr:
+         NUMBER
+         {
+           $$ = $1;
+         }
+       | '(' sizednumexpr ')'
+         {
+           $$ = $2;
+         }
+       | '~' sizednumexpr %prec '~'
+         {
+           $$.val = ~ $2.val;
+           $$.dword = $2.dword;
+         }
+       | sizedposnumexpr '*' sizednumexpr
+         {
+           $$.val = $1.val * $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizedposnumexpr '/' sizednumexpr
+         {
+           $$.val = $1.val / $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizedposnumexpr '%' sizednumexpr
+         {
+           $$.val = $1.val % $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizedposnumexpr '+' sizednumexpr
+         {
+           $$.val = $1.val + $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizedposnumexpr '-' sizednumexpr
+         {
+           $$.val = $1.val - $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizedposnumexpr '&' sizednumexpr
+         {
+           $$.val = $1.val & $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizedposnumexpr '^' sizednumexpr
+         {
+           $$.val = $1.val ^ $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       | sizedposnumexpr '|' sizednumexpr
+         {
+           $$.val = $1.val | $3.val;
+           $$.dword = $1.dword || $3.dword;
+         }
+       ;
+
+%%
+
+/* Set the language from the command line.  */
+
+void
+rcparse_set_language (lang)
+     int lang;
+{
+  language = lang;
+}
diff --git a/binutils/rdcoff.c b/binutils/rdcoff.c
new file mode 100644 (file)
index 0000000..ee68bc6
--- /dev/null
@@ -0,0 +1,889 @@
+/* stabs.c -- Parse COFF debugging information
+   Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file contains code which parses COFF debugging information.  */
+
+#include "bfd.h"
+#include "coff/internal.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "demangle.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* FIXME: We should not need this BFD internal file.  We need it for
+   the N_BTMASK, etc., values.  */
+#include "libcoff.h"
+
+/* These macros extract the right mask and shifts for this BFD.  They
+   assume that there is a local variable named ABFD.  This is so that
+   macros like ISFCN and DECREF, from coff/internal.h, will work
+   without modification.  */
+#define N_BTMASK (coff_data (abfd)->local_n_btmask)
+#define        N_BTSHFT (coff_data (abfd)->local_n_btshft)
+#define        N_TMASK  (coff_data (abfd)->local_n_tmask)
+#define        N_TSHIFT (coff_data (abfd)->local_n_tshift)
+
+/* This structure is used to hold the symbols, as well as the current
+   location within the symbols.  */
+
+struct coff_symbols
+{
+  /* The symbols.  */
+  asymbol **syms;
+  /* The number of symbols.  */
+  long symcount;
+  /* The index of the current symbol.  */
+  long symno;
+  /* The index of the current symbol in the COFF symbol table (where
+     each auxent counts as a symbol).  */
+  long coff_symno;
+};
+
+/* The largest basic type we are prepared to handle.  */
+
+#define T_MAX (T_LNGDBL)
+
+/* This structure is used to hold slots.  */
+
+struct coff_slots
+{
+  /* Next set of slots.  */
+  struct coff_slots *next;
+  /* Slots.  */
+#define COFF_SLOTS (16)
+  debug_type slots[COFF_SLOTS];
+};
+
+/* This structure is used to map symbol indices to types.  */
+
+struct coff_types
+{
+  /* Slots.  */
+  struct coff_slots *slots;
+  /* Basic types.  */
+  debug_type basic[T_MAX + 1];
+};
+
+static debug_type *coff_get_slot PARAMS ((struct coff_types *, int));
+static debug_type parse_coff_type
+  PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int,
+          union internal_auxent *, boolean, PTR));
+static debug_type parse_coff_base_type
+  PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int,
+          union internal_auxent *, PTR));
+static debug_type parse_coff_struct_type
+  PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, int,
+          union internal_auxent *, PTR));
+static debug_type parse_coff_enum_type
+  PARAMS ((bfd *, struct coff_symbols *, struct coff_types *,
+          union internal_auxent *, PTR));
+static boolean parse_coff_symbol
+  PARAMS ((bfd *, struct coff_types *, asymbol *, long,
+          struct internal_syment *, PTR, debug_type, boolean));
+\f
+/* Return the slot for a type.  */
+
+static debug_type *
+coff_get_slot (types, indx)
+     struct coff_types *types;
+     int indx;
+{
+  struct coff_slots **pps;
+
+  pps = &types->slots;
+
+  while (indx >= COFF_SLOTS)
+    {
+      if (*pps == NULL)
+       {
+         *pps = (struct coff_slots *) xmalloc (sizeof **pps);
+         memset (*pps, 0, sizeof **pps);
+       }
+      pps = &(*pps)->next;
+      indx -= COFF_SLOTS;
+    }
+
+  if (*pps == NULL)
+    {
+      *pps = (struct coff_slots *) xmalloc (sizeof **pps);
+      memset (*pps, 0, sizeof **pps);
+    }
+
+  return (*pps)->slots + indx;
+}
+
+/* Parse a COFF type code in NTYPE.  */
+
+static debug_type
+parse_coff_type (abfd, symbols, types, coff_symno, ntype, pauxent, useaux,
+                dhandle)
+     bfd *abfd;
+     struct coff_symbols *symbols;
+     struct coff_types *types;
+     long coff_symno;
+     int ntype;
+     union internal_auxent *pauxent;
+     boolean useaux;
+     PTR dhandle;
+{
+  debug_type type;
+
+  if ((ntype & ~N_BTMASK) != 0)
+    {
+      int newtype;
+
+      newtype = DECREF (ntype);
+
+      if (ISPTR (ntype))
+       {
+         type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
+                                 pauxent, useaux, dhandle);
+         type = debug_make_pointer_type (dhandle, type);
+       }
+      else if (ISFCN (ntype))
+       {
+         type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
+                                 pauxent, useaux, dhandle);
+         type = debug_make_function_type (dhandle, type, (debug_type *) NULL,
+                                          false);
+       }
+      else if (ISARY (ntype))
+       {
+         int n;
+
+         if (pauxent == NULL)
+           n = 0;
+         else
+           {
+             unsigned short *dim;
+             int i;
+
+             /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets
+                 the c_naux field of the syment to 0.  */
+
+             /* Move the dimensions down, so that the next array
+                 picks up the next one.  */
+             dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen;
+             n = dim[0];
+             for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++)
+               *dim = *(dim + 1);
+             *dim = 0;
+           }
+
+         type = parse_coff_type (abfd, symbols, types, coff_symno, newtype,
+                                 pauxent, false, dhandle);
+         type = debug_make_array_type (dhandle, type,
+                                       parse_coff_base_type (abfd, symbols,
+                                                             types,
+                                                             coff_symno,
+                                                             T_INT,
+                                                             NULL, dhandle),
+                                       0, n - 1, false);
+       }
+      else
+       {
+         fprintf (stderr, _("%s: parse_coff_type: Bad type code 0x%x\n"),
+                  program_name, ntype);
+         return DEBUG_TYPE_NULL;
+       }
+
+      return type;
+    }
+
+  if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0)
+    {
+      debug_type *slot;
+
+      /* This is a reference to an existing type.  FIXME: gdb checks
+        that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG.  */
+      slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l);
+      if (*slot != DEBUG_TYPE_NULL)
+       return *slot;
+      else
+       return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
+    }
+
+  /* If the aux entry has already been used for something, useaux will
+     have been set to false, indicating that parse_coff_base_type
+     should not use it.  We need to do it this way, rather than simply
+     passing pauxent as NULL, because we need to be able handle
+     multiple array dimensions while still discarding pauxent after
+     having handled all of them.  */
+  if (! useaux)
+    pauxent = NULL;
+
+  return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype,
+                              pauxent, dhandle);
+}
+
+/* Parse a basic COFF type in NTYPE.  */
+
+static debug_type
+parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent,
+                     dhandle)
+     bfd *abfd;
+     struct coff_symbols *symbols;
+     struct coff_types *types;
+     long coff_symno;
+     int ntype;
+     union internal_auxent *pauxent;
+     PTR dhandle;
+{
+  debug_type ret;
+  boolean set_basic;
+  const char *name;
+  debug_type *slot;
+
+  if (ntype >= 0
+      && ntype <= T_MAX
+      && types->basic[ntype] != DEBUG_TYPE_NULL)
+    return types->basic[ntype];
+
+  set_basic = true;
+  name = NULL;
+
+  switch (ntype)
+    {
+    default:
+      ret = debug_make_void_type (dhandle);
+      break;
+
+    case T_NULL:
+    case T_VOID:
+      ret = debug_make_void_type (dhandle);
+      name = "void";
+      break;
+
+    case T_CHAR:
+      ret = debug_make_int_type (dhandle, 1, false);
+      name = "char";
+      break;
+
+    case T_SHORT:
+      ret = debug_make_int_type (dhandle, 2, false);
+      name = "short";
+      break;
+
+    case T_INT:
+      /* FIXME: Perhaps the size should depend upon the architecture.  */
+      ret = debug_make_int_type (dhandle, 4, false);
+      name = "int";
+      break;
+
+    case T_LONG:
+      ret = debug_make_int_type (dhandle, 4, false);
+      name = "long";
+      break;
+
+    case T_FLOAT:
+      ret = debug_make_float_type (dhandle, 4);
+      name = "float";
+      break;
+
+    case T_DOUBLE:
+      ret = debug_make_float_type (dhandle, 8);
+      name = "double";
+      break;
+
+    case T_LNGDBL:
+      ret = debug_make_float_type (dhandle, 12);
+      name = "long double";
+      break;
+
+    case T_UCHAR:
+      ret = debug_make_int_type (dhandle, 1, true);
+      name = "unsigned char";
+      break;
+
+    case T_USHORT:
+      ret = debug_make_int_type (dhandle, 2, true);
+      name = "unsigned short";
+      break;
+
+    case T_UINT:
+      ret = debug_make_int_type (dhandle, 4, true);
+      name = "unsigned int";
+      break;
+
+    case T_ULONG:
+      ret = debug_make_int_type (dhandle, 4, true);
+      name = "unsigned long";
+      break;
+
+    case T_STRUCT:
+      if (pauxent == NULL)
+       ret = debug_make_struct_type (dhandle, true, 0,
+                                     (debug_field *) NULL);
+      else
+       ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
+                                     dhandle);
+
+      slot = coff_get_slot (types, coff_symno);
+      *slot = ret;
+
+      set_basic = false;
+      break;
+
+    case T_UNION:
+      if (pauxent == NULL)
+       ret = debug_make_struct_type (dhandle, false, 0, (debug_field *) NULL);
+      else
+       ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent,
+                                     dhandle);
+
+      slot = coff_get_slot (types, coff_symno);
+      *slot = ret;
+
+      set_basic = false;
+      break;
+
+    case T_ENUM:
+      if (pauxent == NULL)
+       ret = debug_make_enum_type (dhandle, (const char **) NULL,
+                                   (bfd_signed_vma *) NULL);
+      else
+       ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle);
+
+      slot = coff_get_slot (types, coff_symno);
+      *slot = ret;
+
+      set_basic = false;
+      break;
+    }
+
+  if (name != NULL)
+    ret = debug_name_type (dhandle, name, ret);
+
+  if (set_basic
+      && ntype >= 0
+      && ntype <= T_MAX)
+    types->basic[ntype] = ret;
+
+  return ret;
+}
+
+/* Parse a struct type.  */
+
+static debug_type
+parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle)
+     bfd *abfd;
+     struct coff_symbols *symbols;
+     struct coff_types *types;
+     int ntype;
+     union internal_auxent *pauxent;
+     PTR dhandle;
+{
+  long symend;
+  int alloc;
+  debug_field *fields;
+  int count;
+  boolean done;
+
+  symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
+
+  alloc = 10;
+  fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+  count = 0;
+
+  done = false;
+  while (! done
+        && symbols->coff_symno < symend
+        && symbols->symno < symbols->symcount)
+    {
+      asymbol *sym;
+      long this_coff_symno;
+      struct internal_syment syment;
+      union internal_auxent auxent;
+      union internal_auxent *psubaux;
+      bfd_vma bitpos = 0, bitsize = 0;
+
+      sym = symbols->syms[symbols->symno];
+
+      if (! bfd_coff_get_syment (abfd, sym, &syment))
+       {
+         fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"),
+                  program_name, bfd_errmsg (bfd_get_error ()));
+         return DEBUG_TYPE_NULL;
+       }
+
+      this_coff_symno = symbols->coff_symno;
+
+      ++symbols->symno;
+      symbols->coff_symno += 1 + syment.n_numaux;
+
+      if (syment.n_numaux == 0)
+       psubaux = NULL;
+      else
+       {
+         if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
+           {
+             fprintf (stderr, _("%s: bfd_coff_get_auxent failed: %s\n"),
+                      program_name, bfd_errmsg (bfd_get_error ()));
+             return DEBUG_TYPE_NULL;
+           }
+         psubaux = &auxent;
+       }
+
+      switch (syment.n_sclass)
+       {
+       case C_MOS:
+       case C_MOU:
+         bitpos = 8 * bfd_asymbol_value (sym);
+         bitsize = 0;
+         break;
+
+       case C_FIELD:
+         bitpos = bfd_asymbol_value (sym);
+         bitsize = auxent.x_sym.x_misc.x_lnsz.x_size;
+         break;
+
+       case C_EOS:
+         done = true;
+         break;
+       }
+
+      if (! done)
+       {
+         debug_type ftype;
+         debug_field f;
+
+         ftype = parse_coff_type (abfd, symbols, types, this_coff_symno,
+                                  syment.n_type, psubaux, true, dhandle);
+         f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype,
+                               bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC);
+         if (f == DEBUG_FIELD_NULL)
+           return DEBUG_TYPE_NULL;
+
+         if (count + 1 >= alloc)
+           {
+             alloc += 10;
+             fields = ((debug_field *)
+                       xrealloc (fields, alloc * sizeof *fields));
+           }
+
+         fields[count] = f;
+         ++count;
+       }
+    }
+
+  fields[count] = DEBUG_FIELD_NULL;
+
+  return debug_make_struct_type (dhandle, ntype == T_STRUCT,
+                                pauxent->x_sym.x_misc.x_lnsz.x_size,
+                                fields);
+}
+
+/* Parse an enum type.  */
+
+static debug_type
+parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle)
+     bfd *abfd;
+     struct coff_symbols *symbols;
+     struct coff_types *types;
+     union internal_auxent *pauxent;
+     PTR dhandle;
+{
+  long symend;
+  int alloc;
+  const char **names;
+  bfd_signed_vma *vals;
+  int count;
+  boolean done;
+
+  symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l;
+
+  alloc = 10;
+  names = (const char **) xmalloc (alloc * sizeof *names);
+  vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals);
+  count = 0;
+
+  done = false;
+  while (! done
+        && symbols->coff_symno < symend
+        && symbols->symno < symbols->symcount)
+    {
+      asymbol *sym;
+      struct internal_syment syment;
+
+      sym = symbols->syms[symbols->symno];
+
+      if (! bfd_coff_get_syment (abfd, sym, &syment))
+       {
+         fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"),
+                  program_name, bfd_errmsg (bfd_get_error ()));
+         return DEBUG_TYPE_NULL;
+       }
+
+      ++symbols->symno;
+      symbols->coff_symno += 1 + syment.n_numaux;
+
+      switch (syment.n_sclass)
+       {
+       case C_MOE:
+         if (count + 1 >= alloc)
+           {
+             alloc += 10;
+             names = ((const char **)
+                      xrealloc (names, alloc * sizeof *names));
+             vals = ((bfd_signed_vma *)
+                     xrealloc (vals, alloc * sizeof *vals));
+           }
+
+         names[count] = bfd_asymbol_name (sym);
+         vals[count] = bfd_asymbol_value (sym);
+         ++count;
+         break;
+
+       case C_EOS:
+         done = true;
+         break;
+       }
+    }
+
+  names[count] = NULL;
+
+  return debug_make_enum_type (dhandle, names, vals);
+}
+
+/* Handle a single COFF symbol.  */
+
+static boolean
+parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type,
+                  within_function)
+     bfd *abfd;
+     struct coff_types *types;
+     asymbol *sym;
+     long coff_symno;
+     struct internal_syment *psyment;
+     PTR dhandle;
+     debug_type type;
+     boolean within_function;
+{
+  switch (psyment->n_sclass)
+    {
+    case C_NULL:
+      break;
+
+    case C_AUTO:
+      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+                                  DEBUG_LOCAL, bfd_asymbol_value (sym)))
+       return false;
+      break;
+
+    case C_EXT:
+      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+                                  DEBUG_GLOBAL, bfd_asymbol_value (sym)))
+       return false;
+      break;
+
+    case C_STAT:
+      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+                                  (within_function
+                                   ? DEBUG_LOCAL_STATIC
+                                   : DEBUG_STATIC),
+                                  bfd_asymbol_value (sym)))
+       return false;
+      break;
+
+    case C_REG:
+      /* FIXME: We may need to convert the register number.  */
+      if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+                                  DEBUG_REGISTER, bfd_asymbol_value (sym)))
+       return false;
+      break;
+
+    case C_LABEL:
+      break;
+
+    case C_ARG:
+      if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
+                                   DEBUG_PARM_STACK, bfd_asymbol_value (sym)))
+       return false;
+      break;
+
+    case C_REGPARM:
+      /* FIXME: We may need to convert the register number.  */
+      if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
+                                   DEBUG_PARM_REG, bfd_asymbol_value (sym)))
+       return false;
+      break;
+
+    case C_TPDEF:
+      type = debug_name_type (dhandle, bfd_asymbol_name (sym), type);
+      if (type == DEBUG_TYPE_NULL)
+       return false;
+      break;
+
+    case C_STRTAG:
+    case C_UNTAG:
+    case C_ENTAG:
+      {
+       debug_type *slot;
+
+       type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type);
+       if (type == DEBUG_TYPE_NULL)
+         return false;
+
+       /* Store the named type into the slot, so that references get
+           the name.  */
+       slot = coff_get_slot (types, coff_symno);
+       *slot = type;
+      }
+      break;
+
+    default:
+      break;
+    }
+
+  return true;                            
+}
+
+/* This is the main routine.  It looks through all the symbols and
+   handles them.  */
+
+boolean
+parse_coff (abfd, syms, symcount, dhandle)
+     bfd *abfd;
+     asymbol **syms;
+     long symcount;
+     PTR dhandle;
+{
+  struct coff_symbols symbols;
+  struct coff_types types;
+  int i;
+  long next_c_file;
+  const char *fnname;
+  int fnclass;
+  int fntype;
+  bfd_vma fnend;
+  alent *linenos;
+  boolean within_function;
+  long this_coff_symno;
+
+  symbols.syms = syms;
+  symbols.symcount = symcount;
+  symbols.symno = 0;
+  symbols.coff_symno = 0;
+
+  types.slots = NULL;
+  for (i = 0; i <= T_MAX; i++)
+    types.basic[i] = DEBUG_TYPE_NULL;
+
+  next_c_file = -1;
+  fnname = NULL;
+  fnclass = 0;
+  fntype = 0;
+  fnend = 0;
+  linenos = NULL;
+  within_function = false;
+
+  while (symbols.symno < symcount)
+    {
+      asymbol *sym;
+      const char *name;
+      struct internal_syment syment;
+      union internal_auxent auxent;
+      union internal_auxent *paux;
+      debug_type type;
+
+      sym = syms[symbols.symno];
+
+      if (! bfd_coff_get_syment (abfd, sym, &syment))
+       {
+         fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"),
+                  program_name, bfd_errmsg (bfd_get_error ()));
+         return false;
+       }
+
+      name = bfd_asymbol_name (sym);
+
+      this_coff_symno = symbols.coff_symno;
+
+      ++symbols.symno;
+      symbols.coff_symno += 1 + syment.n_numaux;
+
+      /* We only worry about the first auxent, because that is the
+        only one which is relevant for debugging information.  */
+      if (syment.n_numaux == 0)
+       paux = NULL;
+      else
+       {
+         if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent))
+           {
+             fprintf (stderr, _("%s: bfd_coff_get_auxent failed: %s\n"),
+                      program_name, bfd_errmsg (bfd_get_error ()));
+             return false;
+           }
+         paux = &auxent;
+       }
+
+      if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE)
+       {
+         /* The last C_FILE symbol points to the first external
+             symbol.  */
+         if (! debug_set_filename (dhandle, "*globals*"))
+           return false;
+       }
+
+      switch (syment.n_sclass)
+       {
+       case C_EFCN:
+       case C_EXTDEF:
+       case C_ULABEL:
+       case C_USTATIC:
+       case C_LINE:
+       case C_ALIAS:
+       case C_HIDDEN:
+         /* Just ignore these classes.  */
+         break;
+
+       case C_FILE:
+         next_c_file = syment.n_value;
+         if (! debug_set_filename (dhandle, name))
+           return false;
+         break;
+
+       case C_STAT:
+         /* Ignore static symbols with a type of T_NULL.  These
+             represent section entries.  */
+         if (syment.n_type == T_NULL)
+           break;
+         /* Fall through.  */
+       case C_EXT:
+         if (ISFCN (syment.n_type))
+           {
+             fnname = name;
+             fnclass = syment.n_sclass;
+             fntype = syment.n_type;
+             if (syment.n_numaux > 0)
+               fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize;
+             else
+               fnend = 0;
+             linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym));
+             break;
+           }
+         type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
+                                 syment.n_type, paux, true, dhandle);
+         if (type == DEBUG_TYPE_NULL)
+           return false;
+         if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
+                                  dhandle, type, within_function))
+           return false;
+         break;
+
+       case C_FCN:
+         if (strcmp (name, ".bf") == 0)
+           {
+             if (fnname == NULL)
+               {
+                 fprintf (stderr, _("%s: %ld: .bf without preceding function\n"),
+                          program_name, this_coff_symno);
+                 return false;
+               }
+
+             type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
+                                     DECREF (fntype), paux, false, dhandle);
+             if (type == DEBUG_TYPE_NULL)
+               return false;
+
+             if (! debug_record_function (dhandle, fnname, type,
+                                          fnclass == C_EXT,
+                                          bfd_asymbol_value (sym)))
+               return false;
+
+             if (linenos != NULL)
+               {
+                 int base;
+                 bfd_vma addr;
+
+                 if (syment.n_numaux == 0)
+                   base = 0;
+                 else
+                   base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1;
+
+                 addr = bfd_get_section_vma (abfd, bfd_get_section (sym));
+
+                 ++linenos;
+
+                 while (linenos->line_number != 0)
+                   {
+                     if (! debug_record_line (dhandle,
+                                              linenos->line_number + base,
+                                              linenos->u.offset + addr))
+                       return false;
+                     ++linenos;
+                   }
+               }
+
+             fnname = NULL;
+             linenos = NULL;
+             fnclass = 0;
+             fntype = 0;
+
+             within_function = true;
+           }
+         else if (strcmp (name, ".ef") == 0)
+           {
+             if (! within_function)
+               {
+                 fprintf (stderr, _("%s: %ld: unexpected .ef\n"),
+                          program_name, this_coff_symno);
+                 return false;
+               }
+
+             if (bfd_asymbol_value (sym) > fnend)
+               fnend = bfd_asymbol_value (sym);
+             if (! debug_end_function (dhandle, fnend))
+               return false;
+
+             fnend = 0;
+             within_function = false;
+           }
+         break;
+
+       case C_BLOCK:
+         if (strcmp (name, ".bb") == 0)
+           {
+             if (! debug_start_block (dhandle, bfd_asymbol_value (sym)))
+               return false;
+           }
+         else if (strcmp (name, ".eb") == 0)
+           {
+             if (! debug_end_block (dhandle, bfd_asymbol_value (sym)))
+               return false;
+           }
+         break;
+
+       default:
+         type = parse_coff_type (abfd, &symbols, &types, this_coff_symno,
+                                 syment.n_type, paux, true, dhandle);
+         if (type == DEBUG_TYPE_NULL)
+           return false;
+         if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment,
+                                  dhandle, type, within_function))
+           return false;
+         break;
+       }
+    }
+
+  return true;
+}
diff --git a/binutils/rddbg.c b/binutils/rddbg.c
new file mode 100644 (file)
index 0000000..9428c37
--- /dev/null
@@ -0,0 +1,448 @@
+/* rddbg.c -- Read debugging information into a generic form.
+   Copyright (C) 1995, 96, 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file reads debugging information into a generic form.  This
+   file knows how to dig the debugging information out of an object
+   file.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+#include "budbg.h"
+
+static boolean read_section_stabs_debugging_info
+  PARAMS ((bfd *, asymbol **, long, PTR, boolean *));
+static boolean read_symbol_stabs_debugging_info
+  PARAMS ((bfd *, asymbol **, long, PTR, boolean *));
+static boolean read_ieee_debugging_info PARAMS ((bfd *, PTR, boolean *));
+static void save_stab PARAMS ((int, int, bfd_vma, const char *));
+static void stab_context PARAMS ((void));
+static void free_saved_stabs PARAMS ((void));
+
+/* Read debugging information from a BFD.  Returns a generic debugging
+   pointer.  */
+
+PTR
+read_debugging_info (abfd, syms, symcount)
+     bfd *abfd;
+     asymbol **syms;
+     long symcount;
+{
+  PTR dhandle;
+  boolean found;
+
+  dhandle = debug_init ();
+  if (dhandle == NULL)
+    return NULL;
+
+  if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle,
+                                          &found))
+    return NULL;
+
+  if (bfd_get_flavour (abfd) == bfd_target_aout_flavour)
+    {
+      if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle,
+                                             &found))
+       return NULL;
+    }
+
+  if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour)
+    {
+      if (! read_ieee_debugging_info (abfd, dhandle, &found))
+       return NULL;
+    }
+
+  /* Try reading the COFF symbols if we didn't find any stabs in COFF
+     sections.  */
+  if (! found
+      && bfd_get_flavour (abfd) == bfd_target_coff_flavour
+      && symcount > 0)
+    {
+      if (! parse_coff (abfd, syms, symcount, dhandle))
+       return NULL;
+      found = true;
+    }
+
+  if (! found)
+    {
+      fprintf (stderr, _("%s: no recognized debugging information\n"),
+              bfd_get_filename (abfd));
+      return NULL;
+    }
+
+  return dhandle;
+}
+
+/* Read stabs in sections debugging information from a BFD.  */
+
+static boolean
+read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound)
+     bfd *abfd;
+     asymbol **syms;
+     long symcount;
+     PTR dhandle;
+     boolean *pfound;
+{
+  static struct
+    {
+      const char *secname;
+      const char *strsecname;
+    } names[] = { { ".stab", ".stabstr" } };
+  unsigned int i;
+  PTR shandle;
+
+  *pfound = false;
+  shandle = NULL;
+
+  for (i = 0; i < sizeof names / sizeof names[0]; i++)
+    {
+      asection *sec, *strsec;
+
+      sec = bfd_get_section_by_name (abfd, names[i].secname);
+      strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
+      if (sec != NULL && strsec != NULL)
+       {
+         bfd_size_type stabsize, strsize;
+         bfd_byte *stabs, *strings;
+         bfd_byte *stab;
+         bfd_size_type stroff, next_stroff;
+
+         stabsize = bfd_section_size (abfd, sec);
+         stabs = (bfd_byte *) xmalloc (stabsize);
+         if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize))
+           {
+             fprintf (stderr, "%s: %s: %s\n",
+                      bfd_get_filename (abfd), names[i].secname,
+                      bfd_errmsg (bfd_get_error ()));
+             return false;
+           }
+
+         strsize = bfd_section_size (abfd, strsec);
+         strings = (bfd_byte *) xmalloc (strsize);
+         if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
+           {
+             fprintf (stderr, "%s: %s: %s\n",
+                      bfd_get_filename (abfd), names[i].strsecname,
+                      bfd_errmsg (bfd_get_error ()));
+             return false;
+           }
+
+         if (shandle == NULL)
+           {
+             shandle = start_stab (dhandle, abfd, true, syms, symcount);
+             if (shandle == NULL)
+               return false;
+           }
+
+         *pfound = true;
+
+         stroff = 0;
+         next_stroff = 0;
+         for (stab = stabs; stab < stabs + stabsize; stab += 12)
+           {
+             bfd_size_type strx;
+             int type;
+             int other;
+             int desc;
+             bfd_vma value;
+
+             /* This code presumes 32 bit values.  */
+
+             strx = bfd_get_32 (abfd, stab);
+             type = bfd_get_8 (abfd, stab + 4);
+             other = bfd_get_8 (abfd, stab + 5);
+             desc = bfd_get_16 (abfd, stab + 6);
+             value = bfd_get_32 (abfd, stab + 8);
+
+             if (type == 0)
+               {
+                 /* Special type 0 stabs indicate the offset to the
+                     next string table.  */
+                 stroff = next_stroff;
+                 next_stroff += value;
+               }
+             else
+               {
+                 char *f, *s;
+
+                 f = NULL;
+                 s = (char *) strings + stroff + strx;
+                 while (s[strlen (s) - 1] == '\\'
+                        && stab + 12 < stabs + stabsize)
+                   {
+                     char *p;
+
+                     stab += 12;
+                     p = s + strlen (s) - 1;
+                     *p = '\0';
+                     s = concat (s,
+                                 ((char *) strings
+                                  + stroff
+                                  + bfd_get_32 (abfd, stab)),
+                                 (const char *) NULL);
+
+                     /* We have to restore the backslash, because, if
+                         the linker is hashing stabs strings, we may
+                         see the same string more than once.  */
+                     *p = '\\';
+
+                     if (f != NULL)
+                       free (f);
+                     f = s;
+                   }
+
+                 save_stab (type, desc, value, s);
+
+                 if (! parse_stab (dhandle, shandle, type, desc, value, s))
+                   {
+                     stab_context ();
+                     free_saved_stabs ();
+                     return false;
+                   }
+
+                 /* Don't free f, since I think the stabs code
+                     expects strings to hang around.  This should be
+                     straightened out.  FIXME.  */
+               }
+           }
+
+         free_saved_stabs ();
+         free (stabs);
+
+         /* Don't free strings, since I think the stabs code expects
+             the strings to hang around.  This should be straightened
+             out.  FIXME.  */
+       }
+    }
+
+  if (shandle != NULL)
+    {
+      if (! finish_stab (dhandle, shandle))
+       return false;
+    }
+
+  return true;
+}
+
+/* Read stabs in the symbol table.  */
+
+static boolean
+read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound)
+     bfd *abfd;
+     asymbol **syms;
+     long symcount;
+     PTR dhandle;
+     boolean *pfound;
+{
+  PTR shandle;
+  asymbol **ps, **symend;
+
+  shandle = NULL;
+  symend = syms + symcount;
+  for (ps = syms; ps < symend; ps++)
+    {
+      symbol_info i;
+
+      bfd_get_symbol_info (abfd, *ps, &i);
+
+      if (i.type == '-')
+       {
+         const char *s;
+         char *f;
+
+         if (shandle == NULL)
+           {
+             shandle = start_stab (dhandle, abfd, false, syms, symcount);
+             if (shandle == NULL)
+               return false;
+           }
+
+         *pfound = true;
+
+         s = i.name;
+         f = NULL;
+         while (s[strlen (s) - 1] == '\\'
+                && ps + 1 < symend)
+           {
+             char *sc, *n;
+
+             ++ps;
+             sc = xstrdup (s);
+             sc[strlen (sc) - 1] = '\0';
+             n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL);
+             free (sc);
+             if (f != NULL)
+               free (f);
+             f = n;
+             s = n;
+           }
+
+         save_stab (i.stab_type, i.stab_desc, i.value, s);
+
+         if (! parse_stab (dhandle, shandle, i.stab_type, i.stab_desc,
+                           i.value, s))
+           {
+             stab_context ();
+             free_saved_stabs ();
+             return false;
+           }
+
+         /* Don't free f, since I think the stabs code expects
+            strings to hang around.  This should be straightened out.
+            FIXME.  */
+       }
+    }
+
+  free_saved_stabs ();
+
+  if (shandle != NULL)
+    {
+      if (! finish_stab (dhandle, shandle))
+       return false;
+    }
+
+  return true;
+}
+
+/* Read IEEE debugging information.  */
+
+static boolean
+read_ieee_debugging_info (abfd, dhandle, pfound)
+     bfd *abfd;
+     PTR dhandle;
+     boolean *pfound;
+{
+  asection *dsec;
+  bfd_size_type size;
+  bfd_byte *contents;
+
+  /* The BFD backend puts the debugging information into a section
+     named .debug.  */
+
+  dsec = bfd_get_section_by_name (abfd, ".debug");
+  if (dsec == NULL)
+    return true;
+
+  size = bfd_section_size (abfd, dsec);
+  contents = (bfd_byte *) xmalloc (size);
+  if (! bfd_get_section_contents (abfd, dsec, contents, 0, size))
+    return false;
+
+  if (! parse_ieee (dhandle, abfd, contents, size))
+    return false;
+
+  free (contents);
+
+  *pfound = true;
+
+  return true;
+}
+\f
+/* Record stabs strings, so that we can give some context for errors.  */
+
+#define SAVE_STABS_COUNT (16)
+
+struct saved_stab
+{
+  int type;
+  int desc;
+  bfd_vma value;
+  char *string;
+};
+
+static struct saved_stab saved_stabs[SAVE_STABS_COUNT];
+static int saved_stabs_index;
+
+/* Save a stabs string.  */
+
+static void
+save_stab (type, desc, value, string)
+     int type;
+     int desc;
+     bfd_vma value;
+     const char *string;
+{
+  if (saved_stabs[saved_stabs_index].string != NULL)
+    free (saved_stabs[saved_stabs_index].string);
+  saved_stabs[saved_stabs_index].type = type;
+  saved_stabs[saved_stabs_index].desc = desc;
+  saved_stabs[saved_stabs_index].value = value;
+  saved_stabs[saved_stabs_index].string = xstrdup (string);
+  saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT;
+}
+
+/* Provide context for an error.  */
+
+static void
+stab_context ()
+{
+  int i;
+
+  fprintf (stderr, _("Last stabs entries before error:\n"));
+  fprintf (stderr, "n_type n_desc n_value  string\n");
+
+  i = saved_stabs_index;
+  do
+    {
+      struct saved_stab *stabp;
+
+      stabp = saved_stabs + i;
+      if (stabp->string != NULL)
+       {
+         const char *s;
+
+         s = bfd_get_stab_name (stabp->type);
+         if (s != NULL)
+           fprintf (stderr, "%-6s", s);
+         else if (stabp->type == 0)
+           fprintf (stderr, "HdrSym");
+         else
+           fprintf (stderr, "%-6d", stabp->type);
+         fprintf (stderr, " %-6d ", stabp->desc);
+         fprintf_vma (stderr, stabp->value);
+         if (stabp->type != 0)
+           fprintf (stderr, " %s", stabp->string);
+         fprintf (stderr, "\n");
+       }
+      i = (i + 1) % SAVE_STABS_COUNT;
+    }
+  while (i != saved_stabs_index);
+}
+
+/* Free the saved stab strings.  */
+
+static void
+free_saved_stabs ()
+{
+  int i;
+
+  for (i = 0; i < SAVE_STABS_COUNT; i++)
+    {
+      if (saved_stabs[i].string != NULL)
+       {
+         free (saved_stabs[i].string);
+         saved_stabs[i].string = NULL;
+       }
+    }
+
+  saved_stabs_index = 0;
+}
diff --git a/binutils/readelf.c b/binutils/readelf.c
new file mode 100644 (file)
index 0000000..549bf1a
--- /dev/null
@@ -0,0 +1,5682 @@
+/* readelf.c -- display contents of an ELF format file
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+   Originally developed by Eric Youngdale <eric@andante.jic.com>
+   Modifications by Nick Clifton <nickc@cygnus.com>
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+\f
+
+#include <assert.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "bfd.h"
+
+#include "elf/common.h"
+#include "elf/external.h"
+#include "elf/internal.h"
+#include "elf/dwarf2.h"
+
+/* The following headers use the elf/reloc-macros.h file to
+   automatically generate relocation recognition functions
+   such as elf_mips_reloc_type()  */
+
+#define RELOC_MACROS_GEN_FUNC
+
+#include "elf/i386.h"
+#include "elf/v850.h"
+#include "elf/ppc.h"
+#include "elf/mips.h"
+#include "elf/alpha.h"
+#include "elf/arm.h"
+#include "elf/m68k.h"
+#include "elf/sparc.h"
+#include "elf/m32r.h"
+#include "elf/d10v.h"
+#include "elf/d30v.h"
+#include "elf/sh.h"
+#include "elf/mn10200.h"
+#include "elf/mn10300.h"
+#include "elf/hppa.h"
+#include "elf/arc.h"
+#include "elf/fr30.h"
+#include "elf/mcore.h"
+
+#include "bucomm.h"
+#include "getopt.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+char *                 program_name = "readelf";
+unsigned int           dynamic_addr;
+unsigned int           dynamic_size;
+unsigned int           rela_addr;
+unsigned int           rela_size;
+char *                 dynamic_strings;
+char *                 string_table;
+Elf_Internal_Sym *     dynamic_symbols;
+Elf_Internal_Syminfo * dynamic_syminfo;
+unsigned long          dynamic_syminfo_offset;
+unsigned int           dynamic_syminfo_nent;
+char                   program_interpreter [64];
+int                    dynamic_info[DT_JMPREL + 1];
+int                    version_info[16];
+int                    loadaddr = 0;
+Elf_Internal_Ehdr       elf_header;
+Elf_Internal_Shdr *     section_headers;
+Elf_Internal_Dyn *      dynamic_segment;
+int                    show_name;
+int                    do_dynamic;
+int                    do_syms;
+int                    do_reloc;
+int                    do_sections;
+int                    do_segments;
+int                    do_using_dynamic;
+int                    do_header;
+int                    do_dump;
+int                    do_version;
+int                    do_histogram;
+int                    do_debugging;
+int                     do_debug_info;
+int                     do_debug_abbrevs;
+int                     do_debug_lines;
+int                     do_debug_pubnames;
+int                     do_debug_aranges;
+int                    binary_class;
+
+/* A dynamic array of flags indicating which sections require dumping.  */
+char *                 dump_sects = NULL;
+unsigned int           num_dump_sects = 0;
+
+#define HEX_DUMP       (1 << 0)
+#define DISASS_DUMP    (1 << 1)
+#define DEBUG_DUMP     (1 << 2)
+
+/* Forward declarations for dumb compilers.  */
+static unsigned long (*   byte_get)                   PARAMS ((unsigned char *, int));
+static const char *       get_mips_dynamic_type       PARAMS ((unsigned long type));
+static const char *       get_dynamic_type            PARAMS ((unsigned long type));
+static int                dump_relocations            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *));
+static char *             get_file_type               PARAMS ((unsigned e_type));
+static char *             get_machine_name            PARAMS ((unsigned e_machine));
+static char *             get_machine_data            PARAMS ((unsigned e_data));
+static char *             get_machine_flags           PARAMS ((unsigned, unsigned e_machine));
+static const char *       get_mips_segment_type       PARAMS ((unsigned long type));
+static const char *       get_segment_type            PARAMS ((unsigned long p_type));
+static const char *       get_mips_section_type_name  PARAMS ((unsigned int sh_type));
+static const char *       get_section_type_name       PARAMS ((unsigned int sh_type));
+static char *             get_symbol_binding          PARAMS ((unsigned int binding));
+static char *             get_symbol_type             PARAMS ((unsigned int type));
+static void               usage                       PARAMS ((void));
+static void               parse_args                  PARAMS ((int argc, char ** argv));
+static int                process_file_header         PARAMS ((void));
+static int                process_program_headers     PARAMS ((FILE *));
+static int                process_section_headers     PARAMS ((FILE *));
+static void               dynamic_segment_mips_val    PARAMS ((Elf_Internal_Dyn *entry));
+static int                process_dynamic_segment     PARAMS ((FILE *));
+static int                process_symbol_table        PARAMS ((FILE *));
+static int                process_section_contents    PARAMS ((FILE *));
+static void               process_file                PARAMS ((char * file_name));
+static int                process_relocs              PARAMS ((FILE *));
+static int                process_version_sections    PARAMS ((FILE *));
+static char *             get_ver_flags               PARAMS ((unsigned int flags));
+static char *             get_symbol_index_type       PARAMS ((unsigned int type));
+static int                get_section_headers         PARAMS ((FILE * file));
+static int                get_file_header             PARAMS ((FILE * file));
+static Elf_Internal_Sym * get_elf_symbols             PARAMS ((FILE * file, unsigned long offset, unsigned long number));
+static int *              get_dynamic_data            PARAMS ((FILE * file, unsigned int number));
+#ifdef SUPPORT_DISASSEMBLY
+static int               disassemble_section         PARAMS ((Elf32_Internal_Shdr *, FILE *));
+#endif
+static int               dump_section                PARAMS ((Elf32_Internal_Shdr *, FILE *));
+static int               display_debug_section       PARAMS ((Elf32_Internal_Shdr *, FILE *));
+static int                display_debug_info          PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_lines         PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_abbrev        PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_aranges       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static unsigned char *    process_abbrev_section      PARAMS ((unsigned char *, unsigned char *));
+static unsigned long      read_leb128                 PARAMS ((unsigned char *, int *, int));
+static int                process_extended_line_op    PARAMS ((unsigned char *, int));
+static void               reset_state_machine         PARAMS ((int));
+static char *             get_TAG_name                PARAMS ((unsigned long));
+static char *             get_AT_name                 PARAMS ((unsigned long));
+static char *             get_FORM_name               PARAMS ((unsigned long));
+static void               free_abbrevs                PARAMS ((void));
+static void               add_abbrev                  PARAMS ((unsigned long, unsigned long, int));
+static void               add_abbrev_attr             PARAMS ((unsigned long, unsigned long));
+static unsigned char *    read_and_display_attr       PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long));
+static unsigned char *    display_block               PARAMS ((unsigned char *, unsigned long));
+static void               decode_location_expression  PARAMS ((unsigned char *, unsigned int));
+static void              request_dump                PARAMS ((unsigned int, char));
+static const char *       get_elf_class               PARAMS ((unsigned char));
+static const char *       get_data_encoding           PARAMS ((unsigned char));
+static const char *       get_osabi_name              PARAMS ((unsigned char));
+
+typedef int Elf32_Word;
+
+#define SECTION_NAME(X)        (string_table + (X)->sh_name)
+
+#define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+
+#define BYTE_GET(field)        byte_get (field, sizeof (field))
+
+#define NUM_ELEM(array)        (sizeof (array) / sizeof ((array)[0]))
+
+#define GET_DATA_ALLOC(offset, size, var, type, reason)                        \
+  if (fseek (file, offset, SEEK_SET))                                  \
+    {                                                                  \
+      error (_("Unable to seek to start of %s at %x\n"), reason, offset); \
+      return 0;                                                                \
+    }                                                                  \
+                                                                       \
+  var = (type) malloc (size);                                          \
+                                                                       \
+  if (var == NULL)                                                     \
+    {                                                                  \
+      error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \
+      return 0;                                                                \
+    }                                                                  \
+                                                                       \
+  if (fread (var, size, 1, file) != 1)                                         \
+    {                                                                  \
+      error (_("Unable to read in %d bytes of %s\n"), size, reason);   \
+      free (var);                                                      \
+      var = NULL;                                                      \
+      return 0;                                                        \
+    }
+
+
+#define GET_DATA(offset, var, reason)                                  \
+  if (fseek (file, offset, SEEK_SET))                                  \
+    {                                                                  \
+      error (_("Unable to seek to %x for %s\n"), offset, reason);      \
+      return 0;                                                                \
+    }                                                                  \
+  else if (fread (& var, sizeof (var), 1, file) != 1)                  \
+    {                                                                  \
+      error (_("Unable to read data at %x for %s\n"), offset, reason); \
+      return 0;                                                                \
+    }
+
+#ifdef ANSI_PROTOTYPES
+static void
+error (const char * message, ...)
+{
+  va_list args;
+
+  fprintf (stderr, _("%s: Error: "), program_name);
+  va_start (args, message);
+  vfprintf (stderr, message, args);
+  va_end (args);
+  return;
+}
+
+static void
+warn (const char * message, ...)
+{
+  va_list args;
+
+  fprintf (stderr, _("%s: Warning: "), program_name);
+  va_start (args, message);
+  vfprintf (stderr, message, args);
+  va_end (args);
+  return;
+}
+#else
+static void
+error (va_alist)
+     va_dcl
+{
+  char * message;
+  va_list args;
+
+  fprintf (stderr, _("%s: Error: "), program_name);
+  va_start (args);
+  message = va_arg (args, char *);
+  vfprintf (stderr, message, args);
+  va_end (args);
+  return;
+}
+
+static void
+warn (va_alist)
+     va_dcl
+{
+  char * message;
+  va_list args;
+
+  fprintf (stderr, _("%s: Warning: "), program_name);
+  va_start (args);
+  message = va_arg (args, char *);
+  vfprintf (stderr, message, args);
+  va_end (args);
+  return;
+}
+#endif
+
+static unsigned long int
+byte_get_little_endian (field, size)
+     unsigned char * field;
+     int             size;
+{
+  switch (size)
+    {
+    case 1:
+      return * field;
+
+    case 2:
+      return  ((unsigned int) (field [0]))
+       |    (((unsigned int) (field [1])) << 8);
+
+    case 4:
+      return  ((unsigned long) (field [0]))
+       |    (((unsigned long) (field [1])) << 8)
+       |    (((unsigned long) (field [2])) << 16)
+       |    (((unsigned long) (field [3])) << 24);
+
+    default:
+      error (_("Unhandled data length: %d\n"), size);
+      abort();
+    }
+}
+
+static unsigned long int
+byte_get_big_endian (field, size)
+     unsigned char * field;
+     int             size;
+{
+  switch (size)
+    {
+    case 1:
+      return * field;
+
+    case 2:
+      return ((unsigned int) (field [1])) | (((int) (field [0])) << 8);
+
+    case 4:
+      return ((unsigned long) (field [3]))
+       |   (((unsigned long) (field [2])) << 8)
+       |   (((unsigned long) (field [1])) << 16)
+       |   (((unsigned long) (field [0])) << 24);
+
+    default:
+      error (_("Unhandled data length: %d\n"), size);
+      abort();
+    }
+}
+
+
+/* Display the contents of the relocation data
+   found at the specified offset.  */
+static int
+dump_relocations (file, rel_offset, rel_size, symtab, strtab)
+     FILE *                 file;
+     unsigned long          rel_offset;
+     unsigned long          rel_size;
+     Elf_Internal_Sym *     symtab;
+     char *                 strtab;
+{
+  unsigned int        i;
+  int                 is_rela;
+  Elf_Internal_Rel *  rels;
+  Elf_Internal_Rela * relas;
+
+
+  /* Compute number of relocations and read them in.  */
+  switch (elf_header.e_machine)
+    {
+      /* Targets that use REL relocations.  */
+    case EM_ARM:
+    case EM_386:
+    case EM_486:
+    case EM_CYGNUS_M32R:
+    case EM_CYGNUS_D10V:
+    case EM_MIPS:
+    case EM_MIPS_RS4_BE:
+      {
+       Elf32_External_Rel * erels;
+
+       GET_DATA_ALLOC (rel_offset, rel_size, erels,
+                       Elf32_External_Rel *, "relocs");
+
+       rel_size = rel_size / sizeof (Elf32_External_Rel);
+
+       rels = (Elf_Internal_Rel *) malloc (rel_size *
+                                           sizeof (Elf_Internal_Rel));
+
+       for (i = 0; i < rel_size; i++)
+         {
+           rels[i].r_offset = BYTE_GET (erels[i].r_offset);
+           rels[i].r_info   = BYTE_GET (erels[i].r_info);
+         }
+
+       free (erels);
+
+       is_rela = 0;
+       relas   = (Elf_Internal_Rela *) rels;
+      }
+    break;
+
+      /* Targets that use RELA relocations.  */
+    case EM_68K:
+    case EM_SPARC:
+    case EM_PPC:
+    case EM_CYGNUS_V850:
+    case EM_CYGNUS_D30V:
+    case EM_CYGNUS_MN10200:
+    case EM_CYGNUS_MN10300:
+    case EM_CYGNUS_FR30:
+    case EM_SH:
+    case EM_ALPHA:
+    case EM_MCORE:
+      {
+       Elf32_External_Rela * erelas;
+
+       GET_DATA_ALLOC (rel_offset, rel_size, erelas,
+                       Elf32_External_Rela *, "relocs");
+
+       rel_size = rel_size / sizeof (Elf32_External_Rela);
+
+       relas = (Elf_Internal_Rela *) malloc (rel_size *
+                                             sizeof (Elf_Internal_Rela));
+
+       for (i = 0; i < rel_size; i++)
+         {
+           relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
+           relas[i].r_info   = BYTE_GET (erelas[i].r_info);
+           relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
+         }
+
+       free (erelas);
+
+       is_rela = 1;
+       rels    = (Elf_Internal_Rel *) relas;
+      }
+    break;
+
+    default:
+      warn (_("Don't know about relocations on this machine architecture\n"));
+      return 0;
+    }
+
+  if (is_rela)
+    printf
+      (_("  Offset    Info  Type            Symbol's Value  Symbol's Name          Addend\n"));
+  else
+    printf
+      (_("  Offset    Info  Type            Symbol's Value  Symbol's Name\n"));
+
+  for (i = 0; i < rel_size; i++)
+    {
+      const char *  rtype;
+      unsigned long offset;
+      unsigned long info;
+      int           symtab_index;
+
+      if (is_rela)
+       {
+         offset = relas [i].r_offset;
+         info   = relas [i].r_info;
+       }
+      else
+       {
+         offset = rels [i].r_offset;
+         info   = rels [i].r_info;
+       }
+
+      printf ("  %8.8lx  %5.5lx ", offset, info);
+
+      switch (elf_header.e_machine)
+       {
+       default:
+         rtype = NULL;
+         break;
+
+       case EM_CYGNUS_M32R:
+         rtype = elf_m32r_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_386:
+       case EM_486:
+         rtype = elf_i386_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_68K:
+         rtype = elf_m68k_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_SPARC:
+         rtype = elf_sparc_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_CYGNUS_V850:
+         rtype = v850_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_CYGNUS_D10V:
+         rtype = elf_d10v_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_CYGNUS_D30V:
+         rtype = elf_d30v_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_SH:
+         rtype = elf_sh_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_CYGNUS_MN10300:
+         rtype = elf_mn10300_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_CYGNUS_MN10200:
+         rtype = elf_mn10200_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_CYGNUS_FR30:
+         rtype = elf_fr30_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_MCORE:
+         rtype = elf_mcore_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_PPC:
+         rtype = elf_ppc_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_MIPS:
+       case EM_MIPS_RS4_BE:
+         rtype = elf_mips_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_ALPHA:
+         rtype = elf_alpha_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_ARM:
+         rtype = elf_arm_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_CYGNUS_ARC:
+         rtype = elf_arc_reloc_type (ELF32_R_TYPE (info));
+         break;
+
+       case EM_PARISC:
+         rtype = elf32_hppa_reloc_type (ELF32_R_TYPE (info));
+         break;
+       }
+
+      if (rtype == NULL)
+       printf (_("unrecognised: %-7lx"), ELF32_R_TYPE (info));
+      else
+       printf ("%-21.21s", rtype);
+
+      symtab_index = ELF32_R_SYM (info);
+
+      if (symtab_index && symtab != NULL)
+       {
+         Elf_Internal_Sym * psym;
+
+         psym = symtab + symtab_index;
+
+         printf (" %08lx  ", (unsigned long) psym->st_value);
+
+         if (psym->st_name == 0)
+           printf ("%-25.25s",
+                   SECTION_NAME (section_headers + psym->st_shndx));
+         else if (strtab == NULL)
+           printf (_("<string table index %3ld>"), psym->st_name);
+         else
+           printf ("%-25.25s", strtab + psym->st_name);
+
+         if (is_rela)
+           printf (" + %lx", (unsigned long) relas [i].r_addend);
+       }
+
+      putchar ('\n');
+    }
+
+  free (relas);
+
+  return 1;
+}
+
+static const char *
+get_mips_dynamic_type (type)
+     unsigned long type;
+{
+  switch (type)
+    {
+    case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION";
+    case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP";
+    case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM";
+    case DT_MIPS_IVERSION: return "MIPS_IVERSION";
+    case DT_MIPS_FLAGS: return "MIPS_FLAGS";
+    case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS";
+    case DT_MIPS_MSYM: return "MIPS_MSYM";
+    case DT_MIPS_CONFLICT: return "MIPS_CONFLICT";
+    case DT_MIPS_LIBLIST: return "MIPS_LIBLIST";
+    case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO";
+    case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO";
+    case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO";
+    case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO";
+    case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO";
+    case DT_MIPS_GOTSYM: return "MIPS_GOTSYM";
+    case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO";
+    case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP";
+    case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS";
+    case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO";
+    case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE";
+    case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO";
+    case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC";
+    case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO";
+    case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM";
+    case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO";
+    case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM";
+    case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO";
+    case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS";
+    case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT";
+    case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
+    case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX";
+    case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX";
+    case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX";
+    case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX";
+    case DT_MIPS_OPTIONS: return "MIPS_OPTIONS";
+    case DT_MIPS_INTERFACE: return "MIPS_INTERFACE";
+    case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN";
+    case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE";
+    case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR";
+    case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX";
+    case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
+    case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
+    case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
+    default:
+      return NULL;
+    }
+}
+
+static const char *
+get_dynamic_type (type)
+     unsigned long type;
+{
+  static char buff [32];
+
+  switch (type)
+    {
+    case DT_NULL:      return "NULL";
+    case DT_NEEDED:    return "NEEDED";
+    case DT_PLTRELSZ:  return "PLTRELSZ";
+    case DT_PLTGOT:    return "PLTGOT";
+    case DT_HASH:      return "HASH";
+    case DT_STRTAB:    return "STRTAB";
+    case DT_SYMTAB:    return "SYMTAB";
+    case DT_RELA:      return "RELA";
+    case DT_RELASZ:    return "RELASZ";
+    case DT_RELAENT:   return "RELAENT";
+    case DT_STRSZ:     return "STRSZ";
+    case DT_SYMENT:    return "SYMENT";
+    case DT_INIT:      return "INIT";
+    case DT_FINI:      return "FINI";
+    case DT_SONAME:    return "SONAME";
+    case DT_RPATH:     return "RPATH";
+    case DT_SYMBOLIC:  return "SYMBOLIC";
+    case DT_REL:       return "REL";
+    case DT_RELSZ:     return "RELSZ";
+    case DT_RELENT:    return "RELENT";
+    case DT_PLTREL:    return "PLTREL";
+    case DT_DEBUG:     return "DEBUG";
+    case DT_TEXTREL:   return "TEXTREL";
+    case DT_JMPREL:    return "JMPREL";
+    case DT_BIND_NOW:   return "BIND_NOW";
+    case DT_INIT_ARRAY: return "INIT_ARRAY";
+    case DT_FINI_ARRAY: return "FINI_ARRAY";
+    case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ";
+    case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ";
+      
+    case DT_PLTPADSZ:  return "PLTPADSZ";
+    case DT_MOVEENT:   return "MOVEENT";
+    case DT_MOVESZ:    return "MOVESZ";
+    case DT_FEATURE_1: return "FEATURE_1";
+    case DT_POSFLAG_1: return "POSFLAG_1";
+    case DT_SYMINSZ:   return "SYMINSZ";
+    case DT_SYMINENT:  return "SYMINENT"; /* aka VALRNGHI */
+      
+    case DT_ADDRRNGLO:  return "ADDRRNGLO";
+    case DT_SYMINFO:   return "SYMINFO"; /* aka ADDRRNGHI */
+      
+    case DT_VERSYM:    return "VERSYM";
+      
+    case DT_RELACOUNT: return "RELACOUNT";
+    case DT_RELCOUNT:  return "RELCOUNT";
+    case DT_FLAGS_1:   return "FLAGS_1";
+    case DT_VERDEF:    return "VERDEF";
+    case DT_VERDEFNUM: return "VERDEFNUM";
+    case DT_VERNEED:   return "VERNEED";
+    case DT_VERNEEDNUM:        return "VERNEEDNUM";
+      
+    case DT_AUXILIARY: return "AUXILARY";
+    case DT_USED:      return "USED";
+    case DT_FILTER:    return "FILTER";
+      
+    default:
+      if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
+       {
+         const char * result;
+         
+         switch (elf_header.e_machine)
+           {
+           case EM_MIPS:
+           case EM_MIPS_RS4_BE:
+             result = get_mips_dynamic_type (type);
+             break;
+           default:
+             result = NULL;
+             break;
+           }
+
+         if (result != NULL)
+           return result;
+
+         sprintf (buff, _("Processor Specific: %lx"), type);
+       }
+      else if ((type >= DT_LOOS) && (type <= DT_HIOS))
+       sprintf (buff, _("Operating System specific: %lx"), type);
+      else
+       sprintf (buff, _("<unknown>: %lx"), type);
+      
+      return buff;
+    }
+}
+
+static char *
+get_file_type (e_type)
+     unsigned e_type;
+{
+  static char buff [32];
+
+  switch (e_type)
+    {
+    case ET_NONE:      return _("NONE (None)");
+    case ET_REL:       return _("REL (Relocatable file)");
+    case ET_EXEC:       return _("EXEC (Executable file)");
+    case ET_DYN:        return _("DYN (Shared object file)");
+    case ET_CORE:       return _("CORE (Core file)");
+
+    default:
+      if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
+       sprintf (buff, _("Processor Specific: (%x)"), e_type);
+      else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS))
+       sprintf (buff, _("OS Specific: (%x)"), e_type);
+      else
+       sprintf (buff, _("<unknown>: %x"), e_type);
+      return buff;
+    }
+}
+
+static char *
+get_machine_name (e_machine)
+     unsigned e_machine;
+{
+  static char buff [32];
+
+  switch (e_machine)
+    {
+    case EM_NONE:              return _("None");
+    case EM_M32:               return "WE32100";
+    case EM_SPARC:             return "Sparc";
+    case EM_386:               return "Intel 80386";
+    case EM_68K:               return "MC68000";
+    case EM_88K:               return "MC88000";
+    case EM_486:               return "Intel 80486";
+    case EM_860:               return "Intel 80860";
+    case EM_MIPS:              return "MIPS R3000 big-endian";
+    case EM_S370:              return "Amdahl";
+    case EM_MIPS_RS4_BE:       return "MIPS R4000 big-endian";
+    case EM_OLD_SPARCV9:       return "Sparc v9 (old)";
+    case EM_PARISC:            return "HPPA";
+    case EM_PPC_OLD:           return "Power PC (old)";
+    case EM_SPARC32PLUS:       return "Sparc v8+" ;
+    case EM_960:               return "Intel 90860";
+    case EM_PPC:               return "PowerPC";
+    case EM_V800:              return "NEC V800";
+    case EM_FR20:              return "Fujitsu FR20";
+    case EM_RH32:              return "TRW RH32";
+    case EM_MCORE:             return "MCORE";
+    case EM_ARM:               return "ARM";
+    case EM_OLD_ALPHA:         return "Digital Alpha (old)";
+    case EM_SH:                        return "Hitachi SH";
+    case EM_SPARCV9:           return "Sparc v9";
+    case EM_TRICORE:           return "Siemens Tricore";
+    case EM_ARC:               return "Argonaut RISC Core";
+    case EM_H8_300:            return "Hitachi H8/300";
+    case EM_H8_300H:           return "Hitachi H8/300H";
+    case EM_H8S:               return "Hitachi H8S";
+    case EM_H8_500:            return "Hitachi H8/500";
+    case EM_IA_64:             return "Intel Merced";
+    case EM_MIPS_X:            return "Stanford MIPS-X";
+    case EM_COLDFIRE:          return "Motorola Coldfire";
+    case EM_68HC12:            return "Motorola M68HC12";
+    case EM_ALPHA:             return "Alpha";
+    case EM_CYGNUS_D10V:        return "d10v";
+    case EM_CYGNUS_D30V:        return "d30v";
+    case EM_CYGNUS_ARC:                return "Arc";
+    case EM_CYGNUS_M32R:       return "Mitsubishi M32r";
+    case EM_CYGNUS_V850:       return "NEC v850";
+    case EM_CYGNUS_MN10300:    return "mn10300";
+    case EM_CYGNUS_MN10200:    return "mn10200";
+    case EM_CYGNUS_FR30:       return "Fujitsu FR30";
+
+    default:
+      sprintf (buff, _("<unknown>: %x"), e_machine);
+      return buff;
+    }
+}
+
+static char *
+get_machine_flags (e_flags, e_machine)
+     unsigned e_flags;
+     unsigned e_machine;
+{
+  static char buf [1024];
+
+  buf[0] = '\0';
+  if (e_flags)
+    {
+      switch (e_machine)
+       {
+       default:
+         break;
+
+       case EM_PPC:
+         if (e_flags & EF_PPC_EMB)
+           strcat (buf, ", emb");
+
+         if (e_flags & EF_PPC_RELOCATABLE)
+           strcat (buf, ", relocatable");
+
+         if (e_flags & EF_PPC_RELOCATABLE_LIB)
+           strcat (buf, ", relocatable-lib");
+         break;
+
+       case EM_CYGNUS_V850:
+         switch (e_flags & EF_V850_ARCH)
+           {
+           case E_V850E_ARCH:
+             strcat (buf, ", v850e");
+             break;
+           case E_V850EA_ARCH:
+             strcat (buf, ", v850ea");
+             break;
+           case E_V850_ARCH:
+             strcat (buf, ", v850");
+             break;
+           default:
+             strcat (buf, ", unknown v850 architecture variant");
+             break;
+           }
+         break;
+
+       case EM_CYGNUS_M32R:
+         if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
+           strcat (buf, ", m32r");
+
+         break;
+
+       case EM_MIPS:
+       case EM_MIPS_RS4_BE:
+         if (e_flags & EF_MIPS_NOREORDER)
+           strcat (buf, ", noreorder");
+
+         if (e_flags & EF_MIPS_PIC)
+           strcat (buf, ", pic");
+
+         if (e_flags & EF_MIPS_CPIC)
+           strcat (buf, ", cpic");
+
+         if (e_flags & EF_MIPS_ABI2)
+           strcat (buf, ", abi2");
+
+         if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
+           strcat (buf, ", mips1");
+
+         if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
+           strcat (buf, ", mips2");
+
+         if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
+           strcat (buf, ", mips3");
+
+         if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
+           strcat (buf, ", mips4");
+         break;
+       }
+    }
+
+  return buf;
+}
+
+static char *
+get_machine_data (e_data)
+     unsigned e_data;
+{
+  static char buff [32];
+
+  switch (e_data)
+    {
+    case ELFDATA2LSB: return _("ELFDATA2LSB (little endian)");
+    case ELFDATA2MSB: return _("ELFDATA2MSB (big endian)");
+    default:
+      sprintf (buff, _("<unknown>: %x"), e_data);
+      return buff;
+    }
+}
+
+static const char *
+get_mips_segment_type (type)
+     unsigned long type;
+{
+  switch (type)
+    {
+    case PT_MIPS_REGINFO:
+      return "REGINFO";
+    case PT_MIPS_RTPROC:
+      return "RTPROC";
+    case PT_MIPS_OPTIONS:
+      return "OPTIONS";
+    default:
+      break;
+    }
+
+  return NULL;
+}
+
+static const char *
+get_segment_type (p_type)
+     unsigned long p_type;
+{
+  static char buff [32];
+
+  switch (p_type)
+    {
+    case PT_NULL:       return "NULL";
+    case PT_LOAD:       return "LOAD";
+    case PT_DYNAMIC:   return "DYNAMIC";
+    case PT_INTERP:     return "INTERP";
+    case PT_NOTE:       return "NOTE";
+    case PT_SHLIB:      return "SHLIB";
+    case PT_PHDR:       return "PHDR";
+
+    default:
+      if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
+       {
+         const char * result;
+         
+         switch (elf_header.e_machine)
+           {
+           case EM_MIPS:
+           case EM_MIPS_RS4_BE:
+             result = get_mips_segment_type (p_type);
+             break;
+           default:
+             result = NULL;
+             break;
+           }
+         
+         if (result != NULL)
+           return result;
+         
+         sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC);
+       }
+      else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS))
+       sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
+      else
+       sprintf (buff, _("<unknown>: %lx"), p_type);
+
+      return buff;
+    }
+}
+
+static const char *
+get_mips_section_type_name (sh_type)
+     unsigned int sh_type;
+{
+  switch (sh_type)
+    {
+    case SHT_MIPS_LIBLIST:       return "MIPS_LIBLIST";
+    case SHT_MIPS_MSYM:          return "MIPS_MSYM";
+    case SHT_MIPS_CONFLICT:      return "MIPS_CONFLICT";
+    case SHT_MIPS_GPTAB:         return "MIPS_GPTAB";
+    case SHT_MIPS_UCODE:         return "MIPS_UCODE";
+    case SHT_MIPS_DEBUG:         return "MIPS_DEBUG";
+    case SHT_MIPS_REGINFO:       return "MIPS_REGINFO";
+    case SHT_MIPS_PACKAGE:       return "MIPS_PACKAGE";
+    case SHT_MIPS_PACKSYM:       return "MIPS_PACKSYM";
+    case SHT_MIPS_RELD:          return "MIPS_RELD";
+    case SHT_MIPS_IFACE:         return "MIPS_IFACE";
+    case SHT_MIPS_CONTENT:       return "MIPS_CONTENT";
+    case SHT_MIPS_OPTIONS:       return "MIPS_OPTIONS";
+    case SHT_MIPS_SHDR:          return "MIPS_SHDR";
+    case SHT_MIPS_FDESC:         return "MIPS_FDESC";
+    case SHT_MIPS_EXTSYM:        return "MIPS_EXTSYM";
+    case SHT_MIPS_DENSE:         return "MIPS_DENSE";
+    case SHT_MIPS_PDESC:         return "MIPS_PDESC";
+    case SHT_MIPS_LOCSYM:        return "MIPS_LOCSYM";
+    case SHT_MIPS_AUXSYM:        return "MIPS_AUXSYM";
+    case SHT_MIPS_OPTSYM:        return "MIPS_OPTSYM";
+    case SHT_MIPS_LOCSTR:        return "MIPS_LOCSTR";
+    case SHT_MIPS_LINE:          return "MIPS_LINE";
+    case SHT_MIPS_RFDESC:        return "MIPS_RFDESC";
+    case SHT_MIPS_DELTASYM:      return "MIPS_DELTASYM";
+    case SHT_MIPS_DELTAINST:     return "MIPS_DELTAINST";
+    case SHT_MIPS_DELTACLASS:    return "MIPS_DELTACLASS";
+    case SHT_MIPS_DWARF:         return "MIPS_DWARF";
+    case SHT_MIPS_DELTADECL:     return "MIPS_DELTADECL";
+    case SHT_MIPS_SYMBOL_LIB:    return "MIPS_SYMBOL_LIB";
+    case SHT_MIPS_EVENTS:        return "MIPS_EVENTS";
+    case SHT_MIPS_TRANSLATE:     return "MIPS_TRANSLATE";
+    case SHT_MIPS_PIXIE:         return "MIPS_PIXIE";
+    case SHT_MIPS_XLATE:         return "MIPS_XLATE";
+    case SHT_MIPS_XLATE_DEBUG:   return "MIPS_XLATE_DEBUG";
+    case SHT_MIPS_WHIRL:         return "MIPS_WHIRL";
+    case SHT_MIPS_EH_REGION:     return "MIPS_EH_REGION";
+    case SHT_MIPS_XLATE_OLD:     return "MIPS_XLATE_OLD";
+    case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+static const char *
+get_section_type_name (sh_type)
+     unsigned int sh_type;
+{
+  static char buff [32];
+
+  switch (sh_type)
+    {
+    case SHT_NULL:             return "NULL";
+    case SHT_PROGBITS:         return "PROGBITS";
+    case SHT_SYMTAB:           return "SYMTAB";
+    case SHT_STRTAB:           return "STRTAB";
+    case SHT_RELA:             return "RELA";
+    case SHT_HASH:             return "HASH";
+    case SHT_DYNAMIC:          return "DYNAMIC";
+    case SHT_NOTE:             return "NOTE";
+    case SHT_NOBITS:           return "NOBITS";
+    case SHT_REL:              return "REL";
+    case SHT_SHLIB:            return "SHLIB";
+    case SHT_DYNSYM:           return "DYNSYM";
+    case SHT_GNU_verdef:       return "VERDEF";
+    case SHT_GNU_verneed:      return "VERNEED";
+    case SHT_GNU_versym:       return "VERSYM";
+    case 0x6ffffff0:           return "VERSYM";
+    case 0x6ffffffc:           return "VERDEF";
+    case 0x7ffffffd:           return "AUXILIARY";
+    case 0x7fffffff:           return "FILTER";
+
+    default:
+      if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
+       {
+         const char * result;
+
+         switch (elf_header.e_machine)
+           {
+           case EM_MIPS:
+           case EM_MIPS_RS4_BE:
+             result = get_mips_section_type_name (sh_type);
+             break;
+           default:
+             result = NULL;
+             break;
+           }
+
+         if (result != NULL)
+           return result;
+
+         sprintf (buff, "SHT_LOPROC+%x", sh_type - SHT_LOPROC);
+       }
+      else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS))
+       sprintf (buff, "SHT_LOOS+%x", sh_type - SHT_LOOS);
+      else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
+       sprintf (buff, "SHT_LOUSER+%x", sh_type - SHT_LOUSER);
+      else
+       sprintf (buff, _("<unknown>: %x"), sh_type);
+      
+      return buff;
+    }
+}
+
+struct option options [] =
+{
+  {"all",              no_argument, 0, 'a'},
+  {"file-header",      no_argument, 0, 'h'},
+  {"program-headers",  no_argument, 0, 'l'},
+  {"headers",          no_argument, 0, 'e'},
+  {"histogram",        no_argument, & do_histogram, 1},
+  {"segments",         no_argument, 0, 'l'},
+  {"sections",         no_argument, 0, 'S'},
+  {"section-headers",  no_argument, 0, 'S'},
+  {"symbols",          no_argument, 0, 's'},
+  {"syms",             no_argument, 0, 's'},
+  {"relocs",           no_argument, 0, 'r'},
+  {"dynamic",          no_argument, 0, 'd'},
+  {"version-info",     no_argument, 0, 'V'},
+  {"use-dynamic",      no_argument, 0, 'D'},
+  {"hex-dump",         required_argument, 0, 'x'},
+  {"debug-dump",       optional_argument, 0, 'w'},
+#ifdef SUPPORT_DISASSEMBLY
+  {"instruction-dump", required_argument, 0, 'i'},
+#endif
+
+  {"version",          no_argument, 0, 'v'},
+  {"help",             no_argument, 0, 'H'},
+  {0,                  no_argument, 0, 0}
+};
+
+static void
+usage ()
+{
+  fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
+  fprintf (stdout, _("  Options are:\n"));
+  fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V --histogram\n"));
+  fprintf (stdout, _("  -h or --file-header       Display the ELF file header\n"));
+  fprintf (stdout, _("  -l or --program-headers or --segments\n"));
+  fprintf (stdout, _("                            Display the program headers\n"));
+  fprintf (stdout, _("  -S or --section-headers or --sections\n"));
+  fprintf (stdout, _("                            Display the sections' header\n"));
+  fprintf (stdout, _("  -e or --headers           Equivalent to: -h -l -S\n"));
+  fprintf (stdout, _("  -s or --syms or --symbols Display the symbol table\n"));
+  fprintf (stdout, _("  -r or --relocs            Display the relocations (if present)\n"));
+  fprintf (stdout, _("  -d or --dynamic           Display the dynamic segment (if present)\n"));
+  fprintf (stdout, _("  -V or --version-info      Display the version sections (if present)\n"));
+  fprintf (stdout, _("  -D or --use-dynamic       Use the dynamic section info when displaying symbols\n"));
+  fprintf (stdout, _("  -x <number> or --hex-dump=<number>\n"));
+  fprintf (stdout, _("                            Dump the contents of section <number>\n"));
+  fprintf (stdout, _("  -w[liapr] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges]\n"));
+  fprintf (stdout, _("                            Display the contents of DWARF2 debug sections\n"));
+#ifdef SUPPORT_DISASSEMBLY
+  fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
+  fprintf (stdout, _("                            Disassemble the contents of section <number>\n"));
+#endif
+  fprintf (stdout, _("        --histogram         Display histogram of bucket list lengths\n"));
+  fprintf (stdout, _("  -v or --version           Display the version number of readelf\n"));
+  fprintf (stdout, _("  -H or --help              Display this information\n"));
+  fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+
+  exit (0);
+}
+
+static void
+request_dump (section, type)
+     unsigned int section;
+     char         type;
+{
+  if (section >= num_dump_sects)
+    {
+      char * new_dump_sects;
+
+      new_dump_sects = (char *) calloc (section + 1, 1);
+
+      if (new_dump_sects == NULL)
+       error (_("Out of memory allocating dump request table."));
+      else
+       {
+         /* Copy current flag settings.  */
+         memcpy (new_dump_sects, dump_sects, num_dump_sects);
+
+         free (dump_sects);
+
+         dump_sects = new_dump_sects;
+         num_dump_sects = section + 1;
+       }
+    }
+
+  if (dump_sects)
+    dump_sects [section] |= type;
+
+  return;
+}
+
+static void
+parse_args (argc, argv)
+     int argc;
+     char ** argv;
+{
+  int c;
+
+  if (argc < 2)
+    usage ();
+
+  while ((c = getopt_long
+         (argc, argv, "ersahldSDw::x:i:vV", options, NULL)) != EOF)
+    {
+      char *    cp;
+      int      section;
+
+      switch (c)
+       {
+       case 0:
+         /* Long options.  */
+         break;
+       case 'H':
+         usage ();
+         break;
+
+       case 'a':
+         do_syms ++;
+         do_reloc ++;
+         do_dynamic ++;
+         do_header ++;
+         do_sections ++;
+         do_segments ++;
+         do_version ++;
+         do_histogram ++;
+         break;
+       case 'e':
+         do_header ++;
+         do_sections ++;
+         do_segments ++;
+         break;
+       case 'D':
+         do_using_dynamic ++;
+         break;
+       case 'r':
+         do_reloc ++;
+         break;
+       case 'h':
+         do_header ++;
+         break;
+       case 'l':
+         do_segments ++;
+         break;
+       case 's':
+         do_syms ++;
+         break;
+       case 'S':
+         do_sections ++;
+         break;
+       case 'd':
+         do_dynamic ++;
+         break;
+       case 'x':
+         do_dump ++;
+         section = strtoul (optarg, & cp, 0);
+         if (! * cp && section >= 0)
+           {
+             request_dump (section, HEX_DUMP);
+             break;
+           }
+         goto oops;
+       case 'w':
+         do_dump ++;
+         if (optarg == 0)
+           do_debugging = 1;
+         else
+           {
+             do_debugging = 0;
+             switch (optarg[0])
+               {
+               case 'i':
+               case 'I':
+                 do_debug_info = 1;
+                 break;
+
+               case 'a':
+               case 'A':
+                 do_debug_abbrevs = 1;
+                 break;
+
+               case 'l':
+               case 'L':
+                 do_debug_lines = 1;
+                 break;
+
+               case 'p':
+               case 'P':
+                 do_debug_pubnames = 1;
+                 break;
+
+               case 'r':
+               case 'R':
+                 do_debug_aranges = 1;
+                 break;
+
+               default:
+                 warn (_("Unrecognised debug option '%s'\n"), optarg);
+                 break;
+               }
+           }
+         break;
+#ifdef SUPPORT_DISASSEMBLY
+       case 'i':
+         do_dump ++;
+         section = strtoul (optarg, & cp, 0);
+         if (! * cp && section >= 0)
+           {
+             request_dump (section, DISASS_DUMP);
+             break;
+           }
+         goto oops;
+#endif
+       case 'v':
+         print_version (program_name);
+         break;
+       case 'V':
+         do_version ++;
+         break;
+       default:
+       oops:
+         /* xgettext:c-format */
+         error (_("Invalid option '-%c'\n"), c);
+         /* Drop through.  */
+       case '?':
+         usage ();
+       }
+    }
+
+  if (!do_dynamic && !do_syms && !do_reloc && !do_sections
+      && !do_segments && !do_header && !do_dump && !do_version
+      && !do_histogram && !do_debugging)
+    usage ();
+  else if (argc < 3)
+    {
+      warn (_("Nothing to do.\n"));
+      usage();
+    }
+}
+
+static const char *
+get_elf_class (elf_class)
+     unsigned char elf_class;
+{
+  switch (elf_class)
+    {
+    case ELFCLASSNONE: return _("none");
+    case ELFCLASS32:   return _("ELF32");
+    case ELFCLASS64:   return _("ELF64");
+    default:           return _("<unknown>");
+    }
+}
+
+static const char *
+get_data_encoding (encoding)
+     unsigned char encoding;
+{
+  switch (encoding)
+    {
+    case ELFDATANONE: return _("none");
+    case ELFDATA2LSB: return _("2's compilment, little endian");
+    case ELFDATA2MSB: return _("2's compilment, big endian");
+    default:          return _("<unknown>");
+    }
+}
+
+static const char *
+get_osabi_name (osabi)
+     unsigned char osabi;
+{
+  switch (osabi)
+    {
+    case ELFOSABI_SYSV:       return _("UNIX - System V");
+    case ELFOSABI_HPUX:       return _("UNIX - HP-UX");
+    case ELFOSABI_STANDALONE: return _("Standalone App");
+    default:                  return _("<unknown>");
+    }
+}
+
+/* Decode the data held in 'elf_header'.  */
+static int
+process_file_header ()
+{
+  if (   elf_header.e_ident [EI_MAG0] != ELFMAG0
+      || elf_header.e_ident [EI_MAG1] != ELFMAG1
+      || elf_header.e_ident [EI_MAG2] != ELFMAG2
+      || elf_header.e_ident [EI_MAG3] != ELFMAG3)
+    {
+      error
+       (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
+      return 0;
+    }
+
+  if (do_header)
+    {
+      int i;
+
+      printf (_("ELF Header:\n"));
+      printf (_("  Magic:   "));
+      for (i = 0; i < EI_NIDENT; i ++)
+       printf ("%2.2x ", elf_header.e_ident [i]);
+      printf ("\n");
+      printf (_("  Class:                             %s\n"),
+             get_elf_class (elf_header.e_ident [EI_CLASS]));
+      printf (_("  Data:                              %s\n"),
+             get_data_encoding (elf_header.e_ident [EI_DATA]));
+      printf (_("  Version:                           %d %s\n"),
+             elf_header.e_ident [EI_VERSION],
+             elf_header.e_ident [EI_VERSION] == EV_CURRENT ? "(current)" :
+             elf_header.e_ident [EI_VERSION] != EV_NONE ? "<unknown>" : "");
+      printf (_("  OS/ABI:                            %s\n"),
+             get_osabi_name (elf_header.e_ident [EI_OSABI]));
+      printf (_("  ABI Version:                       %d\n"),
+             elf_header.e_ident [EI_ABIVERSION]);
+      printf (_("  Type:                              %s\n"),
+             get_file_type (elf_header.e_type));
+      printf (_("  Machine:                           %s\n"),
+             get_machine_name (elf_header.e_machine));
+      printf (_("  Version:                           0x%lx\n"),
+             (unsigned long) elf_header.e_version);
+      printf (_("  Data:                              %s\n"),
+             get_machine_data (elf_header.e_ident [EI_DATA]));
+      printf (_("  Entry point address:               0x%lx\n"),
+             (unsigned long) elf_header.e_entry);
+      printf (_("  Start of program headers:          %ld (bytes into file)\n"),
+             (long) elf_header.e_phoff);
+      printf (_("  Start of section headers:          %ld (bytes into file)\n"),
+             (long) elf_header.e_shoff);
+      printf (_("  Flags:                             0x%lx%s\n"),
+             (unsigned long) elf_header.e_flags,
+             get_machine_flags (elf_header.e_flags, elf_header.e_machine));
+      printf (_("  Size of this header:               %ld (bytes)\n"),
+             (long) elf_header.e_ehsize);
+      printf (_("  Size of program headers:           %ld (bytes)\n"),
+             (long) elf_header.e_phentsize);
+      printf (_("  Number of program headers:         %ld\n"),
+             (long) elf_header.e_phnum);
+      printf (_("  Size of section headers:           %ld (bytes)\n"),
+             (long) elf_header.e_shentsize);
+      printf (_("  Number of section headers:         %ld\n"),
+             (long) elf_header.e_shnum);
+      printf (_("  Section header string table index: %ld\n"),
+             (long) elf_header.e_shstrndx);
+    }
+
+  /* Test class after dumping header so that at least the header can be
+     display on 64 bit binaries.  */
+  
+  binary_class = elf_header.e_ident [EI_CLASS];
+  if (binary_class != ELFCLASS32)
+    {
+      error (_("Not a 32 bit ELF file\n"));
+      return 0;
+    }
+
+  return 1;
+}
+
+
+static int
+process_program_headers (file)
+     FILE * file;
+{
+  Elf32_External_Phdr * phdrs;
+  Elf32_Internal_Phdr * program_headers;
+  Elf32_Internal_Phdr * segment;
+  unsigned int         i;
+
+  if (elf_header.e_phnum == 0)
+    {
+      if (do_segments)
+       printf (_("\nThere are no program headers in this file.\n"));
+      return 1;
+    }
+
+  if (do_segments && !do_header)
+    {
+      printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type));
+      printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry);
+      printf (_("There are %d program headers, starting at offset %lx:\n"),
+             elf_header.e_phnum, (unsigned long) elf_header.e_phoff);
+    }
+
+  GET_DATA_ALLOC (elf_header.e_phoff,
+                 elf_header.e_phentsize * elf_header.e_phnum,
+                 phdrs, Elf32_External_Phdr *, "program headers");
+
+  program_headers = (Elf32_Internal_Phdr *) malloc
+    (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr));
+
+  if (program_headers == NULL)
+    {
+      error (_("Out of memory\n"));
+      return 0;
+    }
+
+  for (i = 0, segment = program_headers;
+       i < elf_header.e_phnum;
+       i ++, segment ++)
+    {
+      segment->p_type   = BYTE_GET (phdrs[i].p_type);
+      segment->p_offset = BYTE_GET (phdrs[i].p_offset);
+      segment->p_vaddr  = BYTE_GET (phdrs[i].p_vaddr);
+      segment->p_paddr  = BYTE_GET (phdrs[i].p_paddr);
+      segment->p_filesz = BYTE_GET (phdrs[i].p_filesz);
+      segment->p_memsz  = BYTE_GET (phdrs[i].p_memsz);
+      segment->p_flags  = BYTE_GET (phdrs[i].p_flags);
+      segment->p_align  = BYTE_GET (phdrs[i].p_align);
+    }
+
+  free (phdrs);
+
+  if (do_segments)
+    {
+      printf
+       (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
+      printf
+       (_("  Type        Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"));
+    }
+
+  loadaddr = -1;
+  dynamic_addr = 0;
+
+  for (i = 0, segment = program_headers;
+       i < elf_header.e_phnum;
+       i ++, segment ++)
+    {
+      if (do_segments)
+       {
+         printf ("  %-11.11s ", get_segment_type (segment->p_type));
+         printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
+         printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
+         printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
+         printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
+         printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
+         printf ("%c%c%c ",
+                 (segment->p_flags & PF_R ? 'R' : ' '),
+                 (segment->p_flags & PF_W ? 'W' : ' '),
+                 (segment->p_flags & PF_X ? 'E' : ' '));
+         printf ("%#lx", (unsigned long) segment->p_align);
+       }
+
+      switch (segment->p_type)
+       {
+       case PT_LOAD:
+         if (loadaddr == -1)
+           loadaddr = (segment->p_vaddr & 0xfffff000)
+             - (segment->p_offset & 0xfffff000);
+         break;
+
+       case PT_DYNAMIC:
+         if (dynamic_addr)
+           error (_("more than one dynamic segment\n"));
+
+         dynamic_addr = segment->p_offset;
+         dynamic_size = segment->p_filesz;
+         break;
+
+       case PT_INTERP:
+         if (fseek (file, segment->p_offset, SEEK_SET))
+           error (_("Unable to find program interpreter name\n"));
+         else
+           {
+             program_interpreter[0] = 0;
+             fscanf (file, "%63s", program_interpreter);
+
+             if (do_segments)
+               printf (_("\n      [Requesting program interpreter: %s]"),
+                   program_interpreter);
+           }
+         break;
+       }
+
+      if (do_segments)
+       putc ('\n', stdout);
+    }
+
+  if (loadaddr == -1)
+    {
+      /* Very strange. */
+      loadaddr = 0;
+    }
+
+  if (do_segments && section_headers != NULL)
+    {
+      printf (_("\n Section to Segment mapping:\n"));
+      printf (_("  Segment Sections...\n"));
+
+      assert (string_table != NULL);
+
+      for (i = 0; i < elf_header.e_phnum; i++)
+       {
+         int        j;
+         Elf32_Internal_Shdr * section;
+
+         segment = program_headers + i;
+         section = section_headers;
+
+         printf ("   %2.2d     ", i);
+
+         for (j = 0; j < elf_header.e_shnum; j++, section ++)
+           {
+             if (section->sh_size > 0
+                 /* Compare allocated sections by VMA, unallocated
+                    sections by file offset.  */
+                 && (section->sh_flags & SHF_ALLOC
+                     ? (section->sh_addr >= segment->p_vaddr
+                        && section->sh_addr + section->sh_size
+                        <= segment->p_vaddr + segment->p_memsz)
+                     : (section->sh_offset >= segment->p_offset
+                        && (section->sh_offset + section->sh_size
+                            <= segment->p_offset + segment->p_filesz))))
+               printf ("%s ", SECTION_NAME (section));
+           }
+
+         putc ('\n',stdout);
+       }
+    }
+
+  free (program_headers);
+
+  return 1;
+}
+
+
+static int
+get_section_headers (file)
+     FILE * file;
+{
+  Elf32_External_Shdr * shdrs;
+  Elf32_Internal_Shdr * internal;
+  unsigned int          i;
+
+  GET_DATA_ALLOC (elf_header.e_shoff,
+                 elf_header.e_shentsize * elf_header.e_shnum,
+                 shdrs, Elf32_External_Shdr *, "section headers");
+
+  section_headers = (Elf32_Internal_Shdr *) malloc
+    (elf_header.e_shnum * sizeof (Elf32_Internal_Shdr));
+
+  if (section_headers == NULL)
+    {
+      error (_("Out of memory\n"));
+      return 0;
+    }
+
+  for (i = 0, internal = section_headers;
+       i < elf_header.e_shnum;
+       i ++, internal ++)
+    {
+      internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
+      internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
+      internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
+      internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
+      internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
+      internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
+      internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
+      internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
+      internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
+      internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
+    }
+
+  free (shdrs);
+
+  return 1;
+}
+
+static Elf_Internal_Sym *
+get_elf_symbols (file, offset, number)
+     FILE * file;
+     unsigned long offset;
+     unsigned long number;
+{
+  Elf32_External_Sym * esyms;
+  Elf_Internal_Sym *   isyms;
+  Elf_Internal_Sym *   psym;
+  unsigned int         j;
+
+  GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
+                 esyms, Elf32_External_Sym *, "symbols");
+
+  isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
+
+  if (isyms == NULL)
+    {
+      error (_("Out of memory\n"));
+      free (esyms);
+
+      return NULL;
+    }
+
+  for (j = 0, psym = isyms;
+       j < number;
+       j ++, psym ++)
+    {
+      psym->st_name  = BYTE_GET (esyms[j].st_name);
+      psym->st_value = BYTE_GET (esyms[j].st_value);
+      psym->st_size  = BYTE_GET (esyms[j].st_size);
+      psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
+      psym->st_info  = BYTE_GET (esyms[j].st_info);
+      psym->st_other = BYTE_GET (esyms[j].st_other);
+    }
+
+  free (esyms);
+
+  return isyms;
+}
+
+static int
+process_section_headers (file)
+     FILE * file;
+{
+  Elf32_Internal_Shdr * section;
+  int        i;
+
+  section_headers = NULL;
+
+  if (elf_header.e_shnum == 0)
+    {
+      if (do_sections)
+       printf (_("\nThere are no sections in this file.\n"));
+
+      return 1;
+    }
+
+  if (do_sections && !do_header)
+    printf (_("There are %d section headers, starting at offset %lx:\n"),
+           elf_header.e_shnum, (unsigned long) elf_header.e_shoff);
+
+  if (! get_section_headers (file))
+    return 0;
+
+  /* Read in the string table, so that we have names to display.  */
+  section = section_headers + elf_header.e_shstrndx;
+
+  if (section->sh_size != 0)
+    {
+      unsigned long string_table_offset;
+
+      string_table_offset = section->sh_offset;
+
+      GET_DATA_ALLOC (section->sh_offset, section->sh_size,
+                     string_table, char *, "string table");
+    }
+
+  /* Scan the sections for the dynamic symbol table
+     and dynamic string table and debug sections. */
+  dynamic_symbols = NULL;
+  dynamic_strings = NULL;
+  dynamic_syminfo = NULL;
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum;
+       i ++, section ++)
+    {
+      char * name = SECTION_NAME (section);
+
+      if (section->sh_type == SHT_DYNSYM)
+       {
+         if (dynamic_symbols != NULL)
+           {
+             error (_("File contains multiple dynamic symbol tables\n"));
+             continue;
+           }
+
+         dynamic_symbols = get_elf_symbols
+           (file, section->sh_offset,
+            section->sh_size / section->sh_entsize);
+       }
+      else if (section->sh_type == SHT_STRTAB
+              && strcmp (name, ".dynstr") == 0)
+       {
+         if (dynamic_strings != NULL)
+           {
+             error (_("File contains multiple dynamic string tables\n"));
+             continue;
+           }
+
+         GET_DATA_ALLOC (section->sh_offset, section->sh_size,
+                         dynamic_strings, char *, "dynamic strings");
+       }
+      else if ((do_debugging || do_debug_info || do_debug_abbrevs
+               || do_debug_lines || do_debug_pubnames || do_debug_aranges)
+              && strncmp (name, ".debug_", 7) == 0)
+       {
+         name += 7;
+
+         if (do_debugging
+             || (do_debug_info     && (strcmp (name, "info") == 0))
+             || (do_debug_abbrevs  && (strcmp (name, "abbrev") == 0))
+             || (do_debug_lines    && (strcmp (name, "line") == 0))
+             || (do_debug_pubnames && (strcmp (name, "pubnames") == 0))
+             || (do_debug_aranges  && (strcmp (name, "aranges") == 0))
+             )
+           request_dump (i, DEBUG_DUMP);
+       }
+    }
+
+  if (! do_sections)
+    return 1;
+
+  printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
+  printf
+    (_("  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\n"));
+
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum;
+       i ++, section ++)
+    {
+      printf ("  [%2d] %-17.17s %-15.15s ",
+             i,
+             SECTION_NAME (section),
+             get_section_type_name (section->sh_type));
+
+      printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
+              (unsigned long) section->sh_addr,
+              (unsigned long) section->sh_offset,
+              (unsigned long) section->sh_size,
+              (unsigned long) section->sh_entsize);
+
+      printf (" %c%c%c %2ld %3lx %ld\n",
+             (section->sh_flags & SHF_WRITE ? 'W' : ' '),
+             (section->sh_flags & SHF_ALLOC ? 'A' : ' '),
+             (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '),
+             (unsigned long) section->sh_link,
+             (unsigned long) section->sh_info,
+             (unsigned long) section->sh_addralign);
+    }
+
+  return 1;
+}
+
+/* Process the reloc section.  */
+static int
+process_relocs (file)
+     FILE * file;
+{
+  unsigned long    rel_size;
+  unsigned long           rel_offset;
+
+
+  if (!do_reloc)
+    return 1;
+
+  if (do_using_dynamic)
+    {
+      rel_size   = 0;
+      rel_offset = 0;
+
+      if (dynamic_info[DT_REL])
+       {
+         rel_offset = dynamic_info[DT_REL];
+         rel_size   = dynamic_info[DT_RELSZ];
+       }
+      else if (dynamic_info [DT_RELA])
+       {
+         rel_offset = dynamic_info[DT_RELA];
+         rel_size   = dynamic_info[DT_RELASZ];
+       }
+      else if (dynamic_info[DT_JMPREL])
+       {
+         rel_offset = dynamic_info[DT_JMPREL];
+         rel_size   = dynamic_info[DT_PLTRELSZ];
+       }
+
+      if (rel_size)
+       {
+         printf
+           (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"),
+            rel_offset, rel_size);
+
+         dump_relocations (file, rel_offset - loadaddr, rel_size,
+                           dynamic_symbols, dynamic_strings);
+       }
+      else
+       printf (_("\nThere are no dynamic relocations in this file.\n"));
+    }
+  else
+    {
+      Elf32_Internal_Shdr *     section;
+      unsigned long            i;
+      int                      found = 0;
+
+      for (i = 0, section = section_headers;
+          i < elf_header.e_shnum;
+          i++, section ++)
+       {
+         if (   section->sh_type != SHT_RELA
+             && section->sh_type != SHT_REL)
+           continue;
+
+         rel_offset = section->sh_offset;
+         rel_size   = section->sh_size;
+
+         if (rel_size)
+           {
+             Elf32_Internal_Shdr * strsec;
+             Elf32_Internal_Shdr * symsec;
+             Elf_Internal_Sym *    symtab;
+             char *                strtab;
+
+             printf (_("\nRelocation section "));
+
+             if (string_table == NULL)
+               printf ("%d", section->sh_name);
+             else
+               printf ("'%s'", SECTION_NAME (section));
+
+             printf (_(" at offset 0x%lx contains %lu entries:\n"),
+                rel_offset, (unsigned long) (rel_size / section->sh_entsize));
+
+             symsec = section_headers + section->sh_link;
+
+             symtab = get_elf_symbols (file, symsec->sh_offset,
+                                       symsec->sh_size / symsec->sh_entsize);
+
+             if (symtab == NULL)
+               continue;
+
+             strsec = section_headers + symsec->sh_link;
+
+             GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
+                             char *, "string table");
+
+             dump_relocations (file, rel_offset, rel_size, symtab, strtab);
+
+             free (strtab);
+             free (symtab);
+
+             found = 1;
+           }
+       }
+
+      if (! found)
+       printf (_("\nThere are no relocations in this file.\n"));
+    }
+
+  return 1;
+}
+
+
+static void
+dynamic_segment_mips_val (entry)
+     Elf_Internal_Dyn * entry;
+{
+  switch (entry->d_tag)
+    {
+    case DT_MIPS_FLAGS:
+      if (entry->d_un.d_val == 0)
+       printf ("NONE\n");
+      else
+       {
+         static const char * opts[] =
+         {
+           "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
+           "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
+           "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
+           "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
+           "RLD_ORDER_SAFE"
+         };
+         unsigned int cnt;
+         int first = 1;
+         for (cnt = 0; cnt < NUM_ELEM (opts); ++ cnt)
+           if (entry->d_un.d_val & (1 << cnt))
+             {
+               printf ("%s%s", first ? "" : " ", opts[cnt]);
+               first = 0;
+             }
+         puts ("");
+       }
+      break;
+      
+    case DT_MIPS_IVERSION:
+      if (dynamic_strings != NULL)
+       printf ("Interface Version: %s\n",
+               dynamic_strings + entry->d_un.d_val);
+      else
+       printf ("%ld\n", (long) entry->d_un.d_ptr);
+      break;
+      
+    case DT_MIPS_TIME_STAMP:
+      {
+       char timebuf[20];
+       time_t time = entry->d_un.d_val;
+       strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
+       printf ("Time Stamp: %s\n", timebuf);
+      }
+      break;
+      
+    case DT_MIPS_RLD_VERSION:
+    case DT_MIPS_LOCAL_GOTNO:
+    case DT_MIPS_CONFLICTNO:
+    case DT_MIPS_LIBLISTNO:
+    case DT_MIPS_SYMTABNO:
+    case DT_MIPS_UNREFEXTNO:
+    case DT_MIPS_HIPAGENO:
+    case DT_MIPS_DELTA_CLASS_NO:
+    case DT_MIPS_DELTA_INSTANCE_NO:
+    case DT_MIPS_DELTA_RELOC_NO:
+    case DT_MIPS_DELTA_SYM_NO:
+    case DT_MIPS_DELTA_CLASSSYM_NO:
+    case DT_MIPS_COMPACT_SIZE:
+      printf ("%ld\n", (long) entry->d_un.d_ptr);
+      break;
+      
+    default:
+      printf ("%#lx\n", (long) entry->d_un.d_ptr);
+    }
+}
+
+/* Parse the dynamic segment */
+static int
+process_dynamic_segment (file)
+     FILE * file;
+{
+  Elf_Internal_Dyn *    entry;
+  Elf32_External_Dyn *  edyn;
+  unsigned int i;
+
+  if (dynamic_size == 0)
+    {
+      if (do_dynamic)
+       printf (_("\nThere is no dynamic segment in this file.\n"));
+
+      return 1;
+    }
+
+  GET_DATA_ALLOC (dynamic_addr, dynamic_size,
+                 edyn, Elf32_External_Dyn *, "dynamic segment");
+  
+  /* SGI's ELF has more than one section in the DYNAMIC segment.  Determine
+     how large .dynamic is now.  We can do this even before the byte
+     swapping since the DT_NULL tag is recognizable.  */
+  dynamic_size = 0;
+  while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
+    ;
+
+  dynamic_segment = (Elf_Internal_Dyn *)
+    malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
+
+  if (dynamic_segment == NULL)
+    {
+      error (_("Out of memory\n"));
+      free (edyn);
+      return 0;
+    }
+
+  for (i = 0, entry = dynamic_segment;
+       i < dynamic_size;
+       i ++, entry ++)
+    {
+      entry->d_tag      = BYTE_GET (edyn [i].d_tag);
+      entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val);
+    }
+
+  free (edyn);
+
+  /* Find the appropriate symbol table.  */
+  if (dynamic_symbols == NULL)
+    {
+      for (i = 0, entry = dynamic_segment;
+          i < dynamic_size;
+          ++i, ++ entry)
+       {
+         unsigned long        offset;
+         long                 num_syms;
+
+         if (entry->d_tag != DT_SYMTAB)
+           continue;
+
+         dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
+
+         /* Since we do not know how big the symbol table is,
+            we default to reading in the entire file (!) and
+            processing that.  This is overkill, I know, but it
+            should work. */
+
+         offset = entry->d_un.d_val - loadaddr;
+
+         if (fseek (file, 0, SEEK_END))
+           error (_("Unable to seek to end of file!"));
+
+         num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
+
+         if (num_syms < 1)
+           {
+             error (_("Unable to determine the number of symbols to load\n"));
+             continue;
+           }
+
+         dynamic_symbols = get_elf_symbols (file, offset, num_syms);
+       }
+    }
+
+  /* Similarly find a string table.  */
+  if (dynamic_strings == NULL)
+    {
+      for (i = 0, entry = dynamic_segment;
+          i < dynamic_size;
+          ++i, ++ entry)
+       {
+         unsigned long offset;
+         long          str_tab_len;
+
+         if (entry->d_tag != DT_STRTAB)
+           continue;
+
+         dynamic_info[DT_STRTAB] = entry->d_un.d_val;
+
+         /* Since we do not know how big the string table is,
+            we default to reading in the entire file (!) and
+            processing that.  This is overkill, I know, but it
+            should work. */
+
+         offset = entry->d_un.d_val - loadaddr;
+         if (fseek (file, 0, SEEK_END))
+           error (_("Unable to seek to end of file\n"));
+         str_tab_len = ftell (file) - offset;
+
+         if (str_tab_len < 1)
+           {
+             error
+               (_("Unable to determine the length of the dynamic string table\n"));
+             continue;
+           }
+
+         GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
+                         "dynamic string table");
+
+         break;
+       }
+    }
+
+  /* And find the syminfo section if available.  */
+  if (dynamic_syminfo == NULL)
+    {
+      unsigned int syminsz = 0;
+
+      for (i = 0, entry = dynamic_segment;
+          i < dynamic_size;
+          ++i, ++ entry)
+       {
+         if (entry->d_tag == DT_SYMINENT)
+           {
+             /* Note: these braces are necessary to avoid a syntax
+                error from the SunOS4 C compiler.  */
+             assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
+           }
+         else if (entry->d_tag == DT_SYMINSZ)
+           syminsz = entry->d_un.d_val;
+         else if (entry->d_tag == DT_SYMINFO)
+           dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
+       }
+
+      if (dynamic_syminfo_offset != 0 && syminsz != 0)
+       {
+         Elf_External_Syminfo *extsyminfo;
+         Elf_Internal_Syminfo *syminfo;
+
+         /* There is a syminfo section.  Read the data.  */
+         GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo,
+                         Elf_External_Syminfo *, "symbol information");
+
+         dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
+         if (dynamic_syminfo == NULL)
+           {
+             error (_("Out of memory\n"));
+             return 0;
+           }
+
+         dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
+         for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
+              ++i, ++syminfo)
+           {
+             syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
+             syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
+           }
+
+         free (extsyminfo);
+       }
+    }
+
+  if (do_dynamic && dynamic_addr)
+    printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
+           dynamic_addr, dynamic_size);
+  if (do_dynamic)
+    printf (_("  Tag        Type                         Name/Value\n"));
+
+  for (i = 0, entry = dynamic_segment;
+       i < dynamic_size;
+       i++, entry ++)
+    {
+      if (do_dynamic)
+       printf (_("  0x%-8.8lx (%s)%*s"),
+               (unsigned long) entry->d_tag,
+               get_dynamic_type (entry->d_tag),
+               27 - strlen (get_dynamic_type (entry->d_tag)),
+               " ");
+
+      switch (entry->d_tag)
+       {
+       case DT_AUXILIARY:
+       case DT_FILTER:
+         if (do_dynamic)
+           {
+             if (entry->d_tag == DT_AUXILIARY)
+               printf (_("Auxiliary library"));
+             else
+               printf (_("Filter library"));
+
+             if (dynamic_strings)
+               printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
+             else
+               printf (": %#lx\n", (long) entry->d_un.d_val);
+           }
+         break;
+
+       case DT_FEATURE_1:
+         if (do_dynamic)
+           {
+             printf (_("Flags:"));
+             if (entry->d_un.d_val == 0)
+               printf (_(" None\n"));
+             else
+               {
+                 unsigned long int val = entry->d_un.d_val;
+                 if (val & DTF_1_PARINIT)
+                   {
+                     printf (" PARINIT");
+                     val ^= DTF_1_PARINIT;
+                   }
+                 if (val != 0)
+                   printf (" %lx", val);
+                 puts ("");
+               }
+           }
+         break;
+
+       case DT_POSFLAG_1:
+         if (do_dynamic)
+           {
+             printf (_("Flags:"));
+             if (entry->d_un.d_val == 0)
+               printf (_(" None\n"));
+             else
+               {
+                 unsigned long int val = entry->d_un.d_val;
+                 if (val & DF_P1_LAZYLOAD)
+                   {
+                     printf (" LAZYLOAD");
+                     val ^= DF_P1_LAZYLOAD;
+                   }
+                 if (val & DF_P1_GROUPPERM)
+                   {
+                     printf (" GROUPPERM");
+                     val ^= DF_P1_GROUPPERM;
+                   }
+                 if (val != 0)
+                   printf (" %lx", val);
+                 puts ("");
+               }
+           }
+         break;
+
+       case DT_FLAGS_1:
+         if (do_dynamic)
+           {
+             printf (_("Flags:"));
+             if (entry->d_un.d_val == 0)
+               printf (_(" None\n"));
+             else
+               {
+                 unsigned long int val = entry->d_un.d_val;
+                 if (val & DF_1_NOW)
+                   {
+                     printf (" NOW");
+                     val ^= DF_1_NOW;
+                   }
+                 if (val & DF_1_GLOBAL)
+                   {
+                     printf (" GLOBAL");
+                     val ^= DF_1_GLOBAL;
+                   }
+                 if (val & DF_1_GROUP)
+                   {
+                     printf (" GROUP");
+                     val ^= DF_1_GROUP;
+                   }
+                 if (val & DF_1_NODELETE)
+                   {
+                     printf (" NODELETE");
+                     val ^= DF_1_NODELETE;
+                   }
+                 if (val & DF_1_LOADFLTR)
+                   {
+                     printf (" LOADFLTR");
+                     val ^= DF_1_LOADFLTR;
+                   }
+                 if (val & DF_1_INITFIRST)
+                   {
+                     printf (" INITFIRST");
+                     val ^= DF_1_INITFIRST;
+                   }
+                 if (val & DF_1_NOOPEN)
+                   {
+                     printf (" NOOPEN");
+                     val ^= DF_1_NOOPEN;
+                   }
+                 if (val & DF_1_ORIGIN)
+                   {
+                     printf (" ORIGIN");
+                     val ^= DF_1_ORIGIN;
+                   }
+                 if (val & DF_1_DIRECT)
+                   {
+                     printf (" DIRECT");
+                     val ^= DF_1_DIRECT;
+                   }
+                 if (val & DF_1_TRANS)
+                   {
+                     printf (" TRANS");
+                     val ^= DF_1_TRANS;
+                   }
+                 if (val & DF_1_INTERPOSE)
+                   {
+                     printf (" INTERPOSE");
+                     val ^= DF_1_INTERPOSE;
+                   }
+                 if (val != 0)
+                   printf (" %lx", val);
+                 puts ("");
+               }
+           }
+         break;
+
+       case DT_PLTREL:
+         if (do_dynamic)
+           puts (get_dynamic_type (entry->d_un.d_val));
+         break;
+
+       case DT_NULL    :
+       case DT_NEEDED  :
+       case DT_PLTGOT  :
+       case DT_HASH    :
+       case DT_STRTAB  :
+       case DT_SYMTAB  :
+       case DT_RELA    :
+       case DT_INIT    :
+       case DT_FINI    :
+       case DT_SONAME  :
+       case DT_RPATH   :
+       case DT_SYMBOLIC:
+       case DT_REL     :
+       case DT_DEBUG   :
+       case DT_TEXTREL :
+       case DT_JMPREL  :
+         dynamic_info[entry->d_tag] = entry->d_un.d_val;
+
+         if (do_dynamic)
+           {
+             char * name;
+
+             if (dynamic_strings == NULL)
+               name = NULL;
+             else
+               name = dynamic_strings + entry->d_un.d_val;
+
+             if (name)
+               {
+                 switch (entry->d_tag)
+                   {
+                   case DT_NEEDED:
+                     printf (_("Shared library: [%s]"), name);
+
+                     if (strcmp (name, program_interpreter))
+                       printf ("\n");
+                     else
+                       printf (_(" program interpreter\n"));
+                     break;
+
+                   case DT_SONAME:
+                     printf (_("Library soname: [%s]\n"), name);
+                     break;
+
+                   case DT_RPATH:
+                     printf (_("Library rpath: [%s]\n"), name);
+                     break;
+
+                   default:
+                     printf ("%#lx\n", (long) entry->d_un.d_val);
+                   }
+               }
+             else
+               printf ("%#lx\n", (long) entry->d_un.d_val);
+           }
+         break;
+
+       case DT_PLTRELSZ:
+       case DT_RELASZ  :
+       case DT_STRSZ   :
+       case DT_RELSZ   :
+       case DT_RELAENT :
+       case DT_SYMENT  :
+       case DT_RELENT  :
+       case DT_PLTPADSZ:
+       case DT_MOVEENT :
+       case DT_MOVESZ  :
+       case DT_INIT_ARRAYSZ:
+       case DT_FINI_ARRAYSZ:
+         if (do_dynamic)
+           printf ("%lu (bytes)\n", (unsigned long) entry->d_un.d_val);
+         break;
+
+       case DT_VERDEFNUM:
+       case DT_VERNEEDNUM:
+       case DT_RELACOUNT:
+       case DT_RELCOUNT:
+         if (do_dynamic)
+           printf ("%lu\n", (unsigned long) entry->d_un.d_val);
+         break;
+
+       case DT_SYMINSZ:
+       case DT_SYMINENT:
+       case DT_SYMINFO:
+       case DT_USED:
+       case DT_INIT_ARRAY:
+       case DT_FINI_ARRAY:
+         if (do_dynamic)
+           {
+             if (dynamic_strings != NULL && entry->d_tag == DT_USED)
+               {
+                 char * name;
+
+                 name = dynamic_strings + entry->d_un.d_val;
+
+                 if (* name)
+                   {
+                     printf (_("Not needed object: [%s]\n"), name);
+                     break;
+                   }
+               }
+             
+             printf ("%#lx\n", (long) entry->d_un.d_val);
+           }
+         break;
+
+       case DT_BIND_NOW:
+         /* The value of this entry is ignored.  */
+         break;
+         
+       default:
+         if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
+           version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
+             entry->d_un.d_val;
+
+         if (do_dynamic)
+           {
+             switch (elf_header.e_machine)
+               {
+               case EM_MIPS:
+               case EM_MIPS_RS4_BE:
+                 dynamic_segment_mips_val (entry);
+                 break;
+               default:
+                 printf ("%#lx\n", (long) entry->d_un.d_ptr);
+               }
+           }
+         break;
+       }
+    }
+
+  return 1;
+}
+
+static char *
+get_ver_flags (flags)
+     unsigned int flags;
+{
+  static char buff [32];
+
+  buff[0] = 0;
+
+  if (flags == 0)
+    return _("none");
+
+  if (flags & VER_FLG_BASE)
+    strcat (buff, "BASE ");
+
+  if (flags & VER_FLG_WEAK)
+    {
+      if (flags & VER_FLG_BASE)
+       strcat (buff, "| ");
+
+      strcat (buff, "WEAK ");
+    }
+
+  if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
+    strcat (buff, "| <unknown>");
+
+  return buff;
+}
+
+/* Display the contents of the version sections.  */
+static int
+process_version_sections (file)
+     FILE * file;
+{
+  Elf32_Internal_Shdr * section;
+  unsigned   i;
+  int        found = 0;
+
+  if (! do_version)
+    return 1;
+
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum;
+       i++, section ++)
+    {
+      switch (section->sh_type)
+       {
+       case SHT_GNU_verdef:
+         {
+           Elf_External_Verdef * edefs;
+           unsigned int          idx;
+           unsigned int          cnt;
+
+           found = 1;
+
+           printf
+             (_("\nVersion definition section '%s' contains %ld entries:\n"),
+              SECTION_NAME (section), section->sh_info);
+
+           printf (_("  Addr: 0x"));
+           printf_vma (section->sh_addr);
+           printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
+                   section->sh_offset, section->sh_link,
+                   SECTION_NAME (section_headers + section->sh_link));
+
+           GET_DATA_ALLOC (section->sh_offset, section->sh_size,
+                           edefs, Elf_External_Verdef *,
+                           "version definition section");
+
+           for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
+             {
+               char *                 vstart;
+               Elf_External_Verdef *  edef;
+               Elf_Internal_Verdef    ent;
+               Elf_External_Verdaux * eaux;
+               Elf_Internal_Verdaux   aux;
+               int                    j;
+               int                    isum;
+               
+               vstart = ((char *) edefs) + idx;
+
+               edef = (Elf_External_Verdef *) vstart;
+
+               ent.vd_version = BYTE_GET (edef->vd_version);
+               ent.vd_flags   = BYTE_GET (edef->vd_flags);
+               ent.vd_ndx     = BYTE_GET (edef->vd_ndx);
+               ent.vd_cnt     = BYTE_GET (edef->vd_cnt);
+               ent.vd_hash    = BYTE_GET (edef->vd_hash);
+               ent.vd_aux     = BYTE_GET (edef->vd_aux);
+               ent.vd_next    = BYTE_GET (edef->vd_next);
+
+               printf (_("  %#06x: Rev: %d  Flags: %s"),
+                       idx, ent.vd_version, get_ver_flags (ent.vd_flags));
+
+               printf (_("  Index: %d  Cnt: %d  "),
+                       ent.vd_ndx, ent.vd_cnt);
+
+               vstart += ent.vd_aux;
+
+               eaux = (Elf_External_Verdaux *) vstart;
+
+               aux.vda_name = BYTE_GET (eaux->vda_name);
+               aux.vda_next = BYTE_GET (eaux->vda_next);
+
+               if (dynamic_strings)
+                 printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
+               else
+                 printf (_("Name index: %ld\n"), aux.vda_name);
+
+               isum = idx + ent.vd_aux;
+
+               for (j = 1; j < ent.vd_cnt; j ++)
+                 {
+                   isum   += aux.vda_next;
+                   vstart += aux.vda_next;
+
+                   eaux = (Elf_External_Verdaux *) vstart;
+
+                   aux.vda_name = BYTE_GET (eaux->vda_name);
+                   aux.vda_next = BYTE_GET (eaux->vda_next);
+
+                   if (dynamic_strings)
+                     printf (_("  %#06x: Parent %d: %s\n"),
+                             isum, j, dynamic_strings + aux.vda_name);
+                   else
+                     printf (_("  %#06x: Parent %d, name index: %ld\n"),
+                             isum, j, aux.vda_name);
+                 }
+
+               idx += ent.vd_next;
+             }
+
+           free (edefs);
+         }
+         break;
+         
+       case SHT_GNU_verneed:
+         {
+           Elf_External_Verneed *  eneed;
+           unsigned int            idx;
+           unsigned int            cnt;
+
+           found = 1;
+
+           printf (_("\nVersion needs section '%s' contains %ld entries:\n"),
+                   SECTION_NAME (section), section->sh_info);
+
+           printf (_(" Addr: 0x"));
+           printf_vma (section->sh_addr);
+           printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
+                   section->sh_offset, section->sh_link,
+                   SECTION_NAME (section_headers + section->sh_link));
+
+           GET_DATA_ALLOC (section->sh_offset, section->sh_size,
+                           eneed, Elf_External_Verneed *,
+                           "version need section");
+
+           for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
+             {
+               Elf_External_Verneed * entry;
+               Elf_Internal_Verneed     ent;
+               int                      j;
+               int                      isum;
+               char *                   vstart;
+
+               vstart = ((char *) eneed) + idx;
+
+               entry = (Elf_External_Verneed *) vstart;
+
+               ent.vn_version = BYTE_GET (entry->vn_version);
+               ent.vn_cnt     = BYTE_GET (entry->vn_cnt);
+               ent.vn_file    = BYTE_GET (entry->vn_file);
+               ent.vn_aux     = BYTE_GET (entry->vn_aux);
+               ent.vn_next    = BYTE_GET (entry->vn_next);
+
+               printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
+
+               if (dynamic_strings)
+                 printf (_("  File: %s"), dynamic_strings + ent.vn_file);
+               else
+                 printf (_("  File: %lx"), ent.vn_file);
+
+               printf (_("  Cnt: %d\n"), ent.vn_cnt);
+
+               vstart += ent.vn_aux;
+
+               for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
+                 {
+                   Elf_External_Vernaux * eaux;
+                   Elf_Internal_Vernaux   aux;
+
+                   eaux = (Elf_External_Vernaux *) vstart;
+
+                   aux.vna_hash  = BYTE_GET (eaux->vna_hash);
+                   aux.vna_flags = BYTE_GET (eaux->vna_flags);
+                   aux.vna_other = BYTE_GET (eaux->vna_other);
+                   aux.vna_name  = BYTE_GET (eaux->vna_name);
+                   aux.vna_next  = BYTE_GET (eaux->vna_next);
+
+                   if (dynamic_strings)
+                     printf (_("  %#06x: Name: %s"),
+                             isum, dynamic_strings + aux.vna_name);
+                   else
+                     printf (_("  %#06x: Name index: %lx"),
+                             isum, aux.vna_name);
+
+                   printf (_("  Flags: %s  Version: %d\n"),
+                           get_ver_flags (aux.vna_flags), aux.vna_other);
+
+                   isum   += aux.vna_next;
+                   vstart += aux.vna_next;
+                 }
+
+               idx += ent.vn_next;
+             }
+           
+           free (eneed);
+         }
+         break;
+
+       case SHT_GNU_versym:
+         {
+           Elf32_Internal_Shdr *       link_section;
+           int                         total;
+           int                         cnt;
+           unsigned char *             edata;
+           unsigned short *            data;
+           char *                      strtab;
+           Elf_Internal_Sym *          symbols;
+           Elf32_Internal_Shdr *       string_sec;
+
+           link_section = section_headers + section->sh_link;
+           total = section->sh_size / section->sh_entsize;
+
+           found = 1;
+
+           symbols = get_elf_symbols
+             (file, link_section->sh_offset,
+              link_section->sh_size / link_section->sh_entsize);
+
+           string_sec = section_headers + link_section->sh_link;
+
+           GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
+                           strtab, char *, "version string table");
+
+           printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
+                   SECTION_NAME (section), total);
+
+           printf (_(" Addr: "));
+           printf_vma (section->sh_addr);
+           printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
+                   section->sh_offset, section->sh_link,
+                   SECTION_NAME (link_section));
+
+           GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
+                           - loadaddr,
+                           total * sizeof (short), edata,
+                           unsigned char *, "version symbol data");
+
+           data = (unsigned short *) malloc (total * sizeof (short));
+
+           for (cnt = total; cnt --;)
+             data [cnt] = byte_get (edata + cnt * sizeof (short),
+                                    sizeof (short));
+
+           free (edata);
+
+           for (cnt = 0; cnt < total; cnt += 4)
+             {
+               int j, nn;
+
+               printf ("  %03x:", cnt);
+
+               for (j = 0; (j < 4) && (cnt + j) < total; ++j)
+                 switch (data [cnt + j])
+                   {
+                   case 0:
+                     fputs (_("   0 (*local*)    "), stdout);
+                     break;
+
+                   case 1:
+                     fputs (_("   1 (*global*)   "), stdout);
+                     break;
+
+                   default:
+                     nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
+                                  data [cnt + j] & 0x8000 ? 'h' : ' ');
+
+                     if (symbols [cnt + j].st_shndx < SHN_LORESERVE
+                         && section_headers[symbols [cnt + j].st_shndx].sh_type
+                         == SHT_NOBITS)
+                       {
+                         /* We must test both.  */
+                         Elf_Internal_Verneed     ivn;
+                         unsigned long            offset;
+
+                         offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
+                           - loadaddr;
+
+                         do
+                           {
+                             Elf_External_Verneed   evn;
+                             Elf_External_Vernaux   evna;
+                             Elf_Internal_Vernaux     ivna;
+                             unsigned long            vna_off;
+
+                             GET_DATA (offset, evn, "version need");
+
+                             ivn.vn_aux  = BYTE_GET (evn.vn_aux);
+                             ivn.vn_next = BYTE_GET (evn.vn_next);
+
+                             vna_off = offset + ivn.vn_aux;
+
+                             do
+                               {
+                                 GET_DATA (vna_off, evna,
+                                           "version need aux (1)");
+
+                                 ivna.vna_next  = BYTE_GET (evna.vna_next);
+                                 ivna.vna_other = BYTE_GET (evna.vna_other);
+
+                                 vna_off += ivna.vna_next;
+                               }
+                             while (ivna.vna_other != data [cnt + j]
+                                    && ivna.vna_next != 0);
+
+                             if (ivna.vna_other == data [cnt + j])
+                               {
+                                 ivna.vna_name = BYTE_GET (evna.vna_name);
+
+                                 nn += printf ("(%s%-*s",
+                                               strtab + ivna.vna_name,
+                                               12 - strlen (strtab
+                                                            + ivna.vna_name),
+                                               ")");
+                                 break;
+                               }
+                             else if (ivn.vn_next == 0)
+                               {
+                                 if (data [cnt + j] != 0x8001)
+                                   {
+                                     Elf_Internal_Verdef  ivd;
+                                     Elf_External_Verdef  evd;
+
+                                     offset = version_info
+                                       [DT_VERSIONTAGIDX (DT_VERDEF)]
+                                       - loadaddr;
+
+                                     do
+                                       {
+                                         GET_DATA (offset, evd,
+                                                   "version definition");
+
+                                         ivd.vd_next = BYTE_GET (evd.vd_next);
+                                         ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
+
+                                         offset += ivd.vd_next;
+                                       }
+                                     while (ivd.vd_ndx
+                                            != (data [cnt + j] & 0x7fff)
+                                            && ivd.vd_next != 0);
+
+                                     if (ivd.vd_ndx
+                                         == (data [cnt + j] & 0x7fff))
+                                       {
+                                         Elf_External_Verdaux  evda;
+                                         Elf_Internal_Verdaux  ivda;
+
+                                         ivd.vd_aux = BYTE_GET (evd.vd_aux);
+
+                                         GET_DATA (offset + ivd.vd_aux, evda,
+                                                   "version definition aux");
+
+                                         ivda.vda_name =
+                                           BYTE_GET (evda.vda_name);
+
+                                         nn +=
+                                           printf ("(%s%-*s",
+                                                   strtab + ivda.vda_name,
+                                                   12
+                                                   - strlen (strtab
+                                                             + ivda.vda_name),
+                                                   ")");
+                                       }
+                                   }
+
+                                 break;
+                               }
+                             else
+                               offset += ivn.vn_next;
+                           }
+                         while (ivn.vn_next);
+                       }
+                     else if (symbols [cnt + j].st_shndx == SHN_UNDEF)
+                       {
+                         Elf_Internal_Verneed     ivn;
+                         unsigned long            offset;
+
+                         offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
+                           - loadaddr;
+
+                         do
+                           {
+                             Elf_Internal_Vernaux     ivna;
+                             Elf_External_Verneed   evn;
+                             Elf_External_Vernaux   evna;
+                             unsigned long            a_off;
+
+                             GET_DATA (offset, evn, "version need");
+
+                             ivn.vn_aux  = BYTE_GET (evn.vn_aux);
+                             ivn.vn_next = BYTE_GET (evn.vn_next);
+
+                             a_off = offset + ivn.vn_aux;
+
+                             do
+                               {
+                                 GET_DATA (a_off, evna,
+                                           "version need aux (2)");
+
+                                 ivna.vna_next  = BYTE_GET (evna.vna_next);
+                                 ivna.vna_other = BYTE_GET (evna.vna_other);
+
+                                 a_off += ivna.vna_next;
+                               }
+                             while (ivna.vna_other != data [cnt + j]
+                                    && ivna.vna_next != 0);
+
+                             if (ivna.vna_other == data [cnt + j])
+                               {
+                                 ivna.vna_name = BYTE_GET (evna.vna_name);
+
+                                 nn += printf ("(%s%-*s",
+                                               strtab + ivna.vna_name,
+                                               12 - strlen (strtab
+                                                            + ivna.vna_name),
+                                               ")");
+                                 break;
+                               }
+
+                             offset += ivn.vn_next;
+                           }
+                         while (ivn.vn_next);
+                       }
+                     else if (data [cnt + j] != 0x8001)
+                       {
+                         Elf_Internal_Verdef  ivd;
+                         Elf_External_Verdef  evd;
+                         unsigned long        offset;
+
+                         offset = version_info
+                           [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
+
+                         do
+                           {
+                             GET_DATA (offset, evd, "version def");
+
+                             ivd.vd_next = BYTE_GET (evd.vd_next);
+                             ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
+
+                             offset += ivd.vd_next;
+                           }
+                         while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
+                                && ivd.vd_next != 0);
+
+                         if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
+                           {
+                             Elf_External_Verdaux  evda;
+                             Elf_Internal_Verdaux  ivda;
+
+                             ivd.vd_aux = BYTE_GET (evd.vd_aux);
+
+                             GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
+                                       evda, "version def aux");
+
+                             ivda.vda_name = BYTE_GET (evda.vda_name);
+
+                             nn += printf ("(%s%-*s",
+                                           strtab + ivda.vda_name,
+                                           12 - strlen (strtab
+                                                        + ivda.vda_name),
+                                           ")");
+                           }
+                       }
+
+                     if (nn < 18)
+                       printf ("%*c", 18 - nn, ' ');
+                   }
+
+               putchar ('\n');
+             }
+
+           free (data);
+           free (strtab);
+           free (symbols);
+         }
+         break;
+       
+       default:
+         break;
+       }
+    }
+
+  if (! found)
+    printf (_("\nNo version information found in this file.\n"));
+
+  return 1;
+}
+
+static char *
+get_symbol_binding (binding)
+     unsigned int binding;
+{
+  static char buff [32];
+
+  switch (binding)
+    {
+    case STB_LOCAL:  return _("LOCAL");
+    case STB_GLOBAL: return _("GLOBAL");
+    case STB_WEAK:   return _("WEAK");
+    default:
+      if (binding >= STB_LOPROC && binding <= STB_HIPROC)
+       sprintf (buff, _("<processor specific>: %d"), binding);
+      else if (binding >= STB_LOOS && binding <= STB_HIOS)
+       sprintf (buff, _("<OS specific>: %d"), binding);
+      else
+       sprintf (buff, _("<unknown>: %d"), binding);
+      return buff;
+    }
+}
+
+static char *
+get_symbol_type (type)
+     unsigned int type;
+{
+  static char buff [32];
+
+  switch (type)
+    {
+    case STT_NOTYPE:   return _("NOTYPE");
+    case STT_OBJECT:   return _("OBJECT");
+    case STT_FUNC:     return _("FUNC");
+    case STT_SECTION:  return _("SECTION");
+    case STT_FILE:     return _("FILE");
+    default:
+      if (type >= STT_LOPROC && type <= STT_HIPROC)
+       sprintf (buff, _("<processor specific>: %d"), type);
+      else if (type >= STT_LOOS && type <= STT_HIOS)
+       sprintf (buff, _("<OS specific>: %d"), type);
+      else
+       sprintf (buff, _("<unknown>: %d"), type);
+      return buff;
+    }
+}
+
+static char *
+get_symbol_index_type (type)
+     unsigned int type;
+{
+  switch (type)
+    {
+    case SHN_UNDEF:  return "UND";
+    case SHN_ABS:    return "ABS";
+    case SHN_COMMON: return "COM";
+    default:
+      if (type >= SHN_LOPROC && type <= SHN_HIPROC)
+       return "PRC";
+      else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
+       return "RSV";
+      else if (type >= SHN_LOOS && type <= SHN_HIOS)
+       return "OS ";
+      else
+       {
+         static char buff [32];
+
+         sprintf (buff, "%3d", type);
+         return buff;
+       }
+    }
+}
+
+
+static int *
+get_dynamic_data (file, number)
+     FILE *       file;
+     unsigned int number;
+{
+  char * e_data;
+  int *  i_data;
+
+  e_data = (char *) malloc (number * 4);
+
+  if (e_data == NULL)
+    {
+      error (_("Out of memory\n"));
+      return NULL;
+    }
+
+  if (fread (e_data, 4, number, file) != number)
+    {
+      error (_("Unable to read in dynamic data\n"));
+      return NULL;
+    }
+
+  i_data = (int *) malloc (number * sizeof (* i_data));
+
+  if (i_data == NULL)
+    {
+      error (_("Out of memory\n"));
+      free (e_data);
+      return NULL;
+    }
+
+  while (number--)
+    i_data [number] = byte_get (e_data + number * 4, 4);
+
+  free (e_data);
+
+  return i_data;
+}
+
+/* Dump the symbol table */
+static int
+process_symbol_table (file)
+     FILE * file;
+{
+  Elf32_Internal_Shdr *   section;
+  char   nb [4];
+  char   nc [4];
+  int    nbuckets;
+  int    nchains;
+  int *  buckets = NULL;
+  int *  chains = NULL;
+
+  if (! do_syms && !do_histogram)
+    return 1;
+
+  if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
+                               || do_histogram))
+    {
+      if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
+       {
+         error (_("Unable to seek to start of dynamic information"));
+         return 0;
+       }
+
+      if (fread (nb, sizeof (nb), 1, file) != 1)
+       {
+         error (_("Failed to read in number of buckets\n"));
+         return 0;
+       }
+
+      if (fread (nc, sizeof (nc), 1, file) != 1)
+       {
+         error (_("Failed to read in number of chains\n"));
+         return 0;
+       }
+
+      nbuckets = byte_get (nb, 4);
+      nchains  = byte_get (nc, 4);
+
+      buckets = get_dynamic_data (file, nbuckets);
+      chains  = get_dynamic_data (file, nchains);
+
+      if (buckets == NULL || chains == NULL)
+       return 0;
+    }
+
+  if (do_syms
+      && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
+    {
+      int    hn;
+      int    si;
+
+      printf (_("\nSymbol table for image:\n"));
+      printf (_("  Num Buc:    Value  Size   Type   Bind Ot Ndx Name\n"));
+
+      for (hn = 0; hn < nbuckets; hn++)
+       {
+         if (! buckets [hn])
+           continue;
+
+         for (si = buckets [hn]; si; si = chains [si])
+           {
+             Elf_Internal_Sym * psym;
+
+             psym = dynamic_symbols + si;
+
+             printf ("  %3d %3d: %8lx %5ld %6s %6s %2d ",
+                     si, hn,
+                     (unsigned long) psym->st_value,
+                     (unsigned long) psym->st_size,
+                     get_symbol_type (ELF_ST_TYPE (psym->st_info)),
+                     get_symbol_binding (ELF_ST_BIND (psym->st_info)),
+                     psym->st_other);
+
+             printf ("%3.3s", get_symbol_index_type (psym->st_shndx));
+
+             printf (" %s\n", dynamic_strings + psym->st_name);
+           }
+       }
+    }
+  else if (do_syms && !do_using_dynamic)
+    {
+      unsigned int     i;
+
+      for (i = 0, section = section_headers;
+          i < elf_header.e_shnum;
+          i++, section++)
+       {
+         unsigned int          si;
+         char *                strtab;
+         Elf_Internal_Sym *    symtab;
+         Elf_Internal_Sym *    psym;
+
+
+         if (   section->sh_type != SHT_SYMTAB
+             && section->sh_type != SHT_DYNSYM)
+           continue;
+
+         printf (_("\nSymbol table '%s' contains %lu entries:\n"),
+                 SECTION_NAME (section),
+                 (unsigned long) (section->sh_size / section->sh_entsize));
+         fputs (_("  Num:    Value  Size Type    Bind   Ot  Ndx Name\n"),
+                stdout);
+
+         symtab = get_elf_symbols (file, section->sh_offset,
+                                   section->sh_size / section->sh_entsize);
+         if (symtab == NULL)
+           continue;
+
+         if (section->sh_link == elf_header.e_shstrndx)
+           strtab = string_table;
+         else
+           {
+             Elf32_Internal_Shdr * string_sec;
+
+             string_sec = section_headers + section->sh_link;
+
+             GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
+                             strtab, char *, "string table");
+           }
+
+         for (si = 0, psym = symtab;
+              si < section->sh_size / section->sh_entsize;
+              si ++, psym ++)
+           {
+             printf ("  %3d: %8lx %5ld %-7s %-6s %2d ",
+                     si,
+                     (unsigned long) psym->st_value,
+                     (unsigned long) psym->st_size,
+                     get_symbol_type (ELF_ST_TYPE (psym->st_info)),
+                     get_symbol_binding (ELF_ST_BIND (psym->st_info)),
+                     psym->st_other);
+
+             if (psym->st_shndx == 0)
+               fputs (" UND", stdout);
+             else if ((psym->st_shndx & 0xffff) == 0xfff1)
+               fputs (" ABS", stdout);
+             else if ((psym->st_shndx & 0xffff) == 0xfff2)
+               fputs (" COM", stdout);
+             else
+               printf ("%4x", psym->st_shndx);
+
+             printf (" %s", strtab + psym->st_name);
+
+             if (section->sh_type == SHT_DYNSYM &&
+                 version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
+               {
+                 unsigned char   data[2];
+                 unsigned short  vers_data;
+                 unsigned long   offset;
+                 int             is_nobits;
+                 int             check_def;
+
+                 offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
+                   - loadaddr;
+
+                 GET_DATA (offset + si * sizeof (vers_data), data,
+                           "version data");
+
+                 vers_data = byte_get (data, 2);
+
+                 is_nobits = psym->st_shndx < SHN_LORESERVE ?
+                   (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
+                   : 0;
+
+                 check_def = (psym->st_shndx != SHN_UNDEF);
+
+                 if ((vers_data & 0x8000) || vers_data > 1)
+                   {
+                     if (is_nobits || ! check_def)
+                       {
+                         Elf_External_Verneed  evn;
+                         Elf_Internal_Verneed  ivn;
+                         Elf_Internal_Vernaux  ivna;
+
+                         /* We must test both.  */
+                         offset = version_info
+                           [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
+
+                         GET_DATA (offset, evn, "version need");
+
+                         ivn.vn_aux  = BYTE_GET (evn.vn_aux);
+                         ivn.vn_next = BYTE_GET (evn.vn_next);
+
+                         do
+                           {
+                             unsigned long  vna_off;
+
+                             vna_off = offset + ivn.vn_aux;
+
+                             do
+                               {
+                                 Elf_External_Vernaux  evna;
+
+                                 GET_DATA (vna_off, evna,
+                                           "version need aux (3)");
+
+                                 ivna.vna_other = BYTE_GET (evna.vna_other);
+                                 ivna.vna_next  = BYTE_GET (evna.vna_next);
+                                 ivna.vna_name  = BYTE_GET (evna.vna_name);
+
+                                 vna_off += ivna.vna_next;
+                               }
+                             while (ivna.vna_other != vers_data
+                                    && ivna.vna_next != 0);
+
+                             if (ivna.vna_other == vers_data)
+                               break;
+
+                             offset += ivn.vn_next;
+                           }
+                         while (ivn.vn_next != 0);
+
+                         if (ivna.vna_other == vers_data)
+                           {
+                             printf ("@%s (%d)",
+                                     strtab + ivna.vna_name, ivna.vna_other);
+                             check_def = 0;
+                           }
+                         else if (! is_nobits)
+                           error (_("bad dynamic symbol"));
+                         else
+                           check_def = 1;
+                       }
+
+                     if (check_def)
+                       {
+                         if (vers_data != 0x8001)
+                           {
+                             Elf_Internal_Verdef     ivd;
+                             Elf_Internal_Verdaux    ivda;
+                             Elf_External_Verdaux  evda;
+                             unsigned long           offset;
+
+                             offset =
+                               version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
+                               - loadaddr;
+
+                             do
+                               {
+                                 Elf_External_Verdef   evd;
+
+                                 GET_DATA (offset, evd, "version def");
+
+                                 ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
+                                 ivd.vd_aux  = BYTE_GET (evd.vd_aux);
+                                 ivd.vd_next = BYTE_GET (evd.vd_next);
+
+                                 offset += ivd.vd_next;
+                               }
+                             while (ivd.vd_ndx != (vers_data & 0x7fff)
+                                    && ivd.vd_next != 0);
+
+                             offset -= ivd.vd_next;
+                             offset += ivd.vd_aux;
+
+                             GET_DATA (offset, evda, "version def aux");
+
+                             ivda.vda_name = BYTE_GET (evda.vda_name);
+
+                             if (psym->st_name != ivda.vda_name)
+                               printf ((vers_data & 0x8000)
+                                       ? "@%s" : "@@%s",
+                                       strtab + ivda.vda_name);
+                           }
+                       }
+                   }
+               }
+
+             putchar ('\n');
+           }
+
+         free (symtab);
+         if (strtab != string_table)
+           free (strtab);
+       }
+    }
+  else if (do_syms)
+    printf
+      (_("\nDynamic symbol information is not available for displaying symbols.\n"));
+
+  if (do_histogram && buckets != NULL)
+    {
+      int *lengths;
+      int *counts;
+      int hn;
+      int si;
+      int maxlength = 0;
+      int nzero_counts = 0;
+      int nsyms = 0;
+
+      printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
+             nbuckets);
+      printf (_(" Length  Number     %% of total  Coverage\n"));
+
+      lengths = (int *) calloc (nbuckets, sizeof (int));
+      if (lengths == NULL)
+       {
+         error (_("Out of memory"));
+         return 0;
+       }
+      for (hn = 0; hn < nbuckets; ++hn)
+       {
+         if (! buckets [hn])
+           continue;
+
+         for (si = buckets[hn]; si; si = chains[si])
+           {
+             ++nsyms;
+             if (maxlength < ++lengths[hn])
+               ++maxlength;
+           }
+       }
+
+      counts = (int *) calloc (maxlength + 1, sizeof (int));
+      if (counts == NULL)
+       {
+         error (_("Out of memory"));
+         return 0;
+       }
+
+      for (hn = 0; hn < nbuckets; ++hn)
+       ++ counts [lengths [hn]];
+
+      printf ("      0  %-10d (%5.1f%%)\n",
+             counts[0], (counts[0] * 100.0) / nbuckets);
+      for (si = 1; si <= maxlength; ++si)
+       {
+         nzero_counts += counts[si] * si;
+         printf ("%7d  %-10d (%5.1f%%)    %5.1f%%\n",
+                 si, counts[si], (counts[si] * 100.0) / nbuckets,
+                 (nzero_counts * 100.0) / nsyms);
+       }
+
+      free (counts);
+      free (lengths);
+    }
+
+  if (buckets != NULL)
+    {
+      free (buckets);
+      free (chains);
+    }
+
+  return 1;
+}
+
+static int
+process_syminfo (file)
+     FILE * file;
+{
+  int i;
+
+  if (dynamic_syminfo == NULL
+      || !do_dynamic)
+    /* No syminfo, this is ok.  */
+    return 1;
+
+  /* There better should be a dynamic symbol section.  */
+  if (dynamic_symbols == NULL || dynamic_strings == NULL)
+    return 0;
+
+  if (dynamic_addr)
+    printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"),
+           dynamic_syminfo_offset, dynamic_syminfo_nent);
+
+  printf (_(" Num: Name                           BoundTo     Flags\n"));
+  for (i = 0; i < dynamic_syminfo_nent; ++i)
+    {
+      unsigned short int flags = dynamic_syminfo[i].si_flags;
+
+      printf ("%4d: %-30s ", i,
+             dynamic_strings + dynamic_symbols[i].st_name);
+
+      switch (dynamic_syminfo[i].si_boundto)
+       {
+       case SYMINFO_BT_SELF:
+         fputs ("SELF       ", stdout);
+         break;
+       case SYMINFO_BT_PARENT:
+         fputs ("PARENT     ", stdout);
+         break;
+       default:
+         if (dynamic_syminfo[i].si_boundto > 0
+             && dynamic_syminfo[i].si_boundto < dynamic_size)
+           printf ("%-10s ",
+                   dynamic_strings
+                   + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val);
+         else
+           printf ("%-10d ", dynamic_syminfo[i].si_boundto);
+         break;
+       }
+
+      if (flags & SYMINFO_FLG_DIRECT)
+       printf (" DIRECT");
+      if (flags & SYMINFO_FLG_PASSTHRU)
+       printf (" PASSTHRU");
+      if (flags & SYMINFO_FLG_COPY)
+       printf (" COPY");
+      if (flags & SYMINFO_FLG_LAZYLOAD)
+       printf (" LAZYLOAD");
+
+      puts ("");
+    }
+
+  return 1;
+}
+
+#ifdef SUPPORT_DISASSEMBLY
+static void
+disassemble_section (section, file)
+     Elf32_Internal_Shdr * section;
+     FILE * file;
+{
+  printf (_("\nAssembly dump of section %s\n"),
+         SECTION_NAME (section));
+
+  /* XXX -- to be done --- XXX */
+
+  return 1;
+}
+#endif
+
+static int
+dump_section (section, file)
+     Elf32_Internal_Shdr * section;
+     FILE * file;
+{
+  int             bytes;
+  int             addr;
+  unsigned char * data;
+  unsigned char * start;
+
+  bytes = section->sh_size;
+
+  if (bytes == 0)
+    {
+      printf (_("\nSection '%s' has no data to dump.\n"),
+             SECTION_NAME (section));
+      return 0;
+    }
+  else
+    printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
+
+  addr = section->sh_addr;
+
+  GET_DATA_ALLOC (section->sh_offset, bytes, start, unsigned char *,
+                 "section data");
+
+  data = start;
+
+  while (bytes)
+    {
+      int j;
+      int k;
+      int lbytes;
+
+      lbytes = (bytes > 16 ? 16 : bytes);
+
+      printf ("  0x%8.8x ", addr);
+
+      switch (elf_header.e_ident [EI_DATA])
+       {
+       case ELFDATA2LSB:
+         for (j = 15; j >= 0; j --)
+           {
+             if (j < lbytes)
+               printf ("%2.2x", data [j]);
+             else
+               printf ("  ");
+
+             if (!(j & 0x3))
+               printf (" ");
+           }
+         break;
+
+       case ELFDATA2MSB:
+         for (j = 0; j < 16; j++)
+           {
+             if (j < lbytes)
+               printf ("%2.2x", data [j]);
+             else
+               printf ("  ");
+
+             if ((j & 3) == 3)
+               printf (" ");
+           }
+         break;
+       }
+
+      for (j = 0; j < lbytes; j++)
+       {
+         k = data [j];
+         if (k >= ' ' && k < 0x80)
+           printf ("%c", k);
+         else
+           printf (".");
+       }
+
+      putchar ('\n');
+
+      data  += lbytes;
+      addr  += lbytes;
+      bytes -= lbytes;
+    }
+
+  free (start);
+
+  return 1;
+}
+
+
+static unsigned long int
+read_leb128 (data, length_return, sign)
+     unsigned char * data;
+     int *           length_return;
+     int             sign;
+{
+  unsigned long int result = 0;
+  unsigned int      num_read = 0;
+  int               shift = 0;
+  unsigned char     byte;
+
+  do
+    {
+      byte = * data ++;
+      num_read ++;
+
+      result |= (byte & 0x7f) << shift;
+
+      shift += 7;
+
+    }
+  while (byte & 0x80);
+
+  if (length_return != NULL)
+    * length_return = num_read;
+
+  if (sign && (shift < 32) && (byte & 0x40))
+    result |= -1 << shift;
+
+  return result;
+}
+
+typedef struct State_Machine_Registers
+{
+  unsigned long        address;
+  unsigned int  file;
+  unsigned int  line;
+  unsigned int  column;
+  int           is_stmt;
+  int           basic_block;
+  int          end_sequence;
+/* This variable hold the number of the last entry seen
+   in the File Table.  */
+  unsigned int  last_file_entry;
+} SMR;
+
+static SMR state_machine_regs;
+
+static void
+reset_state_machine (is_stmt)
+     int is_stmt;
+{
+  state_machine_regs.address = 0;
+  state_machine_regs.file = 1;
+  state_machine_regs.line = 1;
+  state_machine_regs.column = 0;
+  state_machine_regs.is_stmt = is_stmt;
+  state_machine_regs.basic_block = 0;
+  state_machine_regs.end_sequence = 0;
+  state_machine_regs.last_file_entry = 0;
+}
+
+/* Handled an extend line op.  Returns true if this is the end
+   of sequence.  */
+static int
+process_extended_line_op (data, is_stmt)
+     unsigned char * data;
+     int is_stmt;
+{
+  unsigned char   op_code;
+  int             bytes_read;
+  unsigned int    len;
+  unsigned char * name;
+  unsigned long   adr;
+  
+  len = read_leb128 (data, & bytes_read, 0);
+  data += bytes_read;
+
+  if (len == 0)
+    {
+      warn (_("badly formed extended line op encountered!"));
+      return bytes_read;
+    }
+
+  len += bytes_read;
+  op_code = * data ++;
+
+  printf (_("  Extended opcode %d: "), op_code);
+  
+  switch (op_code)
+    {
+    case DW_LNE_end_sequence:
+      printf (_("End of Sequence\n\n"));
+      reset_state_machine (is_stmt);
+      break;
+
+    case DW_LNE_set_address:
+      /* XXX - assumption here that address size is 4! */
+      adr = byte_get (data, 4);
+      printf (_("set Address to 0x%lx\n"), adr);
+      state_machine_regs.address = adr;
+      break;
+
+    case DW_LNE_define_file:
+      printf (_("  define new File Table entry\n"));
+      printf (_("  Entry\tDir\tTime\tSize\tName\n"));
+        
+      printf (_("   %d\t"), ++ state_machine_regs.last_file_entry);
+      name = data;
+      data += strlen (data) + 1;
+      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+      data += bytes_read;
+      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+      data += bytes_read;
+      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+      printf (_("%s\n\n"), name);
+      break;
+
+    default:
+      printf (_("UNKNOWN: length %d\n"), len - bytes_read);
+      break;
+    }
+
+  return len;
+}
+
+
+static int
+display_debug_lines (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file;
+{
+  DWARF2_External_LineInfo * external;
+  DWARF2_Internal_LineInfo   info;
+  unsigned char *            standard_opcodes;
+  unsigned char *            data = start;
+  unsigned char *            end  = start + section->sh_size;
+  unsigned char *            end_of_sequence;
+  int                        i;
+
+  printf (_("\nDump of debug contents of section %s:\n\n"),
+         SECTION_NAME (section));
+
+  while (data < end)
+    {
+      external = (DWARF2_External_LineInfo *) data;
+
+      /* Check the length of the block.  */
+      info.li_length = BYTE_GET (external->li_length);
+      if (info.li_length > section->sh_size)
+       {
+         warn
+           (_("The line info appears to be corrupt - the section is too small\n"));
+         return 0;
+       }
+      
+      /* Check its version number.  */
+      info.li_version = BYTE_GET (external->li_version);
+      if (info.li_version != 2)
+       {
+         warn (_("Only DWARF version 2 line info is currently supported.\n"));
+         return 0;
+       }
+      
+      info.li_prologue_length = BYTE_GET (external->li_prologue_length);
+      info.li_min_insn_length = BYTE_GET (external->li_min_insn_length);
+      info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt);
+      info.li_line_base       = BYTE_GET (external->li_line_base);
+      info.li_line_range      = BYTE_GET (external->li_line_range);
+      info.li_opcode_base     = BYTE_GET (external->li_opcode_base);
+      
+      /* Sign extend the line base field.  */
+      info.li_line_base <<= 24;
+      info.li_line_base >>= 24;
+      
+      printf (_("  Length:                      %ld\n"), info.li_length);
+      printf (_("  DWARF Version:               %d\n"), info.li_version);
+      printf (_("  Prolgue Length:              %d\n"), info.li_prologue_length);
+      printf (_("  Minimum Instruction Length:  %d\n"), info.li_min_insn_length);
+      printf (_("  Initial value of 'is_stmt':  %d\n"), info.li_default_is_stmt);
+      printf (_("  Line Base:                   %d\n"), info.li_line_base);
+      printf (_("  Line Range:                  %d\n"), info.li_line_range);
+      printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
+
+      end_of_sequence = data + info.li_length + sizeof (info.li_length);
+
+      reset_state_machine (info.li_default_is_stmt);
+      
+      /* Display the contents of the Opcodes table.  */
+      standard_opcodes = data + sizeof (* external);
+      
+      printf (_("\n Opcodes:\n"));
+      
+      for (i = 1; i < info.li_opcode_base; i++)
+       printf (_("  Opcode %d has %d args\n"), i, standard_opcodes[i]);
+      
+      /* Display the contents of the Directory table.  */
+      data = standard_opcodes + info.li_opcode_base - 1;
+      
+      if (* data == 0)
+       printf (_("\n The Directory Table is empty.\n"));
+      else
+       {
+         printf (_("\n The Directory Table:\n"));
+         
+         while (* data != 0)
+           {
+             printf (_("  %s\n"), data);
+             
+             data += strlen (data) + 1;
+           }
+       }
+      
+      /* Skip the NUL at the end of the table.  */
+      data ++;
+      
+      /* Display the contents of the File Name table.  */
+      if (* data == 0)
+       printf (_("\n The File Name Table is empty.\n"));
+      else
+       {
+         printf (_("\n The File Name Table:\n"));
+         printf (_("  Entry\tDir\tTime\tSize\tName\n"));
+         
+         while (* data != 0)
+           {
+             char * name;
+             int bytes_read;
+             
+             printf (_("  %d\t"), ++ state_machine_regs.last_file_entry);
+             name = data;
+             
+             data += strlen (data) + 1;
+             
+             printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+             data += bytes_read;
+             printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+             data += bytes_read;
+             printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+             data += bytes_read;
+             printf (_("%s\n"), name);
+           }
+       }
+      
+      /* Skip the NUL at the end of the table.  */
+      data ++;
+      
+      /* Now display the statements.  */
+      printf (_("\n Line Number Statements:\n"));
+      
+      
+      while (data < end_of_sequence)
+       {
+         unsigned char op_code;
+         int           adv;
+         int           bytes_read;
+         
+         op_code = * data ++;
+         
+         switch (op_code)
+           {
+           case DW_LNS_extended_op:
+             data += process_extended_line_op (data, info.li_default_is_stmt);
+             break;
+             
+           case DW_LNS_copy:
+             printf (_("  Copy\n"));
+             break;
+             
+           case DW_LNS_advance_pc:
+             adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0);
+             data += bytes_read;
+             state_machine_regs.address += adv;
+             printf (_("  Advance PC by %d to %lx\n"), adv,
+                     state_machine_regs.address);
+             break;
+             
+           case DW_LNS_advance_line:
+             adv = read_leb128 (data, & bytes_read, 1);
+             data += bytes_read;
+             state_machine_regs.line += adv;
+             printf (_("  Advance Line by %d to %d\n"), adv,
+                     state_machine_regs.line);
+             break;
+             
+           case DW_LNS_set_file:
+             adv = read_leb128 (data, & bytes_read, 0);
+             data += bytes_read;
+             printf (_("  Set File Name to entry %d in the File Name Table\n"),
+                     adv);
+             state_machine_regs.file = adv;
+             break;
+             
+           case DW_LNS_set_column:
+             adv = read_leb128 (data, & bytes_read, 0);
+             data += bytes_read;
+             printf (_("  Set column to %d\n"), adv);
+             state_machine_regs.column = adv;
+             break;
+             
+           case DW_LNS_negate_stmt:
+             adv = state_machine_regs.is_stmt;
+             adv = ! adv;
+             printf (_("  Set is_stmt to %d\n"), adv);
+             state_machine_regs.is_stmt = adv;
+             break;
+             
+           case DW_LNS_set_basic_block:
+             printf (_("  Set basic block\n"));
+             state_machine_regs.basic_block = 1;
+             break;
+             
+           case DW_LNS_const_add_pc:
+             adv = (255 - info.li_opcode_base) / info.li_line_range;
+             state_machine_regs.address += adv;
+             printf (_("  Advance PC by constant %d to 0x%lx\n"), adv,
+                     state_machine_regs.address);
+             break;
+             
+           case DW_LNS_fixed_advance_pc:
+             adv = byte_get (data, 2);
+             data += 2;
+             state_machine_regs.address += adv;
+             printf (_("  Advance PC by fixed size amount %d to 0x%lx\n"),
+                     adv, state_machine_regs.address);
+             break;
+             
+           default:
+             op_code -= info.li_opcode_base;
+             adv      = (op_code / info.li_line_range) * info.li_min_insn_length;
+             state_machine_regs.address += adv;
+             printf (_("  Special opcode %d: advance Address by %d to 0x%lx"),
+                     op_code, adv, state_machine_regs.address);
+             adv    += (op_code % info.li_line_range) + info.li_line_base;
+             state_machine_regs.line += adv;
+             printf (_(" and Line by %d to %d\n"),
+                     adv, state_machine_regs.line);
+             break;
+           }
+       }
+      printf ("\n");
+    }
+  
+  return 1;
+}
+
+static int
+display_debug_pubnames (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file;
+{
+  DWARF2_External_PubNames * external;
+  DWARF2_Internal_PubNames   pubnames;
+  unsigned char *            end;
+
+  end = start + section->sh_size;
+
+  printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
+
+  while (start < end)
+    {
+      unsigned char * data;
+      unsigned long   offset;
+
+      external = (DWARF2_External_PubNames *) start;
+
+      pubnames.pn_length  = BYTE_GET (external->pn_length);
+      pubnames.pn_version = BYTE_GET (external->pn_version);
+      pubnames.pn_offset  = BYTE_GET (external->pn_offset);
+      pubnames.pn_size    = BYTE_GET (external->pn_size);
+
+      data   = start + sizeof (* external);
+      start += pubnames.pn_length + sizeof (external->pn_length);
+
+      if (pubnames.pn_version != 2)
+       {
+         warn (_("Only DWARF 2 pubnames are currently supported"));
+         continue;
+       }
+
+      printf (_("  Length:                              %ld\n"),
+             pubnames.pn_length);
+      printf (_("  Version:                             %d\n"),
+             pubnames.pn_version);
+      printf (_("  Offset into .debug_info section:     %ld\n"),
+             pubnames.pn_offset);
+      printf (_("  Size of area in .debug_info section: %ld\n"),
+             pubnames.pn_size);
+
+      printf (_("\n    Offset\tName\n"));
+
+      do
+       {
+         offset = byte_get (data, 4);
+
+         if (offset != 0)
+           {
+             data += 4;
+             printf ("    %ld\t\t%s\n", offset, data);
+             data += strlen (data) + 1;
+           }
+       }
+      while (offset != 0);
+    }
+
+  printf ("\n");
+  return 1;
+}
+
+static char *
+get_TAG_name (tag)
+     unsigned long tag;
+{
+  switch (tag)
+    {
+    case DW_TAG_padding: return "DW_TAG_padding";
+    case DW_TAG_array_type: return "DW_TAG_array_type";
+    case DW_TAG_class_type: return "DW_TAG_class_type";
+    case DW_TAG_entry_point: return "DW_TAG_entry_point";
+    case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type";
+    case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter";
+    case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration";
+    case DW_TAG_label: return "DW_TAG_label";
+    case DW_TAG_lexical_block: return "DW_TAG_lexical_block";
+    case DW_TAG_member: return "DW_TAG_member";
+    case DW_TAG_pointer_type: return "DW_TAG_pointer_type";
+    case DW_TAG_reference_type: return "DW_TAG_reference_type";
+    case DW_TAG_compile_unit: return "DW_TAG_compile_unit";
+    case DW_TAG_string_type: return "DW_TAG_string_type";
+    case DW_TAG_structure_type: return "DW_TAG_structure_type";
+    case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type";
+    case DW_TAG_typedef: return "DW_TAG_typedef";
+    case DW_TAG_union_type: return "DW_TAG_union_type";
+    case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters";
+    case DW_TAG_variant: return "DW_TAG_variant";
+    case DW_TAG_common_block: return "DW_TAG_common_block";
+    case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion";
+    case DW_TAG_inheritance: return "DW_TAG_inheritance";
+    case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine";
+    case DW_TAG_module: return "DW_TAG_module";
+    case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type";
+    case DW_TAG_set_type: return "DW_TAG_set_type";
+    case DW_TAG_subrange_type: return "DW_TAG_subrange_type";
+    case DW_TAG_with_stmt: return "DW_TAG_with_stmt";
+    case DW_TAG_access_declaration: return "DW_TAG_access_declaration";
+    case DW_TAG_base_type: return "DW_TAG_base_type";
+    case DW_TAG_catch_block: return "DW_TAG_catch_block";
+    case DW_TAG_const_type: return "DW_TAG_const_type";
+    case DW_TAG_constant: return "DW_TAG_constant";
+    case DW_TAG_enumerator: return "DW_TAG_enumerator";
+    case DW_TAG_file_type: return "DW_TAG_file_type";
+    case DW_TAG_friend: return "DW_TAG_friend";
+    case DW_TAG_namelist: return "DW_TAG_namelist";
+    case DW_TAG_namelist_item: return "DW_TAG_namelist_item";
+    case DW_TAG_packed_type: return "DW_TAG_packed_type";
+    case DW_TAG_subprogram: return "DW_TAG_subprogram";
+    case DW_TAG_template_type_param: return "DW_TAG_template_type_param";
+    case DW_TAG_template_value_param: return "DW_TAG_template_value_param";
+    case DW_TAG_thrown_type: return "DW_TAG_thrown_type";
+    case DW_TAG_try_block: return "DW_TAG_try_block";
+    case DW_TAG_variant_part: return "DW_TAG_variant_part";
+    case DW_TAG_variable: return "DW_TAG_variable";
+    case DW_TAG_volatile_type: return "DW_TAG_volatile_type";
+    case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop";
+    case DW_TAG_format_label: return "DW_TAG_format_label";
+    case DW_TAG_function_template: return "DW_TAG_function_template";
+    case DW_TAG_class_template: return "DW_TAG_class_template";
+    default:
+      {
+       static char buffer [100];
+
+       sprintf (buffer, _("Unknown TAG value: %lx"), tag);
+       return buffer;
+      }
+    }
+}
+
+static char *
+get_AT_name (attribute)
+     unsigned long attribute;
+{
+  switch (attribute)
+    {
+    case DW_AT_sibling: return "DW_AT_sibling";
+    case DW_AT_location: return "DW_AT_location";
+    case DW_AT_name: return "DW_AT_name";
+    case DW_AT_ordering: return "DW_AT_ordering";
+    case DW_AT_subscr_data: return "DW_AT_subscr_data";
+    case DW_AT_byte_size: return "DW_AT_byte_size";
+    case DW_AT_bit_offset: return "DW_AT_bit_offset";
+    case DW_AT_bit_size: return "DW_AT_bit_size";
+    case DW_AT_element_list: return "DW_AT_element_list";
+    case DW_AT_stmt_list: return "DW_AT_stmt_list";
+    case DW_AT_low_pc: return "DW_AT_low_pc";
+    case DW_AT_high_pc: return "DW_AT_high_pc";
+    case DW_AT_language: return "DW_AT_language";
+    case DW_AT_member: return "DW_AT_member";
+    case DW_AT_discr: return "DW_AT_discr";
+    case DW_AT_discr_value: return "DW_AT_discr_value";
+    case DW_AT_visibility: return "DW_AT_visibility";
+    case DW_AT_import: return "DW_AT_import";
+    case DW_AT_string_length: return "DW_AT_string_length";
+    case DW_AT_common_reference: return "DW_AT_common_reference";
+    case DW_AT_comp_dir: return "DW_AT_comp_dir";
+    case DW_AT_const_value: return "DW_AT_const_value";
+    case DW_AT_containing_type: return "DW_AT_containing_type";
+    case DW_AT_default_value: return "DW_AT_default_value";
+    case DW_AT_inline: return "DW_AT_inline";
+    case DW_AT_is_optional: return "DW_AT_is_optional";
+    case DW_AT_lower_bound: return "DW_AT_lower_bound";
+    case DW_AT_producer: return "DW_AT_producer";
+    case DW_AT_prototyped: return "DW_AT_prototyped";
+    case DW_AT_return_addr: return "DW_AT_return_addr";
+    case DW_AT_start_scope: return "DW_AT_start_scope";
+    case DW_AT_stride_size: return "DW_AT_stride_size";
+    case DW_AT_upper_bound: return "DW_AT_upper_bound";
+    case DW_AT_abstract_origin: return "DW_AT_abstract_origin";
+    case DW_AT_accessibility: return "DW_AT_accessibility";
+    case DW_AT_address_class: return "DW_AT_address_class";
+    case DW_AT_artificial: return "DW_AT_artificial";
+    case DW_AT_base_types: return "DW_AT_base_types";
+    case DW_AT_calling_convention: return "DW_AT_calling_convention";
+    case DW_AT_count: return "DW_AT_count";
+    case DW_AT_data_member_location: return "DW_AT_data_member_location";
+    case DW_AT_decl_column: return "DW_AT_decl_column";
+    case DW_AT_decl_file: return "DW_AT_decl_file";
+    case DW_AT_decl_line: return "DW_AT_decl_line";
+    case DW_AT_declaration: return "DW_AT_declaration";
+    case DW_AT_discr_list: return "DW_AT_discr_list";
+    case DW_AT_encoding: return "DW_AT_encoding";
+    case DW_AT_external: return "DW_AT_external";
+    case DW_AT_frame_base: return "DW_AT_frame_base";
+    case DW_AT_friend: return "DW_AT_friend";
+    case DW_AT_identifier_case: return "DW_AT_identifier_case";
+    case DW_AT_macro_info: return "DW_AT_macro_info";
+    case DW_AT_namelist_items: return "DW_AT_namelist_items";
+    case DW_AT_priority: return "DW_AT_priority";
+    case DW_AT_segment: return "DW_AT_segment";
+    case DW_AT_specification: return "DW_AT_specification";
+    case DW_AT_static_link: return "DW_AT_static_link";
+    case DW_AT_type: return "DW_AT_type";
+    case DW_AT_use_location: return "DW_AT_use_location";
+    case DW_AT_variable_parameter: return "DW_AT_variable_parameter";
+    case DW_AT_virtuality: return "DW_AT_virtuality";
+    case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location";
+    case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde";
+    case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin";
+    case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin";
+    case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin";
+    case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
+    case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth";
+    case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name";
+    case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride";
+    case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name";
+    case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin";
+    case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines";
+    case DW_AT_sf_names: return "DW_AT_sf_names";
+    case DW_AT_src_info: return "DW_AT_src_info";
+    case DW_AT_mac_info: return "DW_AT_mac_info";
+    case DW_AT_src_coords: return "DW_AT_src_coords";
+    case DW_AT_body_begin: return "DW_AT_body_begin";
+    case DW_AT_body_end: return "DW_AT_body_end";
+    default:
+      {
+       static char buffer [100];
+
+       sprintf (buffer, _("Unknown AT value: %lx"), attribute);
+       return buffer;
+      }
+    }
+}
+
+static char *
+get_FORM_name (form)
+     unsigned long form;
+{
+  switch (form)
+    {
+    case DW_FORM_addr: return "DW_FORM_addr";
+    case DW_FORM_block2: return "DW_FORM_block2";
+    case DW_FORM_block4: return "DW_FORM_block4";
+    case DW_FORM_data2: return "DW_FORM_data2";
+    case DW_FORM_data4: return "DW_FORM_data4";
+    case DW_FORM_data8: return "DW_FORM_data8";
+    case DW_FORM_string: return "DW_FORM_string";
+    case DW_FORM_block: return "DW_FORM_block";
+    case DW_FORM_block1: return "DW_FORM_block1";
+    case DW_FORM_data1: return "DW_FORM_data1";
+    case DW_FORM_flag: return "DW_FORM_flag";
+    case DW_FORM_sdata: return "DW_FORM_sdata";
+    case DW_FORM_strp: return "DW_FORM_strp";
+    case DW_FORM_udata: return "DW_FORM_udata";
+    case DW_FORM_ref_addr: return "DW_FORM_ref_addr";
+    case DW_FORM_ref1: return "DW_FORM_ref1";
+    case DW_FORM_ref2: return "DW_FORM_ref2";
+    case DW_FORM_ref4: return "DW_FORM_ref4";
+    case DW_FORM_ref8: return "DW_FORM_ref8";
+    case DW_FORM_ref_udata: return "DW_FORM_ref_udata";
+    case DW_FORM_indirect: return "DW_FORM_indirect";
+    default:
+      {
+       static char buffer [100];
+
+       sprintf (buffer, _("Unknown FORM value: %lx"), form);
+       return buffer;
+      }
+    }
+}
+
+/* FIXME:  There are better and more effiecint ways to handle
+   these structures.  For now though, I just want something that
+   is simple to implement.  */
+typedef struct abbrev_attr
+{
+  unsigned long        attribute;
+  unsigned long        form;
+  struct abbrev_attr * next;
+}
+abbrev_attr;
+
+typedef struct abbrev_entry
+{
+  unsigned long          entry;
+  unsigned long          tag;
+  int                    children;
+  struct abbrev_attr *   first_attr;
+  struct abbrev_attr *   last_attr;
+  struct abbrev_entry *  next;
+}
+abbrev_entry;
+
+static abbrev_entry * first_abbrev = NULL;
+static abbrev_entry * last_abbrev = NULL;
+
+static void
+free_abbrevs PARAMS ((void))
+{
+  abbrev_entry * abbrev;
+
+  for (abbrev = first_abbrev; abbrev;)
+    {
+      abbrev_entry * next = abbrev->next;
+      abbrev_attr  * attr;
+
+      for (attr = abbrev->first_attr; attr;)
+       {
+         abbrev_attr * next = attr->next;
+
+         free (attr);
+         attr = next;
+       }
+
+      free (abbrev);
+      abbrev = next;
+    }
+
+  last_abbrev = first_abbrev = NULL;
+}
+
+static void
+add_abbrev (number, tag, children)
+     unsigned long number;
+     unsigned long tag;
+     int           children;
+{
+  abbrev_entry * entry;
+
+  entry = (abbrev_entry *) malloc (sizeof (* entry));
+
+  if (entry == NULL)
+    /* ugg */
+    return;
+
+  entry->entry      = number;
+  entry->tag        = tag;
+  entry->children   = children;
+  entry->first_attr = NULL;
+  entry->last_attr  = NULL;
+  entry->next       = NULL;
+
+  if (first_abbrev == NULL)
+    first_abbrev = entry;
+  else
+    last_abbrev->next = entry;
+
+  last_abbrev = entry;
+}
+
+static void
+add_abbrev_attr (attribute, form)
+     unsigned long attribute;
+     unsigned long form;
+{
+  abbrev_attr * attr;
+
+  attr = (abbrev_attr *) malloc (sizeof (* attr));
+
+  if (attr == NULL)
+    /* ugg */
+    return;
+
+  attr->attribute = attribute;
+  attr->form      = form;
+  attr->next      = NULL;
+
+  if (last_abbrev->first_attr == NULL)
+    last_abbrev->first_attr = attr;
+  else
+    last_abbrev->last_attr->next = attr;
+
+  last_abbrev->last_attr = attr;
+}
+
+/* Processes the (partial) contents of a .debug_abbrev section.
+   Returns NULL if the end of the section was encountered.
+   Returns the address after the last byte read if the end of
+   an abbreviation set was found.  */
+
+static unsigned char *
+process_abbrev_section (start, end)
+     unsigned char * start;
+     unsigned char * end;
+{
+  if (first_abbrev != NULL)
+    return NULL;
+
+  while (start < end)
+    {
+      int           bytes_read;
+      unsigned long entry;
+      unsigned long tag;
+      unsigned long attribute;
+      int           children;
+
+      entry = read_leb128 (start, & bytes_read, 0);
+      start += bytes_read;
+
+      if (entry == 0)
+       return start;
+
+      tag = read_leb128 (start, & bytes_read, 0);
+      start += bytes_read;
+
+      children = * start ++;
+
+      add_abbrev (entry, tag, children);
+
+      do
+       {
+         unsigned long form;
+
+         attribute = read_leb128 (start, & bytes_read, 0);
+         start += bytes_read;
+
+         form = read_leb128 (start, & bytes_read, 0);
+         start += bytes_read;
+
+         if (attribute != 0)
+           add_abbrev_attr (attribute, form);
+       }
+      while (attribute != 0);
+    }
+
+  return NULL;
+}
+
+
+static int
+display_debug_abbrev (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file;
+{
+  abbrev_entry * entry;
+  unsigned char * end = start + section->sh_size;
+
+  printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
+
+  do
+    {
+      start = process_abbrev_section (start, end);
+
+      printf (_("  Number TAG\n"));
+
+      for (entry = first_abbrev; entry; entry = entry->next)
+       {
+         abbrev_attr * attr;
+
+         printf (_("   %ld      %s    [%s]\n"),
+                 entry->entry,
+                 get_TAG_name (entry->tag),
+                 entry->children ? _("has children") : _("no children"));
+
+         for (attr = entry->first_attr; attr; attr = attr->next)
+           {
+             printf (_("    %-18s %s\n"),
+                     get_AT_name (attr->attribute),
+                     get_FORM_name (attr->form));
+           }
+       }
+    }
+  while (start);
+
+  printf ("\n");
+
+  return 1;
+}
+
+
+static unsigned char *
+display_block (data, length)
+     unsigned char * data;
+     unsigned long   length;
+{
+  printf (_(" %lu byte block: "), length);
+
+  while (length --)
+    printf ("%lx ", byte_get (data ++, 1));
+
+  return data;
+}
+
+static void
+decode_location_expression (data, pointer_size)
+     unsigned char * data;
+     unsigned int    pointer_size;
+{
+  unsigned char op;
+  int           bytes_read;
+
+  op = * data ++;
+
+  switch (op)
+    {
+    case DW_OP_addr:   printf ("DW_OP_addr: %lx", byte_get (data, pointer_size)); break;
+    case DW_OP_deref:  printf ("DW_OP_deref"); break;
+    case DW_OP_const1u:        printf ("DW_OP_const1u: %lu", byte_get (data, 1)); break;
+    case DW_OP_const1s:        printf ("DW_OP_const1s: %ld", (long) byte_get (data, 1)); break;
+    case DW_OP_const2u:        printf ("DW_OP_const2u: %lu", byte_get (data, 2)); break;
+    case DW_OP_const2s:        printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2)); break;
+    case DW_OP_const4u:        printf ("DW_OP_const4u: %lu", byte_get (data, 4)); break;
+    case DW_OP_const4s:        printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4)); break;
+    case DW_OP_const8u:        printf ("DW_OP_const8u: %lu %lu", byte_get (data, 4), byte_get (data + 4, 4)); break;
+    case DW_OP_const8s:        printf ("DW_OP_const8s: %ld %ld", byte_get (data, 4), byte_get (data + 4, 4)); break;
+    case DW_OP_constu: printf ("DW_OP_constu: %lu", read_leb128 (data, NULL, 0)); break;
+    case DW_OP_consts: printf ("DW_OP_consts: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_dup:    printf ("DW_OP_dup"); break;
+    case DW_OP_drop:   printf ("DW_OP_drop"); break;
+    case DW_OP_over:   printf ("DW_OP_over"); break;
+    case DW_OP_pick:   printf ("DW_OP_pick: %ld", byte_get (data, 1)); break;
+    case DW_OP_swap:   printf ("DW_OP_swap"); break;
+    case DW_OP_rot:    printf ("DW_OP_rot"); break;
+    case DW_OP_xderef: printf ("DW_OP_xderef"); break;
+    case DW_OP_abs:    printf ("DW_OP_abs"); break;
+    case DW_OP_and:    printf ("DW_OP_and"); break;
+    case DW_OP_div:    printf ("DW_OP_div"); break;
+    case DW_OP_minus:  printf ("DW_OP_minus"); break;
+    case DW_OP_mod:    printf ("DW_OP_mod"); break;
+    case DW_OP_mul:    printf ("DW_OP_mul"); break;
+    case DW_OP_neg:    printf ("DW_OP_neg"); break;
+    case DW_OP_not:    printf ("DW_OP_not"); break;
+    case DW_OP_or:     printf ("DW_OP_or"); break;
+    case DW_OP_plus:   printf ("DW_OP_plus"); break;
+    case DW_OP_plus_uconst:    printf ("DW_OP_plus_uconst: %lu", read_leb128 (data, NULL, 0)); break;
+    case DW_OP_shl:    printf ("DW_OP_shl"); break;
+    case DW_OP_shr:    printf ("DW_OP_shr"); break;
+    case DW_OP_shra:   printf ("DW_OP_shra"); break;
+    case DW_OP_xor:    printf ("DW_OP_xor"); break;
+    case DW_OP_bra:    printf ("DW_OP_bra: %ld", byte_get (data, 2)); break;
+    case DW_OP_eq:     printf ("DW_OP_eq"); break;
+    case DW_OP_ge:     printf ("DW_OP_ge"); break;
+    case DW_OP_gt:     printf ("DW_OP_gt"); break;
+    case DW_OP_le:     printf ("DW_OP_le"); break;
+    case DW_OP_lt:     printf ("DW_OP_lt"); break;
+    case DW_OP_ne:     printf ("DW_OP_ne"); break;
+    case DW_OP_skip:   printf ("DW_OP_skip: %ld", byte_get (data, 2)); break;
+    case DW_OP_lit0:   printf ("DW_OP_lit0"); break;
+    case DW_OP_lit1:   printf ("DW_OP_lit1"); break;
+    case DW_OP_lit2:   printf ("DW_OP_lit2"); break;
+    case DW_OP_lit3:   printf ("DW_OP_lit3"); break;
+    case DW_OP_lit4:   printf ("DW_OP_lit4"); break;
+    case DW_OP_lit5:   printf ("DW_OP_lit5"); break;
+    case DW_OP_lit6:   printf ("DW_OP_lit6"); break;
+    case DW_OP_lit7:   printf ("DW_OP_lit7"); break;
+    case DW_OP_lit8:   printf ("DW_OP_lit8"); break;
+    case DW_OP_lit9:   printf ("DW_OP_lit9"); break;
+    case DW_OP_lit10:  printf ("DW_OP_lit10"); break;
+    case DW_OP_lit11:  printf ("DW_OP_lit11"); break;
+    case DW_OP_lit12:  printf ("DW_OP_lit12"); break;
+    case DW_OP_lit13:  printf ("DW_OP_lit13"); break;
+    case DW_OP_lit14:  printf ("DW_OP_lit14"); break;
+    case DW_OP_lit15:  printf ("DW_OP_lit15"); break;
+    case DW_OP_lit16:  printf ("DW_OP_lit16"); break;
+    case DW_OP_lit17:  printf ("DW_OP_lit17"); break;
+    case DW_OP_lit18:  printf ("DW_OP_lit18"); break;
+    case DW_OP_lit19:  printf ("DW_OP_lit19"); break;
+    case DW_OP_lit20:  printf ("DW_OP_lit20"); break;
+    case DW_OP_lit21:  printf ("DW_OP_lit21"); break;
+    case DW_OP_lit22:  printf ("DW_OP_lit22"); break;
+    case DW_OP_lit23:  printf ("DW_OP_lit23"); break;
+    case DW_OP_lit24:  printf ("DW_OP_lit24"); break;
+    case DW_OP_lit25:  printf ("DW_OP_lit25"); break;
+    case DW_OP_lit26:  printf ("DW_OP_lit26"); break;
+    case DW_OP_lit27:  printf ("DW_OP_lit27"); break;
+    case DW_OP_lit28:  printf ("DW_OP_lit28"); break;
+    case DW_OP_lit29:  printf ("DW_OP_lit29"); break;
+    case DW_OP_lit30:  printf ("DW_OP_lit30"); break;
+    case DW_OP_lit31:  printf ("DW_OP_lit31"); break;
+    case DW_OP_reg0:   printf ("DW_OP_reg0"); break;
+    case DW_OP_reg1:   printf ("DW_OP_reg1"); break;
+    case DW_OP_reg2:   printf ("DW_OP_reg2"); break;
+    case DW_OP_reg3:   printf ("DW_OP_reg3"); break;
+    case DW_OP_reg4:   printf ("DW_OP_reg4"); break;
+    case DW_OP_reg5:   printf ("DW_OP_reg5"); break;
+    case DW_OP_reg6:   printf ("DW_OP_reg6"); break;
+    case DW_OP_reg7:   printf ("DW_OP_reg7"); break;
+    case DW_OP_reg8:   printf ("DW_OP_reg8"); break;
+    case DW_OP_reg9:   printf ("DW_OP_reg9"); break;
+    case DW_OP_reg10:  printf ("DW_OP_reg10"); break;
+    case DW_OP_reg11:  printf ("DW_OP_reg11"); break;
+    case DW_OP_reg12:  printf ("DW_OP_reg12"); break;
+    case DW_OP_reg13:  printf ("DW_OP_reg13"); break;
+    case DW_OP_reg14:  printf ("DW_OP_reg14"); break;
+    case DW_OP_reg15:  printf ("DW_OP_reg15"); break;
+    case DW_OP_reg16:  printf ("DW_OP_reg16"); break;
+    case DW_OP_reg17:  printf ("DW_OP_reg17"); break;
+    case DW_OP_reg18:  printf ("DW_OP_reg18"); break;
+    case DW_OP_reg19:  printf ("DW_OP_reg19"); break;
+    case DW_OP_reg20:  printf ("DW_OP_reg20"); break;
+    case DW_OP_reg21:  printf ("DW_OP_reg21"); break;
+    case DW_OP_reg22:  printf ("DW_OP_reg22"); break;
+    case DW_OP_reg23:  printf ("DW_OP_reg23"); break;
+    case DW_OP_reg24:  printf ("DW_OP_reg24"); break;
+    case DW_OP_reg25:  printf ("DW_OP_reg25"); break;
+    case DW_OP_reg26:  printf ("DW_OP_reg26"); break;
+    case DW_OP_reg27:  printf ("DW_OP_reg27"); break;
+    case DW_OP_reg28:  printf ("DW_OP_reg28"); break;
+    case DW_OP_reg29:  printf ("DW_OP_reg29"); break;
+    case DW_OP_reg30:  printf ("DW_OP_reg30"); break;
+    case DW_OP_reg31:  printf ("DW_OP_reg31"); break;
+    case DW_OP_breg0:  printf ("DW_OP_breg0: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg1:  printf ("DW_OP_breg1: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg2:  printf ("DW_OP_breg2: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg3:  printf ("DW_OP_breg3: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg4:  printf ("DW_OP_breg4: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg5:  printf ("DW_OP_breg5: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg6:  printf ("DW_OP_breg6: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg7:  printf ("DW_OP_breg7: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg8:  printf ("DW_OP_breg8: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg9:  printf ("DW_OP_breg9: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg10: printf ("DW_OP_breg10: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg11: printf ("DW_OP_breg11: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg12: printf ("DW_OP_breg12: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg13: printf ("DW_OP_breg13: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg14: printf ("DW_OP_breg14: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg15: printf ("DW_OP_breg15: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg16: printf ("DW_OP_breg16: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg17: printf ("DW_OP_breg17: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg18: printf ("DW_OP_breg18: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg19: printf ("DW_OP_breg19: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg20: printf ("DW_OP_breg20: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg21: printf ("DW_OP_breg21: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg22: printf ("DW_OP_breg22: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg23: printf ("DW_OP_breg23: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg24: printf ("DW_OP_breg24: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg25: printf ("DW_OP_breg25: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg26: printf ("DW_OP_breg26: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg27: printf ("DW_OP_breg27: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg28: printf ("DW_OP_breg28: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg29: printf ("DW_OP_breg29: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg30: printf ("DW_OP_breg30: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_breg31: printf ("DW_OP_breg31: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_regx:   printf ("DW_OP_regx: %lu", read_leb128 (data, NULL, 0)); break;
+    case DW_OP_fbreg:  printf ("DW_OP_fbreg: %ld", read_leb128 (data, NULL, 1)); break;
+    case DW_OP_bregx:  printf ("DW_OP_bregx: %lu %ld", read_leb128 (data, & bytes_read, 0), read_leb128 (data + bytes_read, NULL, 1)); break;
+    case DW_OP_piece:  printf ("DW_OP_piece: %lu", read_leb128 (data, NULL, 0)); break;
+    case DW_OP_deref_size:     printf ("DW_OP_deref_size: %ld", byte_get (data, 1)); break;
+    case DW_OP_xderef_size:    printf ("DW_OP_xderef_size: %ld", byte_get (data, 1)); break;
+    case DW_OP_nop:    printf ("DW_OP_nop"); break;
+
+    default:
+      if (op >= DW_OP_lo_user
+         && op <= DW_OP_hi_user)
+       printf (_("(User defined location op)"));
+      else
+       printf (_("(Unknown location op)"));
+      break;
+    }
+}
+
+
+static unsigned char *
+read_and_display_attr (attribute, form, data, pointer_size)
+     unsigned long   attribute;
+     unsigned long   form;
+     unsigned char * data;
+     unsigned long   pointer_size;
+{
+  unsigned long   uvalue;
+  unsigned char * block_start;
+  int             bytes_read;
+  int            is_ref = 0;
+
+  printf ("     %-18s:", get_AT_name (attribute));
+
+  switch (form)
+    {
+    case DW_FORM_ref_addr:
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+      is_ref = 1;
+    }
+
+  switch (form)
+    {
+    case DW_FORM_ref_addr:
+    case DW_FORM_addr:
+      uvalue = byte_get (data, pointer_size);
+      printf (is_ref ? " <%x>" : " %#x", uvalue);
+      data += pointer_size;
+      break;
+
+    case DW_FORM_ref1:
+    case DW_FORM_flag:
+    case DW_FORM_data1:
+      uvalue = byte_get (data ++, 1);
+      printf (is_ref ? " <%x>" : " %d", uvalue);
+      break;
+
+    case DW_FORM_ref2:
+    case DW_FORM_data2:
+      uvalue = byte_get (data, 2);
+      data += 2;
+      printf (is_ref ? " <%x>" : " %d", uvalue);
+      break;
+
+    case DW_FORM_ref4:
+    case DW_FORM_data4:
+      uvalue = byte_get (data, 4);
+      data += 4;
+      printf (is_ref ? " <%x>" : " %d", uvalue);
+      break;
+
+    case DW_FORM_ref8:
+    case DW_FORM_data8:
+      uvalue = byte_get (data, 4);
+      printf (" %lx", uvalue);
+      printf (" %lx", byte_get (data + 4, 4));
+      data += 8;
+      break;
+
+    case DW_FORM_string:
+      printf (" %s", data);
+      data += strlen (data) + 1;
+      break;
+
+    case DW_FORM_sdata:
+      uvalue = read_leb128 (data, & bytes_read, 1);
+      data += bytes_read;
+      printf (" %ld", (long) uvalue);
+      break;
+
+    case DW_FORM_ref_udata:
+    case DW_FORM_udata:
+      uvalue = read_leb128 (data, & bytes_read, 0);
+      data += bytes_read;
+      printf (is_ref ? " <%lx>" : " %ld", uvalue);
+      break;
+
+    case DW_FORM_block:
+      uvalue = read_leb128 (data, & bytes_read, 0);
+      block_start = data + bytes_read;
+      data = display_block (block_start, uvalue);
+      uvalue = * block_start;
+      break;
+
+    case DW_FORM_block1:
+      uvalue = byte_get (data, 1);
+      block_start = data + 1;
+      data = display_block (block_start, uvalue);
+      uvalue = * block_start;
+      break;
+
+    case DW_FORM_block2:
+      uvalue = byte_get (data, 2);
+      block_start = data + 2;
+      data = display_block (block_start, uvalue);
+      uvalue = * block_start;
+      break;
+
+    case DW_FORM_block4:
+      uvalue = byte_get (data, 4);
+      block_start = data + 4;
+      data = display_block (block_start, uvalue);
+      uvalue = * block_start;
+      break;
+
+    case DW_FORM_strp:
+    case DW_FORM_indirect:
+      warn (_("Unable to handle FORM: %d"), form);
+      break;
+
+    default:
+      warn (_("Unrecognised form: %d"), form);
+      break;
+    }
+
+  /* For some attributes we can display futher information.  */
+
+  printf ("\t");
+
+  switch (attribute)
+    {
+    case DW_AT_inline:
+      switch (uvalue)
+       {
+       case DW_INL_not_inlined:          printf (_("(not inlined)")); break;
+       case DW_INL_inlined:              printf (_("(inlined)")); break;
+       case DW_INL_declared_not_inlined: printf (_("(declared as inline but ignored)")); break;
+       case DW_INL_declared_inlined:     printf (_("(declared as inline and inlined)")); break;
+       default: printf (_("  (Unknown inline attribute value: %lx)"), uvalue); break;
+       }
+      break;
+
+    case DW_AT_frame_base:
+      if (uvalue >= DW_OP_reg0 && uvalue <= DW_OP_reg31)
+       printf ("(reg %ld)", uvalue - DW_OP_reg0);
+      break;
+
+    case DW_AT_language:
+      switch (uvalue)
+       {
+       case DW_LANG_C:              printf ("(non-ANSI C)"); break;
+       case DW_LANG_C89:            printf ("(ANSI C)"); break;
+       case DW_LANG_C_plus_plus:    printf ("(C++)"); break;
+       case DW_LANG_Fortran77:      printf ("(FORTRAN 77)"); break;
+       case DW_LANG_Fortran90:      printf ("(Fortran 90)"); break;
+       case DW_LANG_Modula2:        printf ("(Modula 2)"); break;
+       case DW_LANG_Pascal83:       printf ("(ANSI Pascal)"); break;
+       case DW_LANG_Ada83:          printf ("(Ada)"); break;
+       case DW_LANG_Cobol74:        printf ("(Cobol 74)"); break;
+       case DW_LANG_Cobol85:        printf ("(Cobol 85)"); break;
+       case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
+       default:                     printf ("(Unknown: %lx)", uvalue); break;
+       }
+      break;
+
+    case DW_AT_encoding:
+      switch (uvalue)
+       {
+       case DW_ATE_void:            printf ("(void)"); break;
+       case DW_ATE_address:         printf ("(machine address)"); break;
+       case DW_ATE_boolean:         printf ("(boolean)"); break;
+       case DW_ATE_complex_float:   printf ("(complex float)"); break;
+       case DW_ATE_float:           printf ("(float)"); break;
+       case DW_ATE_signed:          printf ("(signed)"); break;
+       case DW_ATE_signed_char:     printf ("(signed char)"); break;
+       case DW_ATE_unsigned:        printf ("(unsigned)"); break;
+       case DW_ATE_unsigned_char:   printf ("(unsigned char)"); break;
+       default:
+         if (uvalue >= DW_ATE_lo_user
+             && uvalue <= DW_ATE_hi_user)
+           printf ("(user defined type)");
+         else
+           printf ("(unknown type)");
+         break;
+       }
+      break;
+
+    case DW_AT_accessibility:
+      switch (uvalue)
+       {
+       case DW_ACCESS_public:          printf ("(public)"); break;
+       case DW_ACCESS_protected:       printf ("(protected)"); break;
+       case DW_ACCESS_private:         printf ("(private)"); break;
+       default:                        printf ("(unknown accessibility)"); break;
+       }
+      break;
+
+    case DW_AT_visibility:
+      switch (uvalue)
+       {
+       case DW_VIS_local:      printf ("(local)"); break;
+       case DW_VIS_exported:   printf ("(exported)"); break;
+       case DW_VIS_qualified:  printf ("(qualified)"); break;
+       default:                printf ("(unknown visibility)"); break;
+       }
+      break;
+
+    case DW_AT_virtuality:
+      switch (uvalue)
+       {
+       case DW_VIRTUALITY_none:        printf ("(none)"); break;
+       case DW_VIRTUALITY_virtual:     printf ("(virtual)"); break;
+       case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
+       default:                        printf ("(unknown virtuality)"); break;
+       }
+      break;
+
+    case DW_AT_identifier_case:
+      switch (uvalue)
+       {
+       case DW_ID_case_sensitive:      printf ("(case_sensitive)"); break;
+       case DW_ID_up_case:             printf ("(up_case)"); break;
+       case DW_ID_down_case:           printf ("(down_case)"); break;
+       case DW_ID_case_insensitive:    printf ("(case_insensitive)"); break;
+       default:                        printf ("(unknown case)"); break;
+       }
+      break;
+
+    case DW_AT_calling_convention:
+      switch (uvalue)
+       {
+       case DW_CC_normal:      printf ("(normal)"); break;
+       case DW_CC_program:     printf ("(program)"); break;
+       case DW_CC_nocall:      printf ("(nocall)"); break;
+       default:
+         if (uvalue >= DW_CC_lo_user
+             && uvalue <= DW_CC_hi_user)
+           printf ("(user defined)");
+         else
+           printf ("(unknown convention)");
+       }
+      break;
+
+    case DW_AT_location:
+    case DW_AT_data_member_location:
+    case DW_AT_vtable_elem_location:
+      printf ("(");
+      decode_location_expression (block_start, pointer_size);
+      printf (")");
+      break;
+
+    default:
+      break;
+    }
+
+  printf ("\n");
+  return data;
+}
+
+static int
+display_debug_info (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file;
+{
+  unsigned char * end = start + section->sh_size;
+  unsigned char * section_begin = start;
+
+  printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
+
+  while (start < end)
+    {
+      DWARF2_External_CompUnit * external;
+      DWARF2_Internal_CompUnit   compunit;
+      unsigned char *            tags;
+      int                        i;
+      int                       level;
+
+      external = (DWARF2_External_CompUnit *) start;
+
+      compunit.cu_length        = BYTE_GET (external->cu_length);
+      compunit.cu_version       = BYTE_GET (external->cu_version);
+      compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset);
+      compunit.cu_pointer_size  = BYTE_GET (external->cu_pointer_size);
+
+      tags = start + sizeof (* external);
+      start += compunit.cu_length + sizeof (external->cu_length);
+
+      if (compunit.cu_version != 2)
+       {
+         warn (_("Only version 2 DWARF debug information is currently supported.\n"));
+         continue;
+       }
+
+      printf (_("  Compilation Unit:\n"));
+      printf (_("   Length:        %ld\n"), compunit.cu_length);
+      printf (_("   Version:       %d\n"), compunit.cu_version);
+      printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
+      printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
+
+      if (first_abbrev != NULL)
+       free_abbrevs ();
+
+      /* Read in the abbrevs used by this compilation unit.  */
+
+      {
+       Elf32_Internal_Shdr * sec;
+       unsigned char *       begin;
+
+       /* Locate the .debug_abbrev section and process it.  */
+       for (i = 0, sec = section_headers;
+            i < elf_header.e_shnum;
+            i ++, sec ++)
+         if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0)
+           break;
+
+       if (i == -1 || sec->sh_size == 0)
+         {
+           warn (_("Unable to locate .debug_abbrev section!\n"));
+           return 0;
+         }
+
+       GET_DATA_ALLOC (sec->sh_offset, sec->sh_size, begin, unsigned char *,
+                       "debug_abbrev section data");
+
+       process_abbrev_section (begin + compunit.cu_abbrev_offset,
+                               begin + sec->sh_size);
+
+       free (begin);
+      }
+
+      level = 0;
+      while (tags < start)
+       {
+         int            bytes_read;
+         int            abbrev_number;
+         abbrev_entry * entry;
+         abbrev_attr  * attr;
+
+         abbrev_number = read_leb128 (tags, & bytes_read, 0);
+         tags += bytes_read;
+
+         /* A null DIE marks the end of a list of children.  */
+         if (abbrev_number == 0)
+           {
+             --level;
+             continue;
+           }
+
+         /* Scan through the abbreviation list until we reach the
+            correct entry.  */
+         for (entry = first_abbrev;
+              entry && entry->entry != abbrev_number;
+              entry = entry->next)
+           continue;
+
+         if (entry == NULL)
+           {
+             warn (_("Unable to locate entry %d in the abbreviation table\n"),
+                   abbrev_number);
+             return 0;
+           }
+
+         printf (_(" <%d><%x>: Abbrev Number: %d (%s)\n"),
+                 level, tags - section_begin - bytes_read,
+                 abbrev_number,
+                 get_TAG_name (entry->tag));
+
+         for (attr = entry->first_attr; attr; attr = attr->next)
+           tags = read_and_display_attr (attr->attribute,
+                                         attr->form,
+                                         tags,
+                                         compunit.cu_pointer_size);
+
+         if (entry->children)
+           ++level;
+       }
+    }
+
+  printf ("\n");
+
+  return 1;
+}
+
+static int
+display_debug_aranges (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file;
+{
+  unsigned char * end = start + section->sh_size;
+
+  printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
+
+  while (start < end)
+    {
+      DWARF2_External_ARange * external;
+      DWARF2_Internal_ARange   arange;
+      unsigned char *          ranges;
+      unsigned long            length;
+      unsigned long            address;
+
+      external = (DWARF2_External_ARange *) start;
+
+      arange.ar_length       = BYTE_GET (external->ar_length);
+      arange.ar_version      = BYTE_GET (external->ar_version);
+      arange.ar_info_offset  = BYTE_GET (external->ar_info_offset);
+      arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size);
+      arange.ar_segment_size = BYTE_GET (external->ar_segment_size);
+
+      printf (_("  Length:                   %ld\n"), arange.ar_length);
+      printf (_("  Version:                  %d\n"), arange.ar_version);
+      printf (_("  Offset into .debug_info:  %lx\n"), arange.ar_info_offset);
+      printf (_("  Pointer Size:             %d\n"), arange.ar_pointer_size);
+      printf (_("  Segment Size:             %d\n"), arange.ar_segment_size);
+
+      printf (_("\n    Address  Length\n"));
+
+      ranges = start + sizeof (* external);
+
+      for (;;)
+       {
+         address = byte_get (ranges, arange.ar_pointer_size);
+
+         if (address == 0)
+           break;
+
+         ranges += arange.ar_pointer_size;
+
+         length  = byte_get (ranges, arange.ar_pointer_size);
+
+         ranges += arange.ar_pointer_size;
+
+         printf ("    %8.8lx %lu\n", address, length);
+       }
+
+      start += arange.ar_length + sizeof (external->ar_length);
+    }
+
+  printf ("\n");
+
+  return 1;
+}
+
+
+static int
+display_debug_not_supported (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file;
+{
+  printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
+           SECTION_NAME (section));
+
+  return 1;
+}
+
+  /* A structure containing the name of a debug section and a pointer
+     to a function that can decode it.  */
+struct
+{
+  char * name;
+  int (* display) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+}
+debug_displays[] =
+{
+  { ".debug_info",        display_debug_info },
+  { ".debug_abbrev",      display_debug_abbrev },
+  { ".debug_line",        display_debug_lines },
+  { ".debug_aranges",     display_debug_aranges },
+  { ".debug_pubnames",    display_debug_pubnames },
+  { ".debug_macinfo",     display_debug_not_supported },
+  { ".debug_frame",       display_debug_not_supported },
+  { ".debug_str",         display_debug_not_supported },
+  { ".debug_static_func", display_debug_not_supported },
+  { ".debug_static_vars", display_debug_not_supported },
+  { ".debug_types",       display_debug_not_supported },
+  { ".debug_weaknames",   display_debug_not_supported }
+};
+
+static int
+display_debug_section (section, file)
+     Elf32_Internal_Shdr * section;
+     FILE * file;
+{
+  char *          name = SECTION_NAME (section);
+  bfd_size_type   length;
+  unsigned char * start;
+  int             i;
+
+  length = section->sh_size;
+  if (length == 0)
+    {
+      printf (_("\nSection '%s' has no debugging data.\n"), name);
+      return 0;
+    }
+
+  GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *,
+                 "debug section data");
+
+  /* See if we know how to display the contents of this section.  */
+  for (i = NUM_ELEM (debug_displays); i--;)
+    if (strcmp (debug_displays[i].name, name) == 0)
+      {
+       debug_displays[i].display (section, start, file);
+       break;
+      }
+
+  if (i == -1)
+    printf (_("Unrecognised debug section: %s\n"), name);
+
+  free (start);
+
+  /* If we loaded in the abbrev section at some point,
+     we must release it here.  */
+  if (first_abbrev != NULL)
+    free_abbrevs ();
+
+  return 1;
+}
+
+static int
+process_section_contents (file)
+     FILE * file;
+{
+  Elf32_Internal_Shdr *    section;
+  unsigned int  i;
+
+  if (! do_dump)
+    return 1;
+
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum
+       && i < num_dump_sects;
+       i ++, section ++)
+    {
+#ifdef SUPPORT_DISASSEMBLY
+      if (dump_sects[i] & DISASS_DUMP)
+       disassemble_section (section, file);
+#endif
+      if (dump_sects[i] & HEX_DUMP)
+       dump_section (section, file);
+
+      if (dump_sects[i] & DEBUG_DUMP)
+       display_debug_section (section, file);
+    }
+
+  if (i < num_dump_sects)
+    warn (_("Some sections were not dumped because they do not exist!\n"));
+
+  return 1;
+}
+
+static void
+process_mips_fpe_exception (mask)
+     int mask;
+{
+  if (mask)
+    {
+      int first = 1;
+      if (mask & OEX_FPU_INEX)
+       fputs ("INEX", stdout), first = 0;
+      if (mask & OEX_FPU_UFLO)
+       printf ("%sUFLO", first ? "" : "|"), first = 0;
+      if (mask & OEX_FPU_OFLO)
+       printf ("%sOFLO", first ? "" : "|"), first = 0;
+      if (mask & OEX_FPU_DIV0)
+       printf ("%sDIV0", first ? "" : "|"), first = 0;
+      if (mask & OEX_FPU_INVAL)
+       printf ("%sINVAL", first ? "" : "|");
+    }
+  else
+    fputs ("0", stdout);
+}
+
+static int
+process_mips_specific (file)
+     FILE *file;
+{
+  Elf_Internal_Dyn *entry;
+  size_t liblist_offset = 0;
+  size_t liblistno = 0;
+  size_t conflictsno = 0;
+  size_t options_offset = 0;
+  size_t conflicts_offset = 0;
+
+  /* We have a lot of special sections.  Thanks SGI!  */
+  if (dynamic_segment == NULL)
+    /* No information available.  */
+    return 0;
+
+  for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
+    switch (entry->d_tag)
+      {
+      case DT_MIPS_LIBLIST:
+       liblist_offset = entry->d_un.d_val - loadaddr;
+       break;
+      case DT_MIPS_LIBLISTNO:
+       liblistno = entry->d_un.d_val;
+       break;
+      case DT_MIPS_OPTIONS:
+       options_offset = entry->d_un.d_val - loadaddr;
+       break;
+      case DT_MIPS_CONFLICT:
+       conflicts_offset = entry->d_un.d_val - loadaddr;
+       break;
+      case DT_MIPS_CONFLICTNO:
+       conflictsno = entry->d_un.d_val;
+       break;
+      default:
+       break;
+      }
+
+  if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
+    {
+      Elf32_External_Lib *elib;
+      size_t cnt;
+
+      GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib),
+                     elib, Elf32_External_Lib *, "liblist");
+
+      printf ("\nSection '.liblist' contains %d entries:\n", liblistno);
+      fputs ("     Library              Time Stamp          Checksum   Version Flags\n",
+            stdout);
+
+      for (cnt = 0; cnt < liblistno; ++cnt)
+       {
+         Elf32_Lib liblist;
+         time_t time;
+         char timebuf[20];
+
+         liblist.l_name = BYTE_GET (elib[cnt].l_name);
+         time = BYTE_GET (elib[cnt].l_time_stamp);
+         liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
+         liblist.l_version = BYTE_GET (elib[cnt].l_version);
+         liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
+
+         strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
+
+         printf ("%3d: %-20s %s %#10lx %-7ld", cnt,
+                 dynamic_strings + liblist.l_name, timebuf,
+                 liblist.l_checksum, liblist.l_version);
+
+         if (liblist.l_flags == 0)
+           puts (" NONE");
+         else
+           {
+             static const struct
+             {
+               const char *name;
+               int bit;
+             } l_flags_vals[] =
+               {
+                 { " EXACT_MATCH", LL_EXACT_MATCH },
+                 { " IGNORE_INT_VER", LL_IGNORE_INT_VER },
+                 { " REQUIRE_MINOR", LL_REQUIRE_MINOR },
+                 { " EXPORTS", LL_EXPORTS },
+                 { " DELAY_LOAD", LL_DELAY_LOAD },
+                 { " DELTA", LL_DELTA }
+               };
+             int flags = liblist.l_flags;
+             int fcnt;
+
+             for (fcnt = 0;
+                  fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]);
+                  ++fcnt)
+               if ((flags & l_flags_vals[fcnt].bit) != 0)
+                 {
+                   fputs (l_flags_vals[fcnt].name, stdout);
+                   flags ^= l_flags_vals[fcnt].bit;
+                 }
+             if (flags != 0)
+               printf (" %#x", (unsigned int) flags);
+
+             puts ("");
+           }
+       }
+
+      free (elib);
+    }
+
+  if (options_offset != 0)
+    {
+      Elf_External_Options *eopt;
+      Elf_Internal_Shdr *sect = section_headers;
+      Elf_Internal_Options *iopt;
+      Elf_Internal_Options *option;
+      size_t offset;
+      int cnt;
+
+      /* Find the section header so that we get the size.  */
+      while (sect->sh_type != SHT_MIPS_OPTIONS)
+       ++sect;
+
+      GET_DATA_ALLOC (options_offset, sect->sh_size, eopt,
+                     Elf_External_Options *, "options");
+
+      iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
+                                             * sizeof (*iopt));
+      if (iopt == NULL)
+       {
+         error (_("Out of memory"));
+         return 0;
+       }
+
+      offset = cnt = 0;
+      option = iopt;
+      while (offset < sect->sh_size)
+       {
+         Elf_External_Options *eoption;
+
+         eoption = (Elf_External_Options *) ((char *) eopt + offset);
+
+         option->kind = BYTE_GET (eoption->kind);
+         option->size = BYTE_GET (eoption->size);
+         option->section = BYTE_GET (eoption->section);
+         option->info = BYTE_GET (eoption->info);
+
+         offset += option->size;
+         ++option;
+         ++cnt;
+       }
+
+      printf (_("\nSection '%s' contains %d entries:\n"),
+             string_table + sect->sh_name, cnt);
+
+      option = iopt;
+      while (cnt-- > 0)
+       {
+         size_t len;
+
+         switch (option->kind)
+           {
+           case ODK_NULL:
+             /* This shouldn't happen.  */
+             printf (" NULL       %d %lx", option->section, option->info);
+             break;
+           case ODK_REGINFO:
+             printf (" REGINFO    ");
+             if (elf_header.e_machine == EM_MIPS)
+               {
+                 /* 32bit form.  */
+                 Elf32_External_RegInfo *ereg;
+                 Elf32_RegInfo reginfo;
+
+                 ereg = (Elf32_External_RegInfo *) (option + 1);
+                 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
+                 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
+                 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
+                 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
+                 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
+                 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
+
+                 printf ("GPR %08lx  GP 0x%lx\n",
+                         reginfo.ri_gprmask,
+                         (unsigned long) reginfo.ri_gp_value);
+                 printf ("            CPR0 %08lx  CPR1 %08lx  CPR2 %08lx  CPR3 %08lx\n",
+                         reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
+                         reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
+               }
+             else
+               {
+                 /* 64 bit form.  */
+                 Elf64_External_RegInfo *ereg;
+                 Elf64_Internal_RegInfo reginfo;
+
+                 ereg = (Elf64_External_RegInfo *) (option + 1);
+                 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
+                 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
+                 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
+                 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
+                 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
+                 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
+
+                 printf ("GPR %08lx  GP 0x",
+                         reginfo.ri_gprmask);
+                 printf_vma (reginfo.ri_gp_value);
+                 printf ("\n");
+
+                 printf ("            CPR0 %08lx  CPR1 %08lx  CPR2 %08lx  CPR3 %08lx\n",
+                         reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
+                         reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
+               }
+             ++option;
+             continue;
+           case ODK_EXCEPTIONS:
+             fputs (" EXCEPTIONS fpe_min(", stdout);
+             process_mips_fpe_exception (option->info & OEX_FPU_MIN);
+             fputs (") fpe_max(", stdout);
+             process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
+             fputs (")", stdout);
+
+             if (option->info & OEX_PAGE0)
+               fputs (" PAGE0", stdout);
+             if (option->info & OEX_SMM)
+               fputs (" SMM", stdout);
+             if (option->info & OEX_FPDBUG)
+               fputs (" FPDBUG", stdout);
+             if (option->info & OEX_DISMISS)
+               fputs (" DISMISS", stdout);
+             break;
+           case ODK_PAD:
+             fputs (" PAD       ", stdout);
+             if (option->info & OPAD_PREFIX)
+               fputs (" PREFIX", stdout);
+             if (option->info & OPAD_POSTFIX)
+               fputs (" POSTFIX", stdout);
+             if (option->info & OPAD_SYMBOL)
+               fputs (" SYMBOL", stdout);
+             break;
+           case ODK_HWPATCH:
+             fputs (" HWPATCH   ", stdout);
+             if (option->info & OHW_R4KEOP)
+               fputs (" R4KEOP", stdout);
+             if (option->info & OHW_R8KPFETCH)
+               fputs (" R8KPFETCH", stdout);
+             if (option->info & OHW_R5KEOP)
+               fputs (" R5KEOP", stdout);
+             if (option->info & OHW_R5KCVTL)
+               fputs (" R5KCVTL", stdout);
+             break;
+           case ODK_FILL:
+             fputs (" FILL       ", stdout);
+             /* XXX Print content of info word?  */
+             break;
+           case ODK_TAGS:
+             fputs (" TAGS       ", stdout);
+             /* XXX Print content of info word?  */
+             break;
+           case ODK_HWAND:
+             fputs (" HWAND     ", stdout);
+             if (option->info & OHWA0_R4KEOP_CHECKED)
+               fputs (" R4KEOP_CHECKED", stdout);
+             if (option->info & OHWA0_R4KEOP_CLEAN)
+               fputs (" R4KEOP_CLEAN", stdout);
+             break;
+           case ODK_HWOR:
+             fputs (" HWOR      ", stdout);
+             if (option->info & OHWA0_R4KEOP_CHECKED)
+               fputs (" R4KEOP_CHECKED", stdout);
+             if (option->info & OHWA0_R4KEOP_CLEAN)
+               fputs (" R4KEOP_CLEAN", stdout);
+             break;
+           case ODK_GP_GROUP:
+             printf (" GP_GROUP  %#06lx  self-contained %#06lx",
+                     option->info & OGP_GROUP,
+                     (option->info & OGP_SELF) >> 16);
+             break;
+           case ODK_IDENT:
+             printf (" IDENT     %#06lx  self-contained %#06lx",
+                     option->info & OGP_GROUP,
+                     (option->info & OGP_SELF) >> 16);
+             break;
+           default:
+             /* This shouldn't happen.  */
+             printf (" %3d ???     %d %lx",
+                     option->kind, option->section, option->info);
+             break;
+           }
+
+         len = sizeof (*eopt);
+         while (len < option->size)
+           if (((char *) option)[len] >= ' '
+               && ((char *) option)[len] < 0x7f)
+             printf ("%c", ((char *) option)[len++]);
+           else
+             printf ("\\%03o", ((char *) option)[len++]);
+
+         fputs ("\n", stdout);
+         ++option;
+       }
+
+      free (eopt);
+    }
+
+  if (conflicts_offset != 0 && conflictsno != 0)
+    {
+      Elf32_External_Conflict *econf32;
+      Elf64_External_Conflict *econf64;
+      Elf32_Conflict *iconf;
+      size_t cnt;
+
+      if (dynamic_symbols == NULL)
+       {
+         error (_("conflict list with without table"));
+         return 0;
+       }
+
+      iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (*iconf));
+      if (iconf == NULL)
+       {
+         error (_("Out of memory"));
+         return 0;
+       }
+
+      if (binary_class == ELFCLASS32)
+       {
+         GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf32),
+                         econf32, Elf32_External_Conflict *, "conflict");
+
+         for (cnt = 0; cnt < conflictsno; ++cnt)
+           iconf[cnt] = BYTE_GET (econf32[cnt]);
+       }
+      else
+       {
+         GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf64),
+                         econf64, Elf64_External_Conflict *, "conflict");
+
+         for (cnt = 0; cnt < conflictsno; ++cnt)
+           iconf[cnt] = BYTE_GET (econf64[cnt]);
+       }
+
+      printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno);
+      puts (_("  Num:    Index       Value  Name"));
+
+      for (cnt = 0; cnt < conflictsno; ++cnt)
+       {
+         Elf_Internal_Sym *psym = &dynamic_symbols[iconf[cnt]];
+
+         printf ("%5u: %8lu  %#10lx  %s\n",
+                 cnt, iconf[cnt], (unsigned long) psym->st_value,
+                 dynamic_strings + psym->st_name);
+       }
+
+
+      free (iconf);
+    }
+
+  return 1;
+}
+
+static int
+process_arch_specific (file)
+     FILE *file;
+{
+  switch (elf_header.e_machine)
+    {
+    case EM_MIPS:
+    case EM_MIPS_RS4_BE:
+      return process_mips_specific (file);
+      break;
+    default:
+      break;
+    }
+  return 1;
+}
+
+static int
+get_file_header (file)
+     FILE * file;
+{
+  Elf32_External_Ehdr ehdr;
+
+  if (fread (& ehdr, sizeof (ehdr), 1, file) != 1)
+    return 0;
+
+  memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT);
+
+  if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB)
+    byte_get = byte_get_little_endian;
+  else
+    byte_get = byte_get_big_endian;
+
+  elf_header.e_entry     = BYTE_GET (ehdr.e_entry);
+  elf_header.e_phoff     = BYTE_GET (ehdr.e_phoff);
+  elf_header.e_shoff     = BYTE_GET (ehdr.e_shoff);
+  elf_header.e_version   = BYTE_GET (ehdr.e_version);
+  elf_header.e_flags     = BYTE_GET (ehdr.e_flags);
+  elf_header.e_type      = BYTE_GET (ehdr.e_type);
+  elf_header.e_machine   = BYTE_GET (ehdr.e_machine);
+  elf_header.e_ehsize    = BYTE_GET (ehdr.e_ehsize);
+  elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize);
+  elf_header.e_phnum     = BYTE_GET (ehdr.e_phnum);
+  elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize);
+  elf_header.e_shnum     = BYTE_GET (ehdr.e_shnum);
+  elf_header.e_shstrndx  = BYTE_GET (ehdr.e_shstrndx);
+
+  return 1;
+}
+
+static void
+process_file (file_name)
+     char * file_name;
+{
+  FILE *       file;
+  struct stat  statbuf;
+  unsigned int i;
+
+  if (stat (file_name, & statbuf) < 0)
+    {
+      error (_("Cannot stat input file %s.\n"), file_name);
+      return;
+    }
+
+  file = fopen (file_name, "rb");
+  if (file == NULL)
+    {
+      error (_("Input file %s not found.\n"), file_name);
+      return;
+    }
+
+  if (! get_file_header (file))
+    {
+      error (_("%s: Failed to read file header\n"), file_name);
+      fclose (file);
+      return;
+    }
+
+  /* Initialise per file variables.  */
+  for (i = NUM_ELEM (version_info); i--;)
+    version_info[i] = 0;
+
+  for (i = NUM_ELEM (dynamic_info); i--;)
+    dynamic_info[i] = 0;
+
+  /* Process the file.  */
+  if (show_name)
+    printf (_("\nFile: %s\n"), file_name);
+
+  if (! process_file_header ())
+    {
+      fclose (file);
+      return;
+    }
+
+  process_section_headers (file);
+
+  process_program_headers (file);
+
+  process_dynamic_segment (file);
+
+  process_relocs (file);
+
+  process_symbol_table (file);
+
+  process_syminfo (file);
+
+  process_version_sections (file);
+
+  process_section_contents (file);
+
+  process_arch_specific (file);
+
+  fclose (file);
+
+  if (section_headers)
+    {
+      free (section_headers);
+      section_headers = NULL;
+    }
+
+  if (string_table)
+    {
+      free (string_table);
+      string_table = NULL;
+    }
+
+  if (dynamic_strings)
+    {
+      free (dynamic_strings);
+      dynamic_strings = NULL;
+    }
+
+  if (dynamic_symbols)
+    {
+      free (dynamic_symbols);
+      dynamic_symbols = NULL;
+    }
+
+  if (dynamic_syminfo)
+    {
+      free (dynamic_syminfo);
+      dynamic_syminfo = NULL;
+    }
+}
+
+#ifdef SUPPORT_DISASSEMBLY
+/* Needed by the i386 disassembler.  For extra credit, someone could
+fix this so that we insert symbolic addresses here, esp for GOT/PLT
+symbols */
+
+void
+print_address (unsigned int addr, FILE * outfile)
+{
+  fprintf (outfile,"0x%8.8x", addr);
+}
+
+/* Needed by the i386 disassembler. */
+void
+db_task_printsym (unsigned int addr)
+{
+  print_address (addr, stderr);
+}
+#endif
+
+int
+main (argc, argv)
+     int     argc;
+     char ** argv;
+{
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  parse_args (argc, argv);
+
+  if (optind < (argc - 1))
+    show_name = 1;
+
+  while (optind < argc)
+    process_file (argv [optind ++]);
+
+  if (dump_sects != NULL)
+    free (dump_sects);
+
+  return 0;
+}
diff --git a/binutils/rename.c b/binutils/rename.c
new file mode 100644 (file)
index 0000000..fdc7263
--- /dev/null
@@ -0,0 +1,210 @@
+/* rename.c -- rename a file, preserving symlinks.
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+
+#include <sys/stat.h>
+
+#ifdef HAVE_GOOD_UTIME_H
+#include <utime.h>
+#else /* ! HAVE_GOOD_UTIME_H */
+#ifdef HAVE_UTIMES
+#include <sys/time.h>
+#endif /* HAVE_UTIMES */
+#endif /* ! HAVE_GOOD_UTIME_H */
+
+static int simple_copy PARAMS ((const char *, const char *));
+
+/* The number of bytes to copy at once.  */
+#define COPY_BUF 8192
+
+/* Copy file FROM to file TO, performing no translations.
+   Return 0 if ok, -1 if error.  */
+
+static int
+simple_copy (from, to)
+     const char *from;
+     const char *to;
+{
+  int fromfd, tofd, nread;
+  int saved;
+  char buf[COPY_BUF];
+
+  fromfd = open (from, O_RDONLY);
+  if (fromfd < 0)
+    return -1;
+  tofd = creat (to, 0777);
+  if (tofd < 0)
+    {
+      saved = errno;
+      close (fromfd);
+      errno = saved;
+      return -1;
+    }
+  while ((nread = read (fromfd, buf, sizeof buf)) > 0)
+    {
+      if (write (tofd, buf, nread) != nread)
+       {
+         saved = errno;
+         close (fromfd);
+         close (tofd);
+         errno = saved;
+         return -1;
+       }
+    }
+  saved = errno;
+  close (fromfd);
+  close (tofd);
+  if (nread < 0)
+    {
+      errno = saved;
+      return -1;
+    }
+  return 0;
+}
+
+/* Set the times of the file DESTINATION to be the same as those in
+   STATBUF.  */
+
+void
+set_times (destination, statbuf)
+     const char *destination;
+     const struct stat *statbuf;
+{
+  int result;
+
+  {
+#ifdef HAVE_GOOD_UTIME_H
+    struct utimbuf tb;
+
+    tb.actime = statbuf->st_atime;
+    tb.modtime = statbuf->st_mtime;
+    result = utime (destination, &tb);
+#else /* ! HAVE_GOOD_UTIME_H */
+#ifndef HAVE_UTIMES
+    long tb[2];
+
+    tb[0] = statbuf->st_atime;
+    tb[1] = statbuf->st_mtime;
+    result = utime (destination, tb);
+#else /* HAVE_UTIMES */
+    struct timeval tv[2];
+
+    tv[0].tv_sec = statbuf->st_atime;
+    tv[0].tv_usec = 0;
+    tv[1].tv_sec = statbuf->st_mtime;
+    tv[1].tv_usec = 0;
+    result = utimes (destination, tv);
+#endif /* HAVE_UTIMES */
+#endif /* ! HAVE_GOOD_UTIME_H */
+  }
+
+  if (result != 0)
+    non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno));
+}
+
+#ifndef S_ISLNK
+#ifdef S_IFLNK
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#else
+#define S_ISLNK(m) 0
+#define lstat stat
+#endif
+#endif
+
+/* Rename FROM to TO, copying if TO is a link.
+   Return 0 if ok, -1 if error.  */
+
+int
+smart_rename (from, to, preserve_dates)
+     const char *from;
+     const char *to;
+     int preserve_dates;
+{
+  int exists;
+  struct stat s;
+  int ret = 0;
+
+  exists = lstat (to, &s);
+
+#if defined (_WIN32) && !defined (__CYGWIN32__)
+  /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but
+     fail instead.  Also, chown is not present.  */
+
+  if (exists == 0)
+    remove (to);
+
+  ret = rename (from, to);
+  if (ret != 0)
+    {
+      /* We have to clean up here. */
+      
+      non_fatal (_("%s: rename: %s"), to, strerror (errno));
+      unlink (from);
+    }
+#else
+  /* Use rename only if TO is not a symbolic link and has
+     only one hard link.  */
+  if (exists < 0 || (!S_ISLNK (s.st_mode) && s.st_nlink == 1))
+    {
+      ret = rename (from, to);
+      if (ret == 0)
+       {
+         if (exists)
+           {
+             /* Try to preserve the permission bits and ownership of
+                TO.  First get the mode right except for the setuid
+                bit.  Then change the ownership.  Then fix the setuid
+                bit.  We do the chmod before the chown because if the
+                chown succeeds, and we are a normal user, we won't be
+                able to do the chmod afterward.  We don't bother to
+                fix the setuid bit first because that might introduce
+                a fleeting security problem, and because the chown
+                will clear the setuid bit anyhow.  We only fix the
+                setuid bit if the chown succeeds, because we don't
+                want to introduce an unexpected setuid file owned by
+                the user running objcopy.  */
+             chmod (to, s.st_mode & 0777);
+             if (chown (to, s.st_uid, s.st_gid) >= 0)
+               chmod (to, s.st_mode & 07777);
+           }
+       }
+      else
+       {
+         /* We have to clean up here. */
+         non_fatal (_("%s: rename: %s"), to, strerror (errno));
+         unlink (from);
+       }
+    }
+  else
+    {
+      ret = simple_copy (from, to);
+      if (ret != 0)
+       non_fatal (_("%s: simple_copy: %s"), to, strerror (errno));
+
+      if (preserve_dates)
+       set_times (to, &s);
+      unlink (from);
+    }
+#endif /* _WIN32 && !__CYGWIN32__ */
+
+  return ret;
+}
diff --git a/binutils/resbin.c b/binutils/resbin.c
new file mode 100644 (file)
index 0000000..8fc07fb
--- /dev/null
@@ -0,0 +1,2387 @@
+/* resbin.c -- manipulate the Windows binary resource format.
+   Copyright 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file contains functions to convert between the binary resource
+   format and the internal structures that we want to use.  The same
+   binary resource format is used in both res and COFF files.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "windres.h"
+
+/* Macros to swap in values.  */
+
+#define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s))
+#define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s))
+
+/* Local functions.  */
+
+static void toosmall PARAMS ((const char *));
+static unichar *get_unicode
+  PARAMS ((const unsigned char *, unsigned long, int, int *));
+static int get_resid
+  PARAMS ((struct res_id *, const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_generic
+  PARAMS ((enum res_type, const unsigned char *, unsigned long));
+static struct res_resource *bin_to_res_cursor
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_menu
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct menuitem *bin_to_res_menuitems
+  PARAMS ((const unsigned char *, unsigned long, int, int *));
+static struct menuitem *bin_to_res_menuexitems
+  PARAMS ((const unsigned char *, unsigned long, int, int *));
+static struct res_resource *bin_to_res_dialog
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_string
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_fontdir
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_accelerators
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_rcdata
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_group_cursor
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_group_icon
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_version
+  PARAMS ((const unsigned char *, unsigned long, int));
+static struct res_resource *bin_to_res_userdata
+  PARAMS ((const unsigned char *, unsigned long, int));
+
+/* Given a resource type ID, a pointer to data, a length, return a
+   res_resource structure which represents that resource.  The caller
+   is responsible for initializing the res_info and coff_info fields
+   of the returned structure.  */
+
+struct res_resource *
+bin_to_res (type, data, length, big_endian)
+     struct res_id type;
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  if (type.named)
+    return bin_to_res_userdata (data, length, big_endian);
+  else
+    {
+      switch (type.u.id)
+       {
+       default:
+         return bin_to_res_userdata (data, length, big_endian);
+       case RT_CURSOR:
+         return bin_to_res_cursor (data, length, big_endian);
+       case RT_BITMAP:
+         return bin_to_res_generic (RES_TYPE_BITMAP, data, length);
+       case RT_ICON:
+         return bin_to_res_generic (RES_TYPE_ICON, data, length);
+       case RT_MENU:
+         return bin_to_res_menu (data, length, big_endian);
+       case RT_DIALOG:
+         return bin_to_res_dialog (data, length, big_endian);
+       case RT_STRING:
+         return bin_to_res_string (data, length, big_endian);
+       case RT_FONTDIR:
+         return bin_to_res_fontdir (data, length, big_endian);
+       case RT_FONT:
+         return bin_to_res_generic (RES_TYPE_FONT, data, length);
+       case RT_ACCELERATOR:
+         return bin_to_res_accelerators (data, length, big_endian);
+       case RT_RCDATA:
+         return bin_to_res_rcdata (data, length, big_endian);
+       case RT_MESSAGETABLE:
+         return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length);
+       case RT_GROUP_CURSOR:
+         return bin_to_res_group_cursor (data, length, big_endian);
+       case RT_GROUP_ICON:
+         return bin_to_res_group_icon (data, length, big_endian);
+       case RT_VERSION:
+         return bin_to_res_version (data, length, big_endian);
+       }
+    }
+}
+
+/* Give an error if the binary data is too small.  */
+
+static void
+toosmall (msg)
+     const char *msg;
+{
+  fatal (_("%s: not enough binary data"), msg);
+}
+
+/* Swap in a NULL terminated unicode string.  */
+
+static unichar *
+get_unicode (data, length, big_endian, retlen)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+     int *retlen;
+{
+  int c, i;
+  unichar *ret;
+
+  c = 0;
+  while (1)
+    {
+      if (length < (unsigned long) c * 2 + 2)
+       toosmall (_("null terminated unicode string"));
+      if (get_16 (big_endian, data + c * 2) == 0)
+       break;
+      ++c;
+    }
+
+  ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
+
+  for (i = 0; i < c; i++)
+    ret[i] = get_16 (big_endian, data + i * 2);
+  ret[i] = 0;
+
+  if (retlen != NULL)
+    *retlen = c;
+
+  return ret;
+}
+
+/* Get a resource identifier.  This returns the number of bytes used.  */
+
+static int
+get_resid (id, data, length, big_endian)
+     struct res_id *id;
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  int first;
+
+  if (length < 2)
+    toosmall (_("resource ID"));
+
+  first = get_16 (big_endian, data);
+  if (first == 0xffff)
+    {
+      if (length < 4)
+       toosmall (_("resource ID"));
+      id->named = 0;
+      id->u.id = get_16 (big_endian, data + 2);
+      return 4;
+    }
+  else
+    {
+      id->named = 1;
+      id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length);
+      return id->u.n.length * 2 + 2;
+    }
+}
+
+/* Convert a resource which just stores uninterpreted data from
+   binary.  */
+
+struct res_resource *
+bin_to_res_generic (type, data, length)
+     enum res_type type;
+     const unsigned char *data;
+     unsigned long length;
+{
+  struct res_resource *r;
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = type;
+  r->u.data.data = data;
+  r->u.data.length = length;
+
+  return r;
+}
+
+/* Convert a cursor resource from binary.  */
+
+struct res_resource *
+bin_to_res_cursor (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  struct cursor *c;
+  struct res_resource *r;
+
+  if (length < 4)
+    toosmall (_("cursor"));
+
+  c = (struct cursor *) res_alloc (sizeof *c);
+  c->xhotspot = get_16 (big_endian, data);
+  c->yhotspot = get_16 (big_endian, data + 2);
+  c->length = length - 4;
+  c->data = data + 4;
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_CURSOR;
+  r->u.cursor = c;
+
+  return r;
+}
+
+/* Convert a menu resource from binary.  */
+
+struct res_resource *
+bin_to_res_menu (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  struct res_resource *r;
+  struct menu *m;
+  int version, read;
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_MENU;
+
+  m = (struct menu *) res_alloc (sizeof *m);
+  r->u.menu = m;
+
+  if (length < 2)
+    toosmall (_("menu header"));
+
+  version = get_16 (big_endian, data);
+
+  if (version == 0)
+    {
+      if (length < 4)
+       toosmall (_("menu header"));
+      m->help = 0;
+      m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian,
+                                      &read);
+    }
+  else if (version == 1)
+    {
+      unsigned int offset;
+
+      if (length < 8)
+       toosmall (_("menuex header"));
+      m->help = get_32 (big_endian, data + 4);
+      offset = get_16 (big_endian, data + 2);
+      if (offset + 4 >= length)
+       toosmall (_("menuex offset"));
+      m->items = bin_to_res_menuexitems (data + 4 + offset,
+                                        length - (4 + offset),
+                                        big_endian,
+                                        &read);
+    }
+  else
+    fatal (_("unsupported menu version %d"), version);
+
+  return r;
+}
+
+/* Convert menu items from binary.  */
+
+static struct menuitem *
+bin_to_res_menuitems (data, length, big_endian, read)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+     int *read;
+{
+  struct menuitem *first, **pp;
+
+  first = NULL;
+  pp = &first;
+
+  *read = 0;
+
+  while (length > 0)
+    {
+      int flags, slen, itemlen;
+      unsigned int stroff;
+      struct menuitem *mi;
+
+      if (length < 4)
+       toosmall (_("menuitem header"));
+
+      mi = (struct menuitem *) res_alloc (sizeof *mi);
+      mi->state = 0;
+      mi->help = 0;
+
+      flags = get_16 (big_endian, data);
+      mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
+
+      if ((flags & MENUITEM_POPUP) == 0)
+       stroff = 4;
+      else
+       stroff = 2;
+
+      if (length < stroff + 2)
+       toosmall (_("menuitem header"));
+
+      if (get_16 (big_endian, data + stroff) == 0)
+       {
+         slen = 0;
+         mi->text = NULL;
+       }
+      else
+       mi->text = get_unicode (data + stroff, length - stroff, big_endian,
+                               &slen);
+
+      itemlen = stroff + slen * 2 + 2;
+
+      if ((flags & MENUITEM_POPUP) == 0)
+       {
+         mi->popup = NULL;
+         mi->id = get_16 (big_endian, data + 2);
+       }
+      else
+       {
+         int subread;
+
+         mi->id = 0;
+         mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
+                                           big_endian, &subread);
+         itemlen += subread;
+       }
+
+      mi->next = NULL;
+      *pp = mi;
+      pp = &mi->next;
+
+      data += itemlen;
+      length -= itemlen;
+      *read += itemlen;
+
+      if ((flags & MENUITEM_ENDMENU) != 0)
+       return first;
+    }
+
+  return first;
+}
+
+/* Convert menuex items from binary.  */
+
+static struct menuitem *
+bin_to_res_menuexitems (data, length, big_endian, read)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+     int *read;
+{
+  struct menuitem *first, **pp;
+
+  first = NULL;
+  pp = &first;
+
+  *read = 0;
+
+  while (length > 0)
+    {
+      int flags, slen;
+      unsigned int itemlen;
+      struct menuitem *mi;
+
+      if (length < 14)
+       toosmall (_("menuitem header"));
+
+      mi = (struct menuitem *) res_alloc (sizeof *mi);
+      mi->type = get_32 (big_endian, data);
+      mi->state = get_32 (big_endian, data + 4);
+      mi->id = get_16 (big_endian, data + 8);
+
+      flags = get_16 (big_endian, data + 10);
+
+      if (get_16 (big_endian, data + 12) == 0)
+       {
+         slen = 0;
+         mi->text = NULL;
+       }
+      else
+       mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
+
+      itemlen = 12 + slen * 2 + 2;
+      itemlen = (itemlen + 3) &~ 3;
+
+      if ((flags & 1) == 0)
+       {
+         mi->popup = NULL;
+         mi->help = 0;
+       }
+      else
+       {
+         int subread;
+
+         if (length < itemlen + 4)
+           toosmall (_("menuitem"));
+         mi->help = get_32 (big_endian, data + itemlen);
+         itemlen += 4;
+
+         mi->popup = bin_to_res_menuexitems (data + itemlen,
+                                             length - itemlen,
+                                             big_endian, &subread);
+         itemlen += subread;
+       }
+
+      mi->next = NULL;
+      *pp = mi;
+      pp = &mi->next;
+
+      data += itemlen;
+      length -= itemlen;
+      *read += itemlen;
+
+      if ((flags & 0x80) != 0)
+       return first;
+    }
+
+  return first;
+}
+
+/* Convert a dialog resource from binary.  */
+
+static struct res_resource *
+bin_to_res_dialog (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  int version;
+  struct dialog *d;
+  int c, sublen, i;
+  unsigned int off;
+  struct dialog_control **pp;
+  struct res_resource *r;
+
+  if (length < 18)
+    toosmall (_("dialog header"));
+
+  d = (struct dialog *) res_alloc (sizeof *d);
+
+  version = get_16 (big_endian, data);
+  if (version != 1)
+    {
+      d->ex = NULL;
+      d->style = get_32 (big_endian, data);
+      d->exstyle = get_32 (big_endian, data + 4);
+      off = 8;
+    }
+  else
+    {
+      int signature;
+
+      signature = get_16 (big_endian, data + 2);
+      if (signature != 0xffff)
+       fatal (_("unexpected dialog signature %d"), signature);
+
+      d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex));
+      d->ex->help = get_32 (big_endian, data + 4);
+      d->exstyle = get_32 (big_endian, data + 8);
+      d->style = get_32 (big_endian, data + 12);
+      off = 16;
+    }
+
+  if (length < off + 10)
+    toosmall (_("dialog header"));
+
+  c = get_16 (big_endian, data + off);
+  d->x = get_16  (big_endian, data + off + 2);
+  d->y = get_16 (big_endian, data + off + 4);
+  d->width = get_16 (big_endian, data + off + 6);
+  d->height = get_16 (big_endian, data + off + 8);
+
+  off += 10;
+
+  sublen = get_resid (&d->menu, data + off, length - off, big_endian);
+  off += sublen;
+
+  sublen = get_resid (&d->class, data + off, length - off, big_endian);
+  off += sublen;
+
+  d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
+  off += sublen * 2 + 2;
+
+  if ((d->style & DS_SETFONT) == 0)
+    {
+      d->pointsize = 0;
+      d->font = NULL;
+      if (d->ex != NULL)
+       {
+         d->ex->weight = 0;
+         d->ex->italic = 0;
+       }
+    }
+  else
+    {
+      if (length < off + 2)
+       toosmall (_("dialog font point size"));
+
+      d->pointsize = get_16 (big_endian, data + off);
+      off += 2;
+
+      if (d->ex != NULL)
+       {
+         if (length < off + 4)
+           toosmall (_("dialogex font information"));
+         d->ex->weight = get_16 (big_endian, data + off);
+         d->ex->italic = get_16 (big_endian, data + off + 2);
+         off += 4;
+       }
+
+      d->font = get_unicode (data + off, length - off, big_endian, &sublen);
+      off += sublen * 2 + 2;
+    }
+
+  d->controls = NULL;
+  pp = &d->controls;
+
+  for (i = 0; i < c; i++)
+    {
+      struct dialog_control *dc;
+      int datalen;
+
+      off = (off + 3) &~ 3;
+
+      dc = (struct dialog_control *) res_alloc (sizeof *dc);
+
+      if (d->ex == NULL)
+       {
+         if (length < off + 8)
+           toosmall (_("dialog control"));
+
+         dc->style = get_32 (big_endian, data + off);
+         dc->exstyle = get_32 (big_endian, data + off + 4);
+         dc->help = 0;
+         off += 8;
+       }
+      else
+       {
+         if (length < off + 12)
+           toosmall (_("dialogex control"));
+         dc->help = get_32 (big_endian, data + off);
+         dc->exstyle = get_32 (big_endian, data + off + 4);
+         dc->style = get_32 (big_endian, data + off + 8);
+         off += 12;
+       }
+
+      if (length < off + 10)
+       toosmall (_("dialog control"));
+
+      dc->x = get_16 (big_endian, data + off);
+      dc->y = get_16 (big_endian, data + off + 2);
+      dc->width = get_16 (big_endian, data + off + 4);
+      dc->height = get_16 (big_endian, data + off + 6);
+
+      if (d->ex != NULL)
+        dc->id = get_32 (big_endian, data + off + 8);
+      else
+        dc->id = get_16 (big_endian, data + off + 8);
+
+      off += 10 + (d->ex != NULL ? 2 : 0);
+
+      sublen = get_resid (&dc->class, data + off, length - off, big_endian);
+      off += sublen;
+
+      sublen = get_resid (&dc->text, data + off, length - off, big_endian);
+      off += sublen;
+
+      if (length < off + 2)
+       toosmall (_("dialog control end"));
+
+      datalen = get_16 (big_endian, data + off);
+      off += 2;
+
+      if (datalen == 0)
+       dc->data = NULL;
+      else
+       {
+         off = (off + 3) &~ 3;
+
+         if (length < off + datalen)
+           toosmall (_("dialog control data"));
+
+         dc->data = ((struct rcdata_item *)
+                     res_alloc (sizeof (struct rcdata_item)));
+         dc->data->next = NULL;
+         dc->data->type = RCDATA_BUFFER;
+         dc->data->u.buffer.length = datalen;
+         dc->data->u.buffer.data = data + off;
+
+         off += datalen;         
+       }
+
+      dc->next = NULL;
+      *pp = dc;
+      pp = &dc->next;
+    }
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_DIALOG;
+  r->u.dialog = d;
+
+  return r;
+}
+
+/* Convert a stringtable resource from binary.  */
+
+static struct res_resource *
+bin_to_res_string (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  struct stringtable *st;
+  int i;
+  struct res_resource *r;
+
+  st = (struct stringtable *) res_alloc (sizeof *st);
+
+  for (i = 0; i < 16; i++)
+    {
+      unsigned int slen;
+
+      if (length < 2)
+       toosmall (_("stringtable string length"));
+      slen = get_16 (big_endian, data);
+      st->strings[i].length = slen;
+
+      if (slen > 0)
+       {
+         unichar *s;
+         unsigned int j;
+
+         if (length < 2 + 2 * slen)
+           toosmall (_("stringtable string"));
+
+         s = (unichar *) res_alloc (slen * sizeof (unichar));
+         st->strings[i].string = s;
+
+         for (j = 0; j < slen; j++)
+           s[j] = get_16 (big_endian, data + 2 + j * 2);
+       }
+
+      data += 2 + 2 * slen;
+      length -= 2 + 2 * slen;
+    }
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_STRINGTABLE;
+  r->u.stringtable = st;
+
+  return r;
+}
+
+/* Convert a fontdir resource from binary.  */
+
+static struct res_resource *
+bin_to_res_fontdir (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  int c, i;
+  struct fontdir *first, **pp;
+  struct res_resource *r;
+
+  if (length < 2)
+    toosmall (_("fontdir header"));
+
+  c = get_16 (big_endian, data);
+
+  first = NULL;
+  pp = &first;
+
+  for (i = 0; i < c; i++)
+    {
+      struct fontdir *fd;
+      unsigned int off;
+
+      if (length < 56)
+       toosmall (_("fontdir"));
+
+      fd = (struct fontdir *) res_alloc (sizeof *fd);
+      fd->index = get_16 (big_endian, data);
+
+      /* To work out the length of the fontdir data, we must get the
+         length of the device name and face name strings, even though
+         we don't store them in the fontdir structure.  The
+         documentation says that these are NULL terminated char
+         strings, not Unicode strings.  */
+
+      off = 56;
+
+      while (off < length && data[off] != '\0')
+       ++off;
+      if (off >= length)
+       toosmall (_("fontdir device name"));
+      ++off;
+
+      while (off < length && data[off] != '\0')
+       ++off;
+      if (off >= length)
+       toosmall (_("fontdir face name"));
+      ++off;
+
+      fd->length = off;
+      fd->data = data;
+
+      fd->next = NULL;
+      *pp = fd;
+      pp = &fd->next;
+
+      /* The documentation does not indicate that any rounding is
+         required.  */
+
+      data += off;
+      length -= off;
+    }
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_FONTDIR;
+  r->u.fontdir = first;
+
+  return r;
+}
+
+/* Convert an accelerators resource from binary.  */
+
+static struct res_resource *
+bin_to_res_accelerators (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  struct accelerator *first, **pp;
+  struct res_resource *r;
+
+  first = NULL;
+  pp = &first;
+
+  while (1)
+    {
+      struct accelerator *a;
+
+      if (length < 8)
+       toosmall (_("accelerator"));
+
+      a = (struct accelerator *) res_alloc (sizeof *a);
+
+      a->flags = get_16 (big_endian, data);
+      a->key = get_16 (big_endian, data + 2);
+      a->id = get_16 (big_endian, data + 4);
+
+      a->next = NULL;
+      *pp = a;
+      pp = &a->next;
+
+      if ((a->flags & ACC_LAST) != 0)
+       break;
+
+      data += 8;
+      length -= 8;
+    }
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_ACCELERATOR;
+  r->u.acc = first;
+
+  return r;
+}
+
+/* Convert an rcdata resource from binary.  */
+
+static struct res_resource *
+bin_to_res_rcdata (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  struct rcdata_item *ri;
+  struct res_resource *r;
+
+  ri = (struct rcdata_item *) res_alloc (sizeof *ri);
+
+  ri->next = NULL;
+  ri->type = RCDATA_BUFFER;
+  ri->u.buffer.length = length;
+  ri->u.buffer.data = data;
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_RCDATA;
+  r->u.rcdata = ri;
+
+  return r;
+}
+
+/* Convert a group cursor resource from binary.  */
+
+static struct res_resource *
+bin_to_res_group_cursor (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  int type, c, i;
+  struct group_cursor *first, **pp;
+  struct res_resource *r;
+
+  if (length < 6)
+    toosmall (_("group cursor header"));
+
+  type = get_16 (big_endian, data + 2);
+  if (type != 2)
+    fatal (_("unexpected group cursor type %d"), type);
+
+  c = get_16 (big_endian, data + 4);
+
+  data += 6;
+  length -= 6;
+
+  first = NULL;
+  pp = &first;
+
+  for (i = 0; i < c; i++)
+    {
+      struct group_cursor *gc;
+
+      if (length < 14)
+       toosmall (_("group cursor"));
+
+      gc = (struct group_cursor *) res_alloc (sizeof *gc);
+
+      gc->width = get_16 (big_endian, data);
+      gc->height = get_16 (big_endian, data + 2);
+      gc->planes = get_16 (big_endian, data + 4);
+      gc->bits = get_16 (big_endian, data + 6);
+      gc->bytes = get_32 (big_endian, data + 8);
+      gc->index = get_16 (big_endian, data + 12);
+
+      gc->next = NULL;
+      *pp = gc;
+      pp = &gc->next;
+
+      data += 14;
+      length -= 14;
+    }
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_GROUP_CURSOR;
+  r->u.group_cursor = first;
+
+  return r;
+}
+
+/* Convert a group icon resource from binary.  */
+
+static struct res_resource *
+bin_to_res_group_icon (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  int type, c, i;
+  struct group_icon *first, **pp;
+  struct res_resource *r;
+
+  if (length < 6)
+    toosmall (_("group icon header"));
+
+  type = get_16 (big_endian, data + 2);
+  if (type != 1)
+    fatal (_("unexpected group icon type %d"), type);
+
+  c = get_16 (big_endian, data + 4);
+
+  data += 6;
+  length -= 6;
+
+  first = NULL;
+  pp = &first;
+
+  for (i = 0; i < c; i++)
+    {
+      struct group_icon *gi;
+
+      if (length < 14)
+       toosmall (_("group icon"));
+
+      gi = (struct group_icon *) res_alloc (sizeof *gi);
+
+      gi->width = data[0];
+      gi->height = data[1];
+      gi->colors = data[2];
+      gi->planes = get_16 (big_endian, data + 4);
+      gi->bits = get_16 (big_endian, data + 6);
+      gi->bytes = get_32 (big_endian, data + 8);
+      gi->index = get_16 (big_endian, data + 12);
+
+      gi->next = NULL;
+      *pp = gi;
+      pp = &gi->next;
+
+      data += 14;
+      length -= 14;
+    }
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_GROUP_ICON;
+  r->u.group_icon = first;
+
+  return r;
+}
+
+/* Extract data from a version header.  If KEY is not NULL, then the
+   key must be KEY; otherwise, the key is returned in *PKEY.  This
+   sets *LEN to the total length, *VALLEN to the value length, *TYPE
+   to the type, and *OFF to the offset to the children.  */
+
+static void
+get_version_header (data, length, big_endian, key, pkey, len, vallen, type,
+                   off)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+     const char *key;
+     unichar **pkey;
+     int *len;
+     int *vallen;
+     int *type;
+     int *off;
+{
+  if (length < 8)
+    toosmall (key);
+
+  *len = get_16 (big_endian, data);
+  *vallen = get_16 (big_endian, data + 2);
+  *type = get_16 (big_endian, data + 4);
+
+  *off = 6;
+
+  length -= 6;
+  data += 6;
+
+  if (key == NULL)
+    {
+      int sublen;
+
+      *pkey = get_unicode (data, length, big_endian, &sublen);
+      *off += sublen * 2 + 2;
+    }
+  else
+    {
+      while (1)
+       {
+         if (length < 2)
+           toosmall (key);
+         if (get_16 (big_endian, data) != (unsigned char) *key)
+           fatal (_("unexpected version string"));
+
+         *off += 2;
+         length -= 2;
+         data += 2;
+
+         if (*key == '\0')
+           break;
+
+         ++key;
+       }
+    }
+
+  *off = (*off + 3) &~ 3;
+}
+
+/* Convert a version resource from binary.  */
+
+static struct res_resource *
+bin_to_res_version (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  int verlen, vallen, type, off;
+  struct fixed_versioninfo *fi;
+  struct ver_info *first, **pp;
+  struct versioninfo *v;
+  struct res_resource *r;
+
+  get_version_header (data, length, big_endian, "VS_VERSION_INFO",
+                     (unichar *) NULL, &verlen, &vallen, &type, &off);
+
+  if ((unsigned int) verlen != length)
+    fatal (_("version length %d does not match resource length %lu"),
+          verlen, length);
+
+  if (type != 0)
+    fatal (_("unexpected version type %d"), type);
+
+  data += off;
+  length -= off;
+
+  if (vallen == 0)
+    fi = NULL;
+  else
+    {
+      unsigned long signature, fiv;
+
+      if (vallen != 52)
+       fatal (_("unexpected fixed version information length %d"), vallen);
+
+      if (length < 52)
+       toosmall (_("fixed version info"));
+
+      signature = get_32 (big_endian, data);
+      if (signature != 0xfeef04bd)
+       fatal (_("unexpected fixed version signature %lu"), signature);
+
+      fiv = get_32 (big_endian, data + 4);
+      if (fiv != 0 && fiv != 0x10000)
+       fatal (_("unexpected fixed version info version %lu"), fiv);
+
+      fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
+
+      fi->file_version_ms = get_32 (big_endian, data + 8);
+      fi->file_version_ls = get_32 (big_endian, data + 12);
+      fi->product_version_ms = get_32 (big_endian, data + 16);
+      fi->product_version_ls = get_32 (big_endian, data + 20);
+      fi->file_flags_mask = get_32 (big_endian, data + 24);
+      fi->file_flags = get_32 (big_endian, data + 28);
+      fi->file_os = get_32 (big_endian, data + 32);
+      fi->file_type = get_32 (big_endian, data + 36);
+      fi->file_subtype = get_32 (big_endian, data + 40);
+      fi->file_date_ms = get_32 (big_endian, data + 44);
+      fi->file_date_ls = get_32 (big_endian, data + 48);
+
+      data += 52;
+      length -= 52;
+    }
+
+  first = NULL;
+  pp = &first;
+
+  while (length > 0)
+    {
+      struct ver_info *vi;
+      int ch;
+
+      if (length < 8)
+       toosmall (_("version var info"));
+
+      vi = (struct ver_info *) res_alloc (sizeof *vi);
+
+      ch = get_16 (big_endian, data + 6);
+
+      if (ch == 'S')
+       {
+         struct ver_stringinfo **ppvs;
+
+         vi->type = VERINFO_STRING;
+
+         get_version_header (data, length, big_endian, "StringFileInfo",
+                             (unichar *) NULL, &verlen, &vallen, &type,
+                             &off);
+
+         if (vallen != 0)
+           fatal (_("unexpected stringfileinfo value length %d"), vallen);
+
+         data += off;
+         length -= off;
+
+         get_version_header (data, length, big_endian, (const char *) NULL,
+                             &vi->u.string.language, &verlen, &vallen,
+                             &type, &off);
+
+         if (vallen != 0)
+           fatal (_("unexpected version stringtable value length %d"), vallen);
+
+         data += off;
+         length -= off;
+         verlen -= off;
+
+         vi->u.string.strings = NULL;
+         ppvs = &vi->u.string.strings;
+
+         /* It's convenient to round verlen to a 4 byte alignment,
+             since we round the subvariables in the loop.  */
+         verlen = (verlen + 3) &~ 3;
+
+         while (verlen > 0)
+           {
+             struct ver_stringinfo *vs;
+             int subverlen, vslen, valoff;
+
+             vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
+
+             get_version_header (data, length, big_endian,
+                                 (const char *) NULL, &vs->key, &subverlen,
+                                 &vallen, &type, &off);
+
+             subverlen = (subverlen + 3) &~ 3;
+
+             data += off;
+             length -= off;
+
+             vs->value = get_unicode (data, length, big_endian, &vslen);
+             valoff = vslen * 2 + 2;
+             valoff = (valoff + 3) &~ 3;
+
+             if (off + valoff != subverlen)
+               fatal (_("unexpected version string length %d != %d + %d"),
+                      subverlen, off, valoff);
+
+             vs->next = NULL;
+             *ppvs = vs;
+             ppvs = &vs->next;
+
+             data += valoff;
+             length -= valoff;
+
+             if (verlen < subverlen)
+               fatal (_("unexpected version string length %d < %d"),
+                      verlen, subverlen);
+
+             verlen -= subverlen;
+           }
+       }
+      else if (ch == 'V')
+       {
+         struct ver_varinfo **ppvv;
+
+         vi->type = VERINFO_VAR;
+
+         get_version_header (data, length, big_endian, "VarFileInfo",
+                             (unichar *) NULL, &verlen, &vallen, &type,
+                             &off);
+
+         if (vallen != 0)
+           fatal (_("unexpected varfileinfo value length %d"), vallen);
+
+         data += off;
+         length -= off;
+
+         get_version_header (data, length, big_endian, (const char *) NULL,
+                             &vi->u.var.key, &verlen, &vallen, &type, &off);
+
+         data += off;
+         length -= off;
+
+         vi->u.var.var = NULL;
+         ppvv = &vi->u.var.var;
+
+         while (vallen > 0)
+           {
+             struct ver_varinfo *vv;
+
+             if (length < 4)
+               toosmall (_("version varfileinfo"));
+
+             vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
+
+             vv->language = get_16 (big_endian, data);
+             vv->charset = get_16 (big_endian, data + 2);
+
+             vv->next = NULL;
+             *ppvv = vv;
+             ppvv = &vv->next;
+
+             data += 4;
+             length -= 4;
+
+             if (vallen < 4)
+               fatal (_("unexpected version value length %d"), vallen);
+
+             vallen -= 4;
+           }
+       }
+      else
+       fatal (_("unexpected version string"));
+
+      vi->next = NULL;
+      *pp = vi;
+      pp = &vi->next;      
+    }
+
+  v = (struct versioninfo *) res_alloc (sizeof *v);
+  v->fixed = fi;
+  v->var = first;
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_VERSIONINFO;
+  r->u.versioninfo = v;
+
+  return r;  
+}
+
+/* Convert an arbitrary user defined resource from binary.  */
+
+static struct res_resource *
+bin_to_res_userdata (data, length, big_endian)
+     const unsigned char *data;
+     unsigned long length;
+     int big_endian;
+{
+  struct rcdata_item *ri;
+  struct res_resource *r;
+
+  ri = (struct rcdata_item *) res_alloc (sizeof *ri);
+
+  ri->next = NULL;
+  ri->type = RCDATA_BUFFER;
+  ri->u.buffer.length = length;
+  ri->u.buffer.data = data;
+
+  r = (struct res_resource *) res_alloc (sizeof *r);
+  r->type = RES_TYPE_USERDATA;
+  r->u.rcdata = ri;
+
+  return r;
+}
+\f
+/* Macros to swap out values.  */
+
+#define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
+#define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
+
+/* Local functions used to convert resources to binary format.  */
+
+static void dword_align_bin PARAMS ((struct bindata ***, unsigned long *));
+static struct bindata *resid_to_bin PARAMS ((struct res_id, int));
+static struct bindata *unicode_to_bin PARAMS ((const unichar *, int));
+static struct bindata *res_to_bin_accelerator
+  PARAMS ((const struct accelerator *, int));
+static struct bindata *res_to_bin_cursor
+  PARAMS ((const struct cursor *, int));
+static struct bindata *res_to_bin_group_cursor
+  PARAMS ((const struct group_cursor *, int));
+static struct bindata *res_to_bin_dialog
+  PARAMS ((const struct dialog *, int));
+static struct bindata *res_to_bin_fontdir
+  PARAMS ((const struct fontdir *, int));
+static struct bindata *res_to_bin_group_icon
+  PARAMS ((const struct group_icon *, int));
+static struct bindata *res_to_bin_menu
+  PARAMS ((const struct menu *, int));
+static struct bindata *res_to_bin_menuitems
+  PARAMS ((const struct menuitem *, int));
+static struct bindata *res_to_bin_menuexitems
+  PARAMS ((const struct menuitem *, int));
+static struct bindata *res_to_bin_rcdata
+  PARAMS ((const struct rcdata_item *, int));
+static struct bindata *res_to_bin_stringtable
+  PARAMS ((const struct stringtable *, int));
+static struct bindata *string_to_unicode_bin PARAMS ((const char *, int));
+static struct bindata *res_to_bin_versioninfo
+  PARAMS ((const struct versioninfo *, int));
+static struct bindata *res_to_bin_generic
+  PARAMS ((unsigned long, const unsigned char *));
+
+/* Convert a resource to binary.  */
+
+struct bindata *
+res_to_bin (res, big_endian)
+     const struct res_resource *res;
+     int big_endian;
+{
+  switch (res->type)
+    {
+    default:
+      abort ();
+    case RES_TYPE_BITMAP:
+    case RES_TYPE_FONT:
+    case RES_TYPE_ICON:
+    case RES_TYPE_MESSAGETABLE:
+      return res_to_bin_generic (res->u.data.length, res->u.data.data);
+    case RES_TYPE_ACCELERATOR:
+      return res_to_bin_accelerator (res->u.acc, big_endian);
+    case RES_TYPE_CURSOR:
+      return res_to_bin_cursor (res->u.cursor, big_endian);
+    case RES_TYPE_GROUP_CURSOR:
+      return res_to_bin_group_cursor (res->u.group_cursor, big_endian);
+    case RES_TYPE_DIALOG:
+      return res_to_bin_dialog (res->u.dialog, big_endian);
+    case RES_TYPE_FONTDIR:
+      return res_to_bin_fontdir (res->u.fontdir, big_endian);
+    case RES_TYPE_GROUP_ICON:
+      return res_to_bin_group_icon (res->u.group_icon, big_endian);
+    case RES_TYPE_MENU:
+      return res_to_bin_menu (res->u.menu, big_endian);
+    case RES_TYPE_RCDATA:
+      return res_to_bin_rcdata (res->u.rcdata, big_endian);
+    case RES_TYPE_STRINGTABLE:
+      return res_to_bin_stringtable (res->u.stringtable, big_endian);
+    case RES_TYPE_USERDATA:
+      return res_to_bin_rcdata (res->u.rcdata, big_endian);
+    case RES_TYPE_VERSIONINFO:
+      return res_to_bin_versioninfo (res->u.versioninfo, big_endian);
+    }
+}
+
+/* Align to a 32 bit boundary.  PPP points to the of a list of bindata
+   structures.  LENGTH points to the length of the structures.  If
+   necessary, this adds a new bindata to bring length up to a 32 bit
+   boundary.  It updates *PPP and *LENGTH.  */
+
+static void
+dword_align_bin (ppp, length)
+     struct bindata ***ppp;
+     unsigned long *length;
+{
+  int add;
+  struct bindata *d;
+
+  if ((*length & 3) == 0)
+    return;
+
+  add = 4 - (*length & 3);
+
+  d = (struct bindata *) reswr_alloc (sizeof *d);
+  d->length = add;
+  d->data = (unsigned char *) reswr_alloc (add);
+  memset (d->data, 0, add);
+
+  d->next = NULL;
+  **ppp = d;
+  *ppp = &(**ppp)->next;
+
+  *length += add;
+}
+
+/* Convert a resource ID to binary.  This always returns exactly one
+   bindata structure.  */
+
+static struct bindata *
+resid_to_bin (id, big_endian)
+     struct res_id id;
+     int big_endian;
+{
+  struct bindata *d;
+
+  d = (struct bindata *) reswr_alloc (sizeof *d);
+
+  if (! id.named)
+    {
+      d->length = 4;
+      d->data = (unsigned char *) reswr_alloc (4);
+      put_16 (big_endian, 0xffff, d->data);
+      put_16 (big_endian, id.u.id, d->data + 2);
+    }
+  else
+    {
+      int i;
+
+      d->length = id.u.n.length * 2 + 2;
+      d->data = (unsigned char *) reswr_alloc (d->length);
+      for (i = 0; i < id.u.n.length; i++)
+       put_16 (big_endian, id.u.n.name[i], d->data + i * 2);
+      put_16 (big_endian, 0, d->data + i * 2);
+    }
+
+  d->next = NULL;
+
+  return d;
+}
+
+/* Convert a null terminated unicode string to binary.  This always
+   returns exactly one bindata structure.  */
+
+static struct bindata *
+unicode_to_bin (str, big_endian)
+     const unichar *str;
+     int big_endian;
+{
+  int len;
+  struct bindata *d;
+
+  len = 0;
+  if (str != NULL)
+    {
+      const unichar *s;
+
+      for (s = str; *s != 0; s++)
+       ++len;
+    }
+
+  d = (struct bindata *) reswr_alloc (sizeof *d);
+  d->length = len * 2 + 2;
+  d->data = (unsigned char *) reswr_alloc (d->length);
+
+  if (str == NULL)
+    put_16 (big_endian, 0, d->data);
+  else
+    {
+      const unichar *s;
+      int i;
+
+      for (s = str, i = 0; *s != 0; s++, i++)
+       put_16 (big_endian, *s, d->data + i * 2);
+      put_16 (big_endian, 0, d->data + i * 2);
+    }
+
+  d->next = NULL;
+
+  return d;
+}
+
+/* Convert an accelerator resource to binary.  */
+
+static struct bindata *
+res_to_bin_accelerator (accelerators, big_endian)
+     const struct accelerator *accelerators;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  const struct accelerator *a;
+
+  first = NULL;
+  pp = &first;
+
+  for (a = accelerators; a != NULL; a = a->next)
+    {
+      struct bindata *d;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = 8;
+      d->data = (unsigned char *) reswr_alloc (8);
+
+      put_16 (big_endian,
+             a->flags | (a->next != NULL ? 0 : ACC_LAST),
+             d->data);
+      put_16 (big_endian, a->key, d->data + 2);
+      put_16 (big_endian, a->id, d->data + 4);
+      put_16 (big_endian, 0, d->data + 8);
+
+      d->next = NULL;
+      *pp = d;
+      pp = &d->next;
+    }
+
+  return first;
+}
+
+/* Convert a cursor resource to binary.  */
+
+static struct bindata *
+res_to_bin_cursor (c, big_endian)
+     const struct cursor *c;
+     int big_endian;
+{
+  struct bindata *d;
+
+  d = (struct bindata *) reswr_alloc (sizeof *d);
+  d->length = 4;
+  d->data = (unsigned char *) reswr_alloc (4);
+
+  put_16 (big_endian, c->xhotspot, d->data);
+  put_16 (big_endian, c->yhotspot, d->data + 2);
+
+  d->next = (struct bindata *) reswr_alloc (sizeof *d);
+  d->next->length = c->length;
+  d->next->data = (unsigned char *) c->data;
+  d->next->next = NULL;
+
+  return d;
+}
+
+/* Convert a group cursor resource to binary.  */
+
+static struct bindata *
+res_to_bin_group_cursor (group_cursors, big_endian)
+     const struct group_cursor *group_cursors;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  int c;
+  const struct group_cursor *gc;
+
+  first = (struct bindata *) reswr_alloc (sizeof *first);
+  first->length = 6;
+  first->data = (unsigned char *) reswr_alloc (6);
+
+  put_16 (big_endian, 0, first->data);
+  put_16 (big_endian, 2, first->data + 2);
+
+  first->next = NULL;
+  pp = &first->next;
+
+  c = 0;
+  for (gc = group_cursors; gc != NULL; gc = gc->next)
+    {
+      struct bindata *d;
+
+      ++c;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = 14;
+      d->data = (unsigned char *) reswr_alloc (14);
+
+      put_16 (big_endian, gc->width, d->data);
+      put_16 (big_endian, gc->height, d->data + 2);
+      put_16 (big_endian, gc->planes, d->data + 4);
+      put_16 (big_endian, gc->bits, d->data + 6);
+      put_32 (big_endian, gc->bytes, d->data + 8);
+      put_16 (big_endian, gc->index, d->data + 12);
+
+      d->next = NULL;
+      *pp = d;
+      pp = &d->next;
+    }
+
+  put_16 (big_endian, c, first->data + 4);
+
+  return first;
+}
+
+/* Convert a dialog resource to binary.  */
+
+static struct bindata *
+res_to_bin_dialog (dialog, big_endian)
+     const struct dialog *dialog;
+     int big_endian;
+{
+  int dialogex;
+  struct bindata *first, **pp;
+  unsigned long length;
+  int off, c;
+  struct dialog_control *dc;
+
+  dialogex = extended_dialog (dialog);
+
+  first = (struct bindata *) reswr_alloc (sizeof *first);
+  first->length = dialogex ? 26 : 18;
+  first->data = (unsigned char *) reswr_alloc (first->length);
+
+  length = first->length;
+
+  if (! dialogex)
+    {
+      put_32 (big_endian, dialog->style, first->data);
+      put_32 (big_endian, dialog->exstyle, first->data + 4);
+      off = 8;
+    }
+  else
+    {
+      put_16 (big_endian, 1, first->data);
+      put_16 (big_endian, 0xffff, first->data + 2);
+
+      if (dialog->ex == NULL)
+       put_32 (big_endian, 0, first->data + 4);
+      else
+       put_32 (big_endian, dialog->ex->help, first->data + 4);
+      put_32 (big_endian, dialog->exstyle, first->data + 8);
+      put_32 (big_endian, dialog->style, first->data + 12);
+      off = 16;
+    }
+
+  put_16 (big_endian, dialog->x, first->data + off + 2);
+  put_16 (big_endian, dialog->y, first->data + off + 4);
+  put_16 (big_endian, dialog->width, first->data + off + 6);
+  put_16 (big_endian, dialog->height, first->data + off + 8);
+
+  pp = &first->next;
+
+  *pp = resid_to_bin (dialog->menu, big_endian);
+  length += (*pp)->length;
+  pp = &(*pp)->next;
+
+  *pp = resid_to_bin (dialog->class, big_endian);
+  length += (*pp)->length;
+  pp = &(*pp)->next;
+
+  *pp = unicode_to_bin (dialog->caption, big_endian);
+  length += (*pp)->length;
+  pp = &(*pp)->next;
+
+  if ((dialog->style & DS_SETFONT) != 0)
+    {
+      struct bindata *d;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = dialogex ? 6 : 2;
+      d->data = (unsigned char *) reswr_alloc (d->length);
+
+      length += d->length;
+
+      put_16 (big_endian, dialog->pointsize, d->data);
+
+      if (dialogex)
+       {
+         if (dialog->ex == NULL)
+           {
+             put_16 (big_endian, 0, d->data + 2);
+             put_16 (big_endian, 0, d->data + 4);
+           }
+         else
+           {
+             put_16 (big_endian, dialog->ex->weight, d->data + 2);
+             put_16 (big_endian, dialog->ex->italic, d->data + 4);
+           }
+       }
+
+      *pp = d;
+      pp = &d->next;
+
+      *pp = unicode_to_bin (dialog->font, big_endian);
+      length += (*pp)->length;
+      pp = &(*pp)->next;
+    }
+
+  c = 0;
+  for (dc = dialog->controls; dc != NULL; dc = dc->next)
+    {
+      struct bindata *d;
+      int dcoff;
+
+      ++c;
+
+      dword_align_bin (&pp, &length);
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = dialogex ? 24 : 18;
+      d->data = (unsigned char *) reswr_alloc (d->length);
+
+      length += d->length;
+
+      if (! dialogex)
+       {
+         put_32 (big_endian, dc->style, d->data);
+         put_32 (big_endian, dc->exstyle, d->data + 4);
+         dcoff = 8;
+       }
+      else
+       {
+         put_32 (big_endian, dc->help, d->data);
+         put_32 (big_endian, dc->exstyle, d->data + 4);
+         put_32 (big_endian, dc->style, d->data + 8);
+         dcoff = 12;
+       }
+
+      put_16 (big_endian, dc->x, d->data + dcoff);
+      put_16 (big_endian, dc->y, d->data + dcoff + 2);
+      put_16 (big_endian, dc->width, d->data + dcoff + 4);
+      put_16 (big_endian, dc->height, d->data + dcoff + 6);
+
+      if (dialogex)
+        put_32 (big_endian, dc->id, d->data + dcoff + 8);
+      else
+        put_16 (big_endian, dc->id, d->data + dcoff + 8);
+
+      *pp = d;
+      pp = &d->next;
+
+      *pp = resid_to_bin (dc->class, big_endian);
+      length += (*pp)->length;
+      pp = &(*pp)->next;
+
+      *pp = resid_to_bin (dc->text, big_endian);
+      length += (*pp)->length;
+      pp = &(*pp)->next;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = 2;
+      d->data = (unsigned char *) reswr_alloc (2);
+
+      length += 2;
+
+      d->next = NULL;
+      *pp = d;
+      pp = &d->next;
+
+      if (dc->data == NULL)
+       put_16 (big_endian, 0, d->data);
+      else
+       {
+         unsigned long sublen;
+
+         dword_align_bin (&pp, &length);
+
+         *pp = res_to_bin_rcdata (dc->data, big_endian);
+         sublen = 0;
+         while (*pp != NULL)
+           {
+             sublen += (*pp)->length;
+             pp = &(*pp)->next;
+           }
+
+         put_16 (big_endian, sublen, d->data);
+
+         length += sublen;
+       }
+    }
+  put_16 (big_endian, c, first->data + off);
+
+  return first;
+}
+
+/* Convert a fontdir resource to binary.  */
+
+static struct bindata *
+res_to_bin_fontdir (fontdirs, big_endian)
+     const struct fontdir *fontdirs;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  int c;
+  const struct fontdir *fd;
+
+  first = (struct bindata *) reswr_alloc (sizeof *first);
+  first->length = 2;
+  first->data = (unsigned char *) reswr_alloc (2);
+
+  first->next = NULL;
+  pp = &first->next;
+
+  c = 0;
+  for (fd = fontdirs; fd != NULL; fd = fd->next)
+    {
+      struct bindata *d;
+
+      ++c;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = 2;
+      d->data = (unsigned char *) reswr_alloc (2);
+
+      put_16 (big_endian, fd->index, d->data);
+
+      *pp = d;
+      pp = &d->next;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = fd->length;
+      d->data = (unsigned char *) fd->data;
+
+      d->next = NULL;
+      *pp = d;
+      pp = &d->next;      
+    }
+
+  put_16 (big_endian, c, first->data);
+
+  return first;  
+}
+
+/* Convert a group icon resource to binary.  */
+
+static struct bindata *
+res_to_bin_group_icon (group_icons, big_endian)
+     const struct group_icon *group_icons;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  int c;
+  const struct group_icon *gi;
+
+  first = (struct bindata *) reswr_alloc (sizeof *first);
+  first->length = 6;
+  first->data = (unsigned char *) reswr_alloc (6);
+
+  put_16 (big_endian, 0, first->data);
+  put_16 (big_endian, 1, first->data + 2);
+
+  first->next = NULL;
+  pp = &first->next;
+
+  c = 0;
+  for (gi = group_icons; gi != NULL; gi = gi->next)
+    {
+      struct bindata *d;
+
+      ++c;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = 14;
+      d->data = (unsigned char *) reswr_alloc (14);
+
+      d->data[0] = gi->width;
+      d->data[1] = gi->height;
+      d->data[2] = gi->colors;
+      d->data[3] = 0;
+      put_16 (big_endian, gi->planes, d->data + 4);
+      put_16 (big_endian, gi->bits, d->data + 6);
+      put_32 (big_endian, gi->bytes, d->data + 8);
+      put_16 (big_endian, gi->index, d->data + 12);
+
+      d->next = NULL;
+      *pp = d;
+      pp = &d->next;
+    }
+
+  put_16 (big_endian, c, first->data + 4);
+
+  return first;
+}
+
+/* Convert a menu resource to binary.  */
+
+static struct bindata *
+res_to_bin_menu (menu, big_endian)
+     const struct menu *menu;
+     int big_endian;
+{
+  int menuex;
+  struct bindata *d;
+
+  menuex = extended_menu (menu);
+
+  d = (struct bindata *) reswr_alloc (sizeof *d);
+  d->length = menuex ? 8 : 4;
+  d->data = (unsigned char *) reswr_alloc (d->length);
+
+  if (! menuex)
+    {
+      put_16 (big_endian, 0, d->data);
+      put_16 (big_endian, 0, d->data + 2);
+
+      d->next = res_to_bin_menuitems (menu->items, big_endian);
+    }
+  else
+    {
+      put_16 (big_endian, 1, d->data);
+      put_16 (big_endian, 4, d->data + 2);
+      put_32 (big_endian, menu->help, d->data + 4);
+
+      d->next = res_to_bin_menuexitems (menu->items, big_endian);
+    }
+
+  return d;
+}
+
+/* Convert menu items to binary.  */
+
+static struct bindata *
+res_to_bin_menuitems (items, big_endian)
+     const struct menuitem *items;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  const struct menuitem *mi;
+
+  first = NULL;
+  pp = &first;
+
+  for (mi = items; mi != NULL; mi = mi->next)
+    {
+      struct bindata *d;
+      int flags;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = mi->popup == NULL ? 4 : 2;
+      d->data = (unsigned char *) reswr_alloc (d->length);
+
+      flags = mi->type;
+      if (mi->next == NULL)
+       flags |= MENUITEM_ENDMENU;
+      if (mi->popup != NULL)
+       flags |= MENUITEM_POPUP;
+
+      put_16 (big_endian, flags, d->data);
+
+      if (mi->popup == NULL)
+       put_16 (big_endian, mi->id, d->data + 2);
+
+      *pp = d;
+      pp = &d->next;
+
+      *pp = unicode_to_bin (mi->text, big_endian);
+      pp = &(*pp)->next;
+
+      if (mi->popup != NULL)
+       {
+         *pp = res_to_bin_menuitems (mi->popup, big_endian);
+         while (*pp != NULL)
+           pp = &(*pp)->next;
+       }
+    }
+
+  return first;
+}
+
+/* Convert menuex items to binary.  */
+
+static struct bindata *
+res_to_bin_menuexitems (items, big_endian)
+     const struct menuitem *items;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  unsigned long length;
+  const struct menuitem *mi;
+
+  first = NULL;
+  pp = &first;
+
+  length = 0;
+
+  for (mi = items; mi != NULL; mi = mi->next)
+    {
+      struct bindata *d;
+      int flags;
+
+      dword_align_bin (&pp, &length);
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = 12;
+      d->data = (unsigned char *) reswr_alloc (12);
+
+      length += 12;
+
+      put_32 (big_endian, mi->type, d->data);
+      put_32 (big_endian, mi->state, d->data + 4);
+      put_16 (big_endian, mi->id, d->data + 8);
+
+      flags = 0;
+      if (mi->next == NULL)
+       flags |= 0x80;
+      if (mi->popup != NULL)
+       flags |= 1;
+      put_16 (big_endian, flags, d->data + 10);
+
+      *pp = d;
+      pp = &d->next;
+
+      *pp = unicode_to_bin (mi->text, big_endian);
+      length += (*pp)->length;
+      pp = &(*pp)->next;
+
+      if (mi->popup != NULL)
+       {
+         dword_align_bin (&pp, &length);
+
+         d = (struct bindata *) reswr_alloc (sizeof *d);
+         d->length = 4;
+         d->data = (unsigned char *) reswr_alloc (4);
+
+         put_32 (big_endian, mi->help, d->data);
+
+         *pp = d;
+         pp = &d->next;
+
+         *pp = res_to_bin_menuexitems (mi->popup, big_endian);
+         while (*pp != NULL)
+           {
+             length += (*pp)->length;
+             pp = &(*pp)->next;
+           }
+       }
+    }
+
+  return first;
+}
+
+/* Convert an rcdata resource to binary.  This is also used to convert
+   other information which happens to be stored in rcdata_item lists
+   to binary.  */
+
+static struct bindata *
+res_to_bin_rcdata (items, big_endian)
+     const struct rcdata_item *items;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  const struct rcdata_item *ri;
+
+  first = NULL;
+  pp = &first;
+
+  for (ri = items; ri != NULL; ri = ri->next)
+    {
+      struct bindata *d;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+
+      switch (ri->type)
+       {
+       default:
+         abort ();
+
+       case RCDATA_WORD:
+         d->length = 2;
+         d->data = (unsigned char *) reswr_alloc (2);
+         put_16 (big_endian, ri->u.word, d->data);
+         break;
+
+       case RCDATA_DWORD:
+         d->length = 4;
+         d->data = (unsigned char *) reswr_alloc (4);
+         put_32 (big_endian, ri->u.dword, d->data);
+         break;
+
+       case RCDATA_STRING:
+         d->length = ri->u.string.length;
+         d->data = (unsigned char *) ri->u.string.s;
+         break;
+
+       case RCDATA_WSTRING:
+         {
+           unsigned long i;
+
+           d->length = ri->u.wstring.length * 2;
+           d->data = (unsigned char *) reswr_alloc (d->length);
+           for (i = 0; i < ri->u.wstring.length; i++)
+             put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2);
+           break;
+         }
+
+       case RCDATA_BUFFER:
+         d->length = ri->u.buffer.length;
+         d->data = (unsigned char *) ri->u.buffer.data;
+         break;
+       }
+
+      d->next = NULL;
+      *pp = d;
+      pp = &d->next;
+    }
+
+  return first;
+}
+
+/* Convert a stringtable resource to binary.  */
+
+static struct bindata *
+res_to_bin_stringtable (st, big_endian)
+     const struct stringtable *st;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  int i;
+
+  first = NULL;
+  pp = &first;
+
+  for (i = 0; i < 16; i++)
+    {
+      int slen, j;
+      struct bindata *d;
+      unichar *s;
+
+      slen = st->strings[i].length;
+      s = st->strings[i].string;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = 2 + slen * 2;
+      d->data = (unsigned char *) reswr_alloc (d->length);
+
+      put_16 (big_endian, slen, d->data);
+
+      for (j = 0; j < slen; j++)
+       put_16 (big_endian, s[j], d->data + 2 + j * 2);
+
+      d->next = NULL;
+      *pp = d;
+      pp = &d->next;      
+    }
+
+  return first;
+}
+
+/* Convert an ASCII string to a unicode binary string.  This always
+   returns exactly one bindata structure.  */
+
+static struct bindata *
+string_to_unicode_bin (s, big_endian)
+     const char *s;
+     int big_endian;
+{
+  size_t len, i;
+  struct bindata *d;
+
+  len = strlen (s);
+
+  d = (struct bindata *) reswr_alloc (sizeof *d);
+  d->length = len * 2 + 2;
+  d->data = (unsigned char *) reswr_alloc (d->length);
+
+  for (i = 0; i < len; i++)
+    put_16 (big_endian, s[i], d->data + i * 2);
+  put_16 (big_endian, 0, d->data + i * 2);
+
+  d->next = NULL;
+
+  return d;  
+}
+
+/* Convert a versioninfo resource to binary.  */
+
+static struct bindata *
+res_to_bin_versioninfo (versioninfo, big_endian)
+     const struct versioninfo *versioninfo;
+     int big_endian;
+{
+  struct bindata *first, **pp;
+  unsigned long length;
+  struct ver_info *vi;
+
+  first = (struct bindata *) reswr_alloc (sizeof *first);
+  first->length = 6;
+  first->data = (unsigned char *) reswr_alloc (6);
+
+  length = 6;
+
+  if (versioninfo->fixed == NULL)
+    put_16 (big_endian, 0, first->data + 2);
+  else
+    put_16 (big_endian, 52, first->data + 2);
+
+  put_16 (big_endian, 0, first->data + 4);
+
+  pp = &first->next;
+
+  *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
+  length += (*pp)->length;
+  pp = &(*pp)->next;
+
+  dword_align_bin (&pp, &length);
+
+  if (versioninfo->fixed != NULL)
+    {
+      const struct fixed_versioninfo *fi;
+      struct bindata *d;
+
+      d = (struct bindata *) reswr_alloc (sizeof *d);
+      d->length = 52;
+      d->data = (unsigned char *) reswr_alloc (52);
+
+      length += 52;
+
+      fi = versioninfo->fixed;
+
+      put_32 (big_endian, 0xfeef04bd, d->data);
+      put_32 (big_endian, 0x10000, d->data + 4);
+      put_32 (big_endian, fi->file_version_ms, d->data + 8);
+      put_32 (big_endian, fi->file_version_ls, d->data + 12);
+      put_32 (big_endian, fi->product_version_ms, d->data + 16);
+      put_32 (big_endian, fi->product_version_ls, d->data + 20);
+      put_32 (big_endian, fi->file_flags_mask, d->data + 24);
+      put_32 (big_endian, fi->file_flags, d->data + 28);
+      put_32 (big_endian, fi->file_os, d->data + 32);
+      put_32 (big_endian, fi->file_type, d->data + 36);
+      put_32 (big_endian, fi->file_subtype, d->data + 40);
+      put_32 (big_endian, fi->file_date_ms, d->data + 44);
+      put_32 (big_endian, fi->file_date_ls, d->data + 48);
+
+      d->next = NULL;
+      *pp = d;
+      pp = &d->next;
+    }
+
+  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
+    {
+      struct bindata *vid;
+      unsigned long vilen;
+
+      dword_align_bin (&pp, &length);
+
+      vid = (struct bindata *) reswr_alloc (sizeof *vid);
+      vid->length = 6;
+      vid->data = (unsigned char *) reswr_alloc (6);
+
+      length += 6;
+      vilen = 6;
+
+      put_16 (big_endian, 0, vid->data + 2);
+      put_16 (big_endian, 0, vid->data + 4);
+
+      *pp = vid;
+      pp = &vid->next;
+
+      switch (vi->type)
+       {
+       default:
+         abort ();
+
+       case VERINFO_STRING:
+         {
+           unsigned long hold, vslen;
+           struct bindata *vsd;
+           const struct ver_stringinfo *vs;
+
+           *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
+           length += (*pp)->length;
+           vilen += (*pp)->length;
+           pp = &(*pp)->next;
+
+           hold = length;
+           dword_align_bin (&pp, &length);
+           vilen += length - hold;
+
+           vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
+           vsd->length = 6;
+           vsd->data = (unsigned char *) reswr_alloc (6);
+
+           length += 6;
+           vilen += 6;
+           vslen = 6;
+
+           put_16 (big_endian, 0, vsd->data + 2);
+           put_16 (big_endian, 0, vsd->data + 4);
+
+           *pp = vsd;
+           pp = &vsd->next;
+
+           *pp = unicode_to_bin (vi->u.string.language, big_endian);
+           length += (*pp)->length;
+           vilen += (*pp)->length;
+           vslen += (*pp)->length;
+           pp = &(*pp)->next;
+
+           for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
+             {
+               struct bindata *vssd;
+               unsigned long vsslen;
+
+               hold = length;
+               dword_align_bin (&pp, &length);
+               vilen += length - hold;
+               vslen += length - hold;
+
+               vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
+               vssd->length = 6;
+               vssd->data = (unsigned char *) reswr_alloc (6);
+
+               length += 6;
+               vilen += 6;
+               vslen += 6;
+               vsslen = 6;
+
+               put_16 (big_endian, 1, vssd->data + 4);
+
+               *pp = vssd;
+               pp = &vssd->next;
+
+               *pp = unicode_to_bin (vs->key, big_endian);
+               length += (*pp)->length;
+               vilen += (*pp)->length;
+               vslen += (*pp)->length;
+               vsslen += (*pp)->length;
+               pp = &(*pp)->next;
+
+               hold = length;
+               dword_align_bin (&pp, &length);
+               vilen += length - hold;
+               vslen += length - hold;
+               vsslen += length - hold;
+
+               *pp = unicode_to_bin (vs->value, big_endian);
+               put_16 (big_endian, (*pp)->length / 2, vssd->data + 2);
+               length += (*pp)->length;
+               vilen += (*pp)->length;
+               vslen += (*pp)->length;
+               vsslen += (*pp)->length;
+               pp = &(*pp)->next;
+
+               put_16 (big_endian, vsslen, vssd->data);
+             }
+
+           put_16 (big_endian, vslen, vsd->data);
+
+           break;
+         }
+
+       case VERINFO_VAR:
+         {
+           unsigned long hold, vvlen, vvvlen;
+           struct bindata *vvd;
+           const struct ver_varinfo *vv;
+
+           *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
+           length += (*pp)->length;
+           vilen += (*pp)->length;
+           pp = &(*pp)->next;
+
+           hold = length;
+           dword_align_bin (&pp, &length);
+           vilen += length - hold;
+
+           vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
+           vvd->length = 6;
+           vvd->data = (unsigned char *) reswr_alloc (6);
+
+           length += 6;
+           vilen += 6;
+           vvlen = 6;
+
+           put_16 (big_endian, 0, vvd->data + 4);
+
+           *pp = vvd;
+           pp = &vvd->next;
+
+           *pp = unicode_to_bin (vi->u.var.key, big_endian);
+           length += (*pp)->length;
+           vilen += (*pp)->length;
+           vvlen += (*pp)->length;
+           pp = &(*pp)->next;
+
+           hold = length;
+           dword_align_bin (&pp, &length);
+           vilen += length - hold;
+           vvlen += length - hold;
+
+           vvvlen = 0;
+
+           for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
+             {
+               struct bindata *vvsd;
+
+               vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
+               vvsd->length = 4;
+               vvsd->data = (unsigned char *) reswr_alloc (4);
+
+               length += 4;
+               vilen += 4;
+               vvlen += 4;
+               vvvlen += 4;
+
+               put_16 (big_endian, vv->language, vvsd->data);
+               put_16 (big_endian, vv->charset, vvsd->data + 2);
+
+               vvsd->next = NULL;
+               *pp = vvsd;
+               pp = &vvsd->next;
+             }
+
+           put_16 (big_endian, vvlen, vvd->data);
+           put_16 (big_endian, vvvlen, vvd->data + 2);
+
+           break;
+         }
+       }
+
+      put_16 (big_endian, vilen, vid->data);
+    }
+
+  put_16 (big_endian, length, first->data);
+
+  return first;
+}
+
+/* Convert a generic resource to binary.  */
+
+static struct bindata *
+res_to_bin_generic (length, data)
+     unsigned long length;
+     const unsigned char *data;
+{
+  struct bindata *d;
+
+  d = (struct bindata *) reswr_alloc (sizeof *d);
+  d->length = length;
+  d->data = (unsigned char *) data;
+
+  d->next = NULL;
+
+  return d;
+}
diff --git a/binutils/rescoff.c b/binutils/rescoff.c
new file mode 100644 (file)
index 0000000..9a028c7
--- /dev/null
@@ -0,0 +1,776 @@
+/* rescoff.c -- read and write resources in Windows COFF files.
+   Copyright 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file contains function that read and write Windows resources
+   in COFF files.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "windres.h"
+
+#include <assert.h>
+
+/* In order to use the address of a resource data entry, we need to
+   get the image base of the file.  Right now we extract it from
+   internal BFD information.  FIXME.  */
+
+#include "coff/internal.h"
+#include "libcoff.h"
+
+/* Information we extract from the file.  */
+
+struct coff_file_info
+{
+  /* File name.  */
+  const char *filename;
+  /* Data read from the file.  */
+  const bfd_byte *data;
+  /* End of data read from file.  */
+  const bfd_byte *data_end;
+  /* Address of the resource section minus the image base of the file.  */
+  bfd_vma secaddr;
+  /* Non-zero if the file is big endian.  */
+  int big_endian;
+};
+
+/* A resource directory table in a COFF file.  */
+
+struct extern_res_directory
+{
+  /* Characteristics.  */
+  bfd_byte characteristics[4];
+  /* Time stamp.  */
+  bfd_byte time[4];
+  /* Major version number.  */
+  bfd_byte major[2];
+  /* Minor version number.  */
+  bfd_byte minor[2];
+  /* Number of named directory entries.  */
+  bfd_byte name_count[2];
+  /* Number of directory entries with IDs.  */
+  bfd_byte id_count[2];
+};
+
+/* A resource directory entry in a COFF file.  */
+
+struct extern_res_entry
+{
+  /* Name or ID.  */
+  bfd_byte name[4];
+  /* Address of resource entry or subdirectory.  */
+  bfd_byte rva[4];
+};
+
+/* A resource data entry in a COFF file.  */
+
+struct extern_res_data
+{
+  /* Address of resource data.  This is apparently a file relative
+     address, rather than a section offset.  */
+  bfd_byte rva[4];
+  /* Size of resource data.  */
+  bfd_byte size[4];
+  /* Code page.  */
+  bfd_byte codepage[4];
+  /* Reserved.  */
+  bfd_byte reserved[4];
+};
+
+/* Macros to swap in values.  */
+
+#define getfi_16(fi, s) ((fi)->big_endian ? bfd_getb16 (s) : bfd_getl16 (s))
+#define getfi_32(fi, s) ((fi)->big_endian ? bfd_getb32 (s) : bfd_getl32 (s))
+
+/* Local functions.  */
+
+static void overrun PARAMS ((const struct coff_file_info *, const char *));
+static struct res_directory *read_coff_res_dir
+  PARAMS ((const bfd_byte *, const struct coff_file_info *,
+          const struct res_id *, int));
+static struct res_resource *read_coff_data_entry
+  PARAMS ((const bfd_byte *, const struct coff_file_info *,
+          const struct res_id *));
+\f
+/* Read the resources in a COFF file.  */
+
+struct res_directory *
+read_coff_rsrc (filename, target)
+     const char *filename;
+     const char *target;
+{
+  bfd *abfd;
+  char **matching;
+  asection *sec;
+  bfd_size_type size;
+  bfd_byte *data;
+  struct coff_file_info finfo;
+
+  if (filename == NULL)
+    fatal (_("filename required for COFF input"));
+
+  abfd = bfd_openr (filename, target);
+  if (abfd == NULL)
+    bfd_fatal (filename);
+
+  if (! bfd_check_format_matches (abfd, bfd_object, &matching))
+    {
+      bfd_nonfatal (bfd_get_filename (abfd));
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       list_matching_formats (matching);
+      xexit (1);
+    }
+
+  sec = bfd_get_section_by_name (abfd, ".rsrc");
+  if (sec == NULL)
+    {
+      fprintf (stderr, _("%s: %s: no resource section\n"), program_name,
+              filename);
+      xexit (1);
+    }
+
+  size = bfd_section_size (abfd, sec);
+  data = (bfd_byte *) res_alloc (size);
+
+  if (! bfd_get_section_contents (abfd, sec, data, 0, size))
+    bfd_fatal (_("can't read resource section"));
+
+  finfo.filename = filename;
+  finfo.data = data;
+  finfo.data_end = data + size;
+  finfo.secaddr = (bfd_get_section_vma (abfd, sec)
+                  - pe_data (abfd)->pe_opthdr.ImageBase);
+  finfo.big_endian = bfd_big_endian (abfd);
+
+  bfd_close (abfd);
+
+  /* Now just read in the top level resource directory.  Note that we
+     don't free data, since we create resource entries that point into
+     it.  If we ever want to free up the resource information we read,
+     this will have to be cleaned up.  */
+
+  return read_coff_res_dir (data, &finfo, (const struct res_id *) NULL, 0);
+}
+
+/* Give an error if we are out of bounds.  */
+
+static void
+overrun (finfo, msg)
+     const struct coff_file_info *finfo;
+     const char *msg;
+{
+  fatal (_("%s: %s: address out of bounds"), finfo->filename, msg);
+}
+
+/* Read a resource directory.  */
+
+static struct res_directory *
+read_coff_res_dir (data, finfo, type, level)
+     const bfd_byte *data;
+     const struct coff_file_info *finfo;
+     const struct res_id *type;
+     int level;
+{
+  const struct extern_res_directory *erd;
+  struct res_directory *rd;
+  int name_count, id_count, i;
+  struct res_entry **pp;
+  const struct extern_res_entry *ere;
+
+  if ((size_t) (finfo->data_end - data) < sizeof (struct extern_res_directory))
+    overrun (finfo, _("directory"));
+
+  erd = (const struct extern_res_directory *) data;
+
+  rd = (struct res_directory *) res_alloc (sizeof *rd);
+  rd->characteristics = getfi_32 (finfo, erd->characteristics);
+  rd->time = getfi_32 (finfo, erd->time);
+  rd->major = getfi_16 (finfo, erd->major);
+  rd->minor = getfi_16 (finfo, erd->minor);
+  rd->entries = NULL;
+
+  name_count = getfi_16 (finfo, erd->name_count);
+  id_count = getfi_16 (finfo, erd->id_count);
+
+  pp = &rd->entries;
+
+  /* The resource directory entries immediately follow the directory
+     table.  */
+  ere = (const struct extern_res_entry *) (erd + 1);
+
+  for (i = 0; i < name_count; i++, ere++)
+    {
+      unsigned long name, rva;
+      struct res_entry *re;
+      const bfd_byte *ers;
+      int length, j;
+
+      if ((const bfd_byte *) ere >= finfo->data_end)
+       overrun (finfo, _("named directory entry"));
+
+      name = getfi_32 (finfo, ere->name);
+      rva = getfi_32 (finfo, ere->rva);
+
+      /* For some reason the high bit in NAME is set.  */
+      name &=~ 0x80000000;
+
+      if (name > (size_t) (finfo->data_end - finfo->data))
+       overrun (finfo, _("directory entry name"));
+
+      ers = finfo->data + name;
+
+      re = (struct res_entry *) res_alloc (sizeof *re);
+      re->next = NULL;
+      re->id.named = 1;
+      length = getfi_16 (finfo, ers);
+      re->id.u.n.length = length;
+      re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar));
+      for (j = 0; j < length; j++)
+       re->id.u.n.name[j] = getfi_16 (finfo, ers + j * 2 + 2);
+
+      if (level == 0)
+       type = &re->id;
+
+      if ((rva & 0x80000000) != 0)
+       {
+         rva &=~ 0x80000000;
+         if (rva >= (size_t) (finfo->data_end - finfo->data))
+           overrun (finfo, _("named subdirectory"));
+         re->subdir = 1;
+         re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type,
+                                        level + 1);
+       }
+      else
+       {
+         if (rva >= (size_t) (finfo->data_end - finfo->data))
+           overrun (finfo, _("named resource"));
+         re->subdir = 0;
+         re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type);
+       }
+
+      *pp = re;
+      pp = &re->next;
+    }
+
+  for (i = 0; i < id_count; i++, ere++)
+    {
+      unsigned long name, rva;
+      struct res_entry *re;
+
+      if ((const bfd_byte *) ere >= finfo->data_end)
+       overrun (finfo, _("ID directory entry"));
+
+      name = getfi_32 (finfo, ere->name);
+      rva = getfi_32 (finfo, ere->rva);
+
+      re = (struct res_entry *) res_alloc (sizeof *re);
+      re->next = NULL;
+      re->id.named = 0;
+      re->id.u.id = name;
+
+      if (level == 0)
+       type = &re->id;
+
+      if ((rva & 0x80000000) != 0)
+       {
+         rva &=~ 0x80000000;
+         if (rva >= (size_t) (finfo->data_end - finfo->data))
+           overrun (finfo, _("ID subdirectory"));
+         re->subdir = 1;
+         re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type,
+                                        level + 1);
+       }
+      else
+       {
+         if (rva >= (size_t) (finfo->data_end - finfo->data))
+           overrun (finfo, _("ID resource"));
+         re->subdir = 0;
+         re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type);
+       }
+
+      *pp = re;
+      pp = &re->next;
+    }
+
+  return rd;
+}
+
+/* Read a resource data entry.  */
+
+static struct res_resource *
+read_coff_data_entry (data, finfo, type)
+     const bfd_byte *data;
+     const struct coff_file_info *finfo;
+     const struct res_id *type;
+{
+  const struct extern_res_data *erd;
+  struct res_resource *r;
+  unsigned long size, rva;
+  const bfd_byte *resdata;
+
+  if (type == NULL)
+    fatal (_("resource type unknown"));
+
+  if ((size_t) (finfo->data_end - data) < sizeof (struct extern_res_data))
+    overrun (finfo, _("data entry"));
+
+  erd = (const struct extern_res_data *) data;
+
+  size = getfi_32 (finfo, erd->size);
+  rva = getfi_32 (finfo, erd->rva);
+  if (rva < finfo->secaddr
+      || rva - finfo->secaddr >= (size_t) (finfo->data_end - finfo->data))
+    overrun (finfo, _("resource data"));
+
+  resdata = finfo->data + (rva - finfo->secaddr);
+
+  if (size > (size_t) (finfo->data_end - resdata))
+    overrun (finfo, _("resource data size"));
+
+  r = bin_to_res (*type, resdata, size, finfo->big_endian);
+
+  memset (&r->res_info, 0, sizeof (struct res_res_info));
+  r->coff_info.codepage = getfi_32 (finfo, erd->codepage);
+  r->coff_info.reserved = getfi_32 (finfo, erd->reserved);
+
+  return r;
+}
+\f
+/* This structure is used to build a list of bindata structures.  */
+
+struct bindata_build
+{
+  /* The data.  */
+  struct bindata *d;
+  /* The last structure we have added to the list.  */
+  struct bindata *last;
+  /* The size of the list as a whole.  */
+  unsigned long length;
+};
+
+/* This structure keeps track of information as we build the directory
+   tree.  */
+
+struct coff_write_info
+{
+  /* These fields are based on the BFD.  */
+  /* The BFD itself.  */
+  bfd *abfd;
+  /* Non-zero if the file is big endian.  */
+  int big_endian;
+  /* Pointer to section symbol used to build RVA relocs.  */
+  asymbol **sympp;
+
+  /* These fields are computed initially, and then not changed.  */
+  /* Length of directory tables and entries.  */
+  unsigned long dirsize;
+  /* Length of directory entry strings.  */
+  unsigned long dirstrsize;
+  /* Length of resource data entries.  */
+  unsigned long dataentsize;
+
+  /* These fields are updated as we add data.  */
+  /* Directory tables and entries.  */
+  struct bindata_build dirs;
+  /* Directory entry strings.  */
+  struct bindata_build dirstrs;
+  /* Resource data entries.  */
+  struct bindata_build dataents;
+  /* Actual resource data.  */
+  struct bindata_build resources;
+  /* Relocations.  */
+  arelent **relocs;
+  /* Number of relocations.  */
+  unsigned int reloc_count;
+};
+
+/* Macros to swap out values.  */
+
+#define putcwi_16(cwi, v, s) \
+  ((cwi->big_endian) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
+#define putcwi_32(cwi, v, s) \
+  ((cwi->big_endian) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
+
+static void coff_bin_sizes
+  PARAMS ((const struct res_directory *, struct coff_write_info *));
+static unsigned char *coff_alloc PARAMS ((struct bindata_build *, size_t));
+static void coff_to_bin
+  PARAMS ((const struct res_directory *, struct coff_write_info *));
+static void coff_res_to_bin
+  PARAMS ((const struct res_resource *, struct coff_write_info *));
+
+/* Write resources to a COFF file.  RESOURCES should already be
+   sorted.
+
+   Right now we always create a new file.  Someday we should also
+   offer the ability to merge resources into an existing file.  This
+   would require doing the basic work of objcopy, just modifying or
+   adding the .rsrc section.  */
+
+void
+write_coff_file (filename, target, resources)
+     const char *filename;
+     const char *target;
+     const struct res_directory *resources;
+{
+  bfd *abfd;
+  asection *sec;
+  struct coff_write_info cwi;
+  struct bindata *d;
+  unsigned long length, offset;
+
+  if (filename == NULL)
+    fatal (_("filename required for COFF output"));
+
+  abfd = bfd_openw (filename, target);
+  if (abfd == NULL)
+    bfd_fatal (filename);
+
+  if (! bfd_set_format (abfd, bfd_object))
+    bfd_fatal ("bfd_set_format");
+
+  /* FIXME: This is obviously i386 specific.  */
+  if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0))
+    bfd_fatal ("bfd_set_arch_mach");
+
+  if (! bfd_set_file_flags (abfd, HAS_SYMS | HAS_RELOC))
+    bfd_fatal ("bfd_set_file_flags");
+
+  sec = bfd_make_section (abfd, ".rsrc");
+  if (sec == NULL)
+    bfd_fatal ("bfd_make_section");
+
+  if (! bfd_set_section_flags (abfd, sec,
+                              (SEC_HAS_CONTENTS | SEC_ALLOC
+                               | SEC_LOAD | SEC_DATA)))
+    bfd_fatal ("bfd_set_section_flags");
+
+  if (! bfd_set_symtab (abfd, sec->symbol_ptr_ptr, 1))
+    bfd_fatal ("bfd_set_symtab");
+
+  /* Requiring this is probably a bug in BFD.  */
+  sec->output_section = sec;
+
+  /* The order of data in the .rsrc section is
+       resource directory tables and entries
+       resource directory strings
+       resource data entries
+       actual resource data
+
+     We build these different types of data in different lists.  */
+
+  cwi.abfd = abfd;
+  cwi.big_endian = bfd_big_endian (abfd);
+  cwi.sympp = sec->symbol_ptr_ptr;
+  cwi.dirsize = 0;
+  cwi.dirstrsize = 0;
+  cwi.dataentsize = 0;
+  cwi.dirs.d = NULL;
+  cwi.dirs.last = NULL;
+  cwi.dirs.length = 0;
+  cwi.dirstrs.d = NULL;
+  cwi.dirstrs.last = NULL;
+  cwi.dirstrs.length = 0;
+  cwi.dataents.d = NULL;
+  cwi.dataents.last = NULL;
+  cwi.dataents.length = 0;
+  cwi.resources.d = NULL;
+  cwi.resources.last = NULL;
+  cwi.resources.length = 0;
+  cwi.relocs = NULL;
+  cwi.reloc_count = 0;
+
+  /* Work out the sizes of the resource directory entries, so that we
+     know the various offsets we will need.  */
+  coff_bin_sizes (resources, &cwi);
+
+  /* Force the directory strings to be 32 bit aligned.  Every other
+     structure is 32 bit aligned anyhow.  */
+  cwi.dirstrsize = (cwi.dirstrsize + 3) &~ 3;
+
+  /* Actually convert the resources to binary.  */
+  coff_to_bin (resources, &cwi);
+
+  /* Add another 2 bytes to the directory strings if needed for
+     alignment.  */
+  if ((cwi.dirstrs.length & 3) != 0)
+    {
+      unsigned char *ex;
+
+      ex = coff_alloc (&cwi.dirstrs, 2);
+      ex[0] = 0;
+      ex[1] = 0;
+    }
+
+  /* Make sure that the data we built came out to the same size as we
+     calculated initially.  */
+  assert (cwi.dirs.length == cwi.dirsize);
+  assert (cwi.dirstrs.length == cwi.dirstrsize);
+  assert (cwi.dataents.length == cwi.dataentsize);
+
+  length = (cwi.dirsize
+           + cwi.dirstrsize
+           + cwi.dataentsize
+           + cwi.resources.length);
+
+  if (! bfd_set_section_size (abfd, sec, length))
+    bfd_fatal ("bfd_set_section_size");
+
+  bfd_set_reloc (abfd, sec, cwi.relocs, cwi.reloc_count);
+
+  offset = 0;
+  for (d = cwi.dirs.d; d != NULL; d = d->next)
+    {
+      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
+       bfd_fatal ("bfd_set_section_contents");
+      offset += d->length;
+    }
+  for (d = cwi.dirstrs.d; d != NULL; d = d->next)
+    {
+      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
+       bfd_fatal ("bfd_set_section_contents");
+      offset += d->length;
+    }
+  for (d = cwi.dataents.d; d != NULL; d = d->next)
+    {
+      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
+       bfd_fatal ("bfd_set_section_contents");
+      offset += d->length;
+    }
+  for (d = cwi.resources.d; d != NULL; d = d->next)
+    {
+      if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length))
+       bfd_fatal ("bfd_set_section_contents");
+      offset += d->length;
+    }
+
+  assert (offset == length);
+
+  if (! bfd_close (abfd))
+    bfd_fatal ("bfd_close");
+
+  /* We allocated the relocs array using malloc.  */
+  free (cwi.relocs);
+}
+
+/* Work out the sizes of the various fixed size resource directory
+   entries.  This updates fields in CWI.  */
+
+static void
+coff_bin_sizes (resdir, cwi)
+     const struct res_directory *resdir;
+     struct coff_write_info *cwi;
+{
+  const struct res_entry *re;
+
+  cwi->dirsize += sizeof (struct extern_res_directory);
+
+  for (re = resdir->entries; re != NULL; re = re->next)
+    {
+      cwi->dirsize += sizeof (struct extern_res_entry);
+
+      if (re->id.named)
+       cwi->dirstrsize += re->id.u.n.length * 2 + 2;
+
+      if (re->subdir)
+       coff_bin_sizes (re->u.dir, cwi);
+      else
+       cwi->dataentsize += sizeof (struct extern_res_data);
+    }
+}
+
+/* Allocate data for a particular list.  */
+
+static unsigned char *
+coff_alloc (bb, size)
+     struct bindata_build *bb;
+     size_t size;
+{
+  struct bindata *d;
+
+  d = (struct bindata *) reswr_alloc (sizeof *d);
+
+  d->next = NULL;
+  d->data = (unsigned char *) reswr_alloc (size);
+  d->length = size;
+
+  if (bb->d == NULL)
+    bb->d = d;
+  else
+    bb->last->next = d;
+  bb->last = d;
+  bb->length += size;
+
+  return d->data;
+}
+
+/* Convert the resource directory RESDIR to binary.  */
+
+static void
+coff_to_bin (resdir, cwi)
+     const struct res_directory *resdir;
+     struct coff_write_info *cwi;
+{
+  struct extern_res_directory *erd;
+  int ci, cn;
+  const struct res_entry *e;
+  struct extern_res_entry *ere;
+
+  /* Write out the directory table.  */
+
+  erd = ((struct extern_res_directory *)
+        coff_alloc (&cwi->dirs, sizeof (*erd)));
+
+  putcwi_32 (cwi, resdir->characteristics, erd->characteristics);
+  putcwi_32 (cwi, resdir->time, erd->time);
+  putcwi_16 (cwi, resdir->major, erd->major);
+  putcwi_16 (cwi, resdir->minor, erd->minor);
+
+  ci = 0;
+  cn = 0;
+  for (e = resdir->entries; e != NULL; e = e->next)
+    {
+      if (e->id.named)
+       ++cn;
+      else
+       ++ci;
+    }
+
+  putcwi_16 (cwi, cn, erd->name_count);
+  putcwi_16 (cwi, ci, erd->id_count);
+
+  /* Write out the data entries.  Note that we allocate space for all
+     the entries before writing them out.  That permits a recursive
+     call to work correctly when writing out subdirectories.  */
+
+  ere = ((struct extern_res_entry *)
+        coff_alloc (&cwi->dirs, (ci + cn) * sizeof (*ere)));
+  for (e = resdir->entries; e != NULL; e = e->next, ere++)
+    {
+      if (! e->id.named)
+       putcwi_32 (cwi, e->id.u.id, ere->name);
+      else
+       {
+         unsigned char *str;
+         int i;
+
+         /* For some reason existing files seem to have the high bit
+             set on the address of the name, although that is not
+             documented.  */
+         putcwi_32 (cwi,
+                    0x80000000 | (cwi->dirsize + cwi->dirstrs.length),
+                    ere->name);
+
+         str = coff_alloc (&cwi->dirstrs, e->id.u.n.length * 2 + 2);
+         putcwi_16 (cwi, e->id.u.n.length, str);
+         for (i = 0; i < e->id.u.n.length; i++)
+           putcwi_16 (cwi, e->id.u.n.name[i], str + i * 2 + 2);
+       }
+
+      if (e->subdir)
+       {
+         putcwi_32 (cwi, 0x80000000 | cwi->dirs.length, ere->rva);
+         coff_to_bin (e->u.dir, cwi);
+       }
+      else
+       {
+         putcwi_32 (cwi,
+                    cwi->dirsize + cwi->dirstrsize + cwi->dataents.length,
+                    ere->rva);
+
+         coff_res_to_bin (e->u.res, cwi);
+       }
+    }
+}
+
+/* Convert the resource RES to binary.  */
+
+static void
+coff_res_to_bin (res, cwi)
+     const struct res_resource *res;
+     struct coff_write_info *cwi;
+{
+  arelent *r;
+  struct extern_res_data *erd;
+  struct bindata *d;
+  unsigned long length;
+
+  /* For some reason, although every other address is a section
+     offset, the address of the resource data itself is an RVA.  That
+     means that we need to generate a relocation for it.  We allocate
+     the relocs array using malloc so that we can use realloc.  FIXME:
+     This relocation handling is correct for the i386, but probably
+     not for any other target.  */
+
+  r = (arelent *) reswr_alloc (sizeof (arelent));
+  r->sym_ptr_ptr = cwi->sympp;
+  r->address = cwi->dirsize + cwi->dirstrsize + cwi->dataents.length;
+  r->addend = 0;
+  r->howto = bfd_reloc_type_lookup (cwi->abfd, BFD_RELOC_RVA);
+  if (r->howto == NULL)
+    bfd_fatal (_("can't get BFD_RELOC_RVA relocation type"));
+
+  cwi->relocs = xrealloc (cwi->relocs,
+                         (cwi->reloc_count + 2) * sizeof (arelent *));
+  cwi->relocs[cwi->reloc_count] = r;
+  cwi->relocs[cwi->reloc_count + 1] = NULL;
+  ++cwi->reloc_count;
+
+  erd = (struct extern_res_data *) coff_alloc (&cwi->dataents, sizeof (*erd));
+
+  putcwi_32 (cwi,
+            (cwi->dirsize
+             + cwi->dirstrsize
+             + cwi->dataentsize
+             + cwi->resources.length),
+            erd->rva);
+  putcwi_32 (cwi, res->coff_info.codepage, erd->codepage);
+  putcwi_32 (cwi, res->coff_info.reserved, erd->reserved);
+
+  d = res_to_bin (res, cwi->big_endian);
+
+  if (cwi->resources.d == NULL)
+    cwi->resources.d = d;
+  else
+    cwi->resources.last->next = d;
+
+  length = 0;
+  for (; d->next != NULL; d = d->next)
+    length += d->length;
+  length += d->length;
+  cwi->resources.last = d;
+  cwi->resources.length += length;
+
+  putcwi_32 (cwi, length, erd->size);
+
+  /* Force the next resource to have 32 bit alignment.  */
+
+  if ((length & 3) != 0)
+    {
+      int add;
+      unsigned char *ex;
+
+      add = 4 - (length & 3);
+
+      ex = coff_alloc (&cwi->resources, add);
+      memset (ex, 0, add);
+    }
+}
diff --git a/binutils/resrc.c b/binutils/resrc.c
new file mode 100644 (file)
index 0000000..9ba3c11
--- /dev/null
@@ -0,0 +1,2265 @@
+/* resrc.c -- read and write Windows rc files.
+   Copyright 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file contains functions that read and write Windows rc files.
+   These are text files that represent resources.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "windres.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if defined (_WIN32) && ! defined (__CYGWIN32__)
+#define popen _popen
+#define pclose _pclose
+#endif
+
+/* The default preprocessor.  */
+
+#define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
+
+/* We read the directory entries in a cursor or icon file into
+   instances of this structure.  */
+
+struct icondir
+{
+  /* Width of image.  */
+  unsigned char width;
+  /* Height of image.  */
+  unsigned char height;
+  /* Number of colors in image.  */
+  unsigned char colorcount;
+  union
+  {
+    struct
+    {
+      /* Color planes.  */
+      unsigned short planes;
+      /* Bits per pixel.  */
+      unsigned short bits;
+    } icon;
+    struct
+    {
+      /* X coordinate of hotspot.  */
+      unsigned short xhotspot;
+      /* Y coordinate of hotspot.  */
+      unsigned short yhotspot;
+    } cursor;
+  } u;
+  /* Bytes in image.  */
+  unsigned long bytes;
+  /* File offset of image.  */
+  unsigned long offset;
+};
+
+/* The name of the rc file we are reading.  */
+
+char *rc_filename;
+
+/* The line number in the rc file.  */
+
+int rc_lineno;
+
+/* The pipe we are reading from, so that we can close it if we exit.  */
+
+static FILE *cpp_pipe;
+
+/* As we read the rc file, we attach information to this structure.  */
+
+static struct res_directory *resources;
+
+/* The number of cursor resources we have written out.  */
+
+static int cursors;
+
+/* The number of font resources we have written out.  */
+
+static int fonts;
+
+/* Font directory information.  */
+
+struct fontdir *fontdirs;
+
+/* Resource info to use for fontdirs.  */
+
+struct res_res_info fontdirs_resinfo;
+
+/* The number of icon resources we have written out.  */
+
+static int icons;
+
+/* Local functions.  */
+
+static void close_pipe PARAMS ((void));
+static void unexpected_eof PARAMS ((const char *));
+static int get_word PARAMS ((FILE *, const char *));
+static unsigned long get_long PARAMS ((FILE *, const char *));
+static void get_data
+  PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
+static void define_fontdirs PARAMS ((void));
+\f
+/* Read an rc file.  */
+
+struct res_directory *
+read_rc_file (filename, preprocessor, preprocargs, language)
+     const char *filename;
+     const char *preprocessor;
+     const char *preprocargs;
+     int language;
+{
+  char *cmd;
+
+  if (preprocessor == NULL)
+    preprocessor = DEFAULT_PREPROCESSOR;
+
+  if (preprocargs == NULL)
+    preprocargs = "";
+  if (filename == NULL)
+    filename = "-";
+
+  cmd = xmalloc (strlen (preprocessor)
+                + strlen (preprocargs)
+                + strlen (filename)
+                + 10);
+  sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
+
+  cpp_pipe = popen (cmd, FOPEN_RT);
+  if (cpp_pipe == NULL)
+    fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
+  free (cmd);
+
+  xatexit (close_pipe);
+
+  rc_filename = xstrdup (filename);
+  rc_lineno = 1;
+  if (language != -1)
+    rcparse_set_language (language);
+  yyin = cpp_pipe;
+  yyparse ();
+
+  if (pclose (cpp_pipe) != 0)
+    fprintf (stderr, _("%s: warning: preprocessor failed\n"), program_name);
+  cpp_pipe = NULL;
+
+  if (fontdirs != NULL)
+    define_fontdirs ();
+
+  free (rc_filename);
+  rc_filename = NULL;
+
+  return resources;
+}
+
+/* Close the pipe if it is open.  This is called via xatexit.  */
+
+void
+close_pipe ()
+{
+  if (cpp_pipe != NULL)
+    pclose (cpp_pipe);
+}
+
+/* Report an error while reading an rc file.  */
+
+void
+yyerror (msg)
+     const char *msg;
+{
+  fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
+}
+
+/* Issue a warning while reading an rc file.  */
+
+void
+rcparse_warning (msg)
+     const char *msg;
+{
+  fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
+}
+
+/* Die if we get an unexpected end of file.  */
+
+static void
+unexpected_eof (msg)
+     const char *msg;
+{
+  fatal (_("%s: unexpected EOF"), msg);
+}
+
+/* Read a 16 bit word from a file.  The data is assumed to be little
+   endian.  */
+
+static int
+get_word (e, msg)
+     FILE *e;
+     const char *msg;
+{
+  int b1, b2;
+
+  b1 = getc (e);
+  b2 = getc (e);
+  if (feof (e))
+    unexpected_eof (msg);
+  return ((b2 & 0xff) << 8) | (b1 & 0xff);
+}
+
+/* Read a 32 bit word from a file.  The data is assumed to be little
+   endian.  */
+
+static unsigned long
+get_long (e, msg)
+     FILE *e;
+     const char *msg;
+{
+  int b1, b2, b3, b4;
+
+  b1 = getc (e);
+  b2 = getc (e);
+  b3 = getc (e);
+  b4 = getc (e);
+  if (feof (e))
+    unexpected_eof (msg);
+  return (((((((b4 & 0xff) << 8)
+             | (b3 & 0xff)) << 8)
+           | (b2 & 0xff)) << 8)
+         | (b1 & 0xff));
+}
+
+/* Read data from a file.  This is a wrapper to do error checking.  */
+
+static void
+get_data (e, p, c, msg)
+     FILE *e;
+     unsigned char *p;
+     unsigned long c;
+     const char *msg;
+{
+  unsigned long got;
+
+  got = fread (p, 1, c, e);
+  if (got == c)
+    return;
+
+  fatal (_("%s: read of %lu returned %lu"), msg, c, got);
+}
+\f
+/* Define an accelerator resource.  */
+
+void
+define_accelerator (id, resinfo, data)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     struct accelerator *data;
+{
+  struct res_resource *r;
+
+  r = define_standard_resource (&resources, RT_ACCELERATOR, id,
+                               resinfo->language, 0);
+  r->type = RES_TYPE_ACCELERATOR;
+  r->u.acc = data;
+  r->res_info = *resinfo;
+}
+
+/* Define a bitmap resource.  Bitmap data is stored in a file.  The
+   first 14 bytes of the file are a standard header, which is not
+   included in the resource data.  */
+
+#define BITMAP_SKIP (14)
+
+void
+define_bitmap (id, resinfo, filename)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     const char *filename;
+{
+  FILE *e;
+  char *real_filename;
+  struct stat s;
+  unsigned char *data;
+  int i;
+  struct res_resource *r;
+
+  e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
+
+  if (stat (real_filename, &s) < 0)
+    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
+          strerror (errno));
+
+  data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
+
+  for (i = 0; i < BITMAP_SKIP; i++)
+    getc (e);
+
+  get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
+
+  fclose (e);
+  free (real_filename);
+
+  r = define_standard_resource (&resources, RT_BITMAP, id,
+                               resinfo->language, 0);
+
+  r->type = RES_TYPE_BITMAP;
+  r->u.data.length = s.st_size - BITMAP_SKIP;
+  r->u.data.data = data;
+  r->res_info = *resinfo;
+}
+
+/* Define a cursor resource.  A cursor file may contain a set of
+   bitmaps, each representing the same cursor at various different
+   resolutions.  They each get written out with a different ID.  The
+   real cursor resource is then a group resource which can be used to
+   select one of the actual cursors.  */
+
+void
+define_cursor (id, resinfo, filename)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     const char *filename;
+{
+  FILE *e;
+  char *real_filename;
+  int type, count, i;
+  struct icondir *icondirs;
+  int first_cursor;
+  struct res_resource *r;
+  struct group_cursor *first, **pp;
+
+  e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
+
+  /* A cursor file is basically an icon file.  The start of the file
+     is a three word structure.  The first word is ignored.  The
+     second word is the type of data.  The third word is the number of
+     entries.  */
+
+  get_word (e, real_filename);
+  type = get_word (e, real_filename);
+  count = get_word (e, real_filename);
+  if (type != 2)
+    fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
+
+  /* Read in the icon directory entries.  */
+
+  icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
+
+  for (i = 0; i < count; i++)
+    {
+      icondirs[i].width = getc (e);
+      icondirs[i].height = getc (e);
+      icondirs[i].colorcount = getc (e);
+      getc (e);
+      icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
+      icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
+      icondirs[i].bytes = get_long (e, real_filename);
+      icondirs[i].offset = get_long (e, real_filename);
+
+      if (feof (e))
+       unexpected_eof (real_filename);
+    }
+
+  /* Define each cursor as a unique resource.  */
+
+  first_cursor = cursors;
+
+  for (i = 0; i < count; i++)
+    {
+      unsigned char *data;
+      struct res_id name;
+      struct cursor *c;
+
+      if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
+       fatal (_("%s: fseek to %lu failed: %s"), real_filename,
+              icondirs[i].offset, strerror (errno));
+
+      data = (unsigned char *) res_alloc (icondirs[i].bytes);
+
+      get_data (e, data, icondirs[i].bytes, real_filename);
+
+      c = (struct cursor *) res_alloc (sizeof *c);
+      c->xhotspot = icondirs[i].u.cursor.xhotspot;
+      c->yhotspot = icondirs[i].u.cursor.yhotspot;
+      c->length = icondirs[i].bytes;
+      c->data = data;
+
+      ++cursors;
+
+      name.named = 0;
+      name.u.id = cursors;
+
+      r = define_standard_resource (&resources, RT_CURSOR, name,
+                                   resinfo->language, 0);
+      r->type = RES_TYPE_CURSOR;
+      r->u.cursor = c;
+      r->res_info = *resinfo;
+    }
+
+  fclose (e);
+  free (real_filename);
+
+  /* Define a cursor group resource.  */
+
+  first = NULL;
+  pp = &first;
+  for (i = 0; i < count; i++)
+    {
+      struct group_cursor *cg;
+
+      cg = (struct group_cursor *) res_alloc (sizeof *cg);
+      cg->next = NULL;
+      cg->width = icondirs[i].width;
+      cg->height = 2 * icondirs[i].height;
+
+      /* FIXME: What should these be set to?  */
+      cg->planes = 1;
+      cg->bits = 1;
+
+      cg->bytes = icondirs[i].bytes + 4;
+      cg->index = first_cursor + i + 1;
+
+      *pp = cg;
+      pp = &(*pp)->next;
+    }
+
+  free (icondirs);
+
+  r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
+                               resinfo->language, 0);
+  r->type = RES_TYPE_GROUP_CURSOR;
+  r->u.group_cursor = first;
+  r->res_info = *resinfo;
+}
+
+/* Define a dialog resource.  */
+
+void
+define_dialog (id, resinfo, dialog)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     const struct dialog *dialog;
+{
+  struct dialog *copy;
+  struct res_resource *r;
+
+  copy = (struct dialog *) res_alloc (sizeof *copy);
+  *copy = *dialog;
+
+  r = define_standard_resource (&resources, RT_DIALOG, id,
+                               resinfo->language, 0);
+  r->type = RES_TYPE_DIALOG;
+  r->u.dialog = copy;
+  r->res_info = *resinfo;
+}
+
+/* Define a dialog control.  This does not define a resource, but
+   merely allocates and fills in a structure.  */
+
+struct dialog_control *
+define_control (text, id, x, y, width, height, class, style, exstyle)
+     const char *text;
+     unsigned long id;
+     unsigned long x;
+     unsigned long y;
+     unsigned long width;
+     unsigned long height;
+     unsigned long class;
+     unsigned long style;
+     unsigned long exstyle;
+{
+  struct dialog_control *n;
+
+  n = (struct dialog_control *) res_alloc (sizeof *n);
+  n->next = NULL;
+  n->id = id;
+  n->style = style;
+  n->exstyle = exstyle;
+  n->x = x;
+  n->y = y;
+  n->width = width;
+  n->height = height;
+  n->class.named = 0;
+  n->class.u.id = class;
+  if (text != NULL)
+    res_string_to_id (&n->text, text);
+  else
+    {
+      n->text.named = 0;
+      n->text.u.id = 0;
+    }
+  n->data = NULL;
+  n->help = 0;
+
+  return n;
+}
+
+/* Define a font resource.  */
+
+void
+define_font (id, resinfo, filename)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     const char *filename;
+{
+  FILE *e;
+  char *real_filename;
+  struct stat s;
+  unsigned char *data;
+  struct res_resource *r;
+  long offset;
+  long fontdatalength;
+  unsigned char *fontdata;
+  struct fontdir *fd;
+  const char *device, *face;
+  struct fontdir **pp;
+
+  e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
+
+  if (stat (real_filename, &s) < 0)
+    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
+          strerror (errno));
+
+  data = (unsigned char *) res_alloc (s.st_size);
+
+  get_data (e, data, s.st_size, real_filename);
+
+  fclose (e);
+  free (real_filename);
+
+  r = define_standard_resource (&resources, RT_FONT, id,
+                               resinfo->language, 0);
+
+  r->type = RES_TYPE_FONT;
+  r->u.data.length = s.st_size;
+  r->u.data.data = data;
+  r->res_info = *resinfo;
+
+  /* For each font resource, we must add an entry in the FONTDIR
+     resource.  The FONTDIR resource includes some strings in the font
+     file.  To find them, we have to do some magic on the data we have
+     read.  */
+
+  offset = ((((((data[47] << 8)
+               | data[46]) << 8)
+             | data[45]) << 8)
+           | data[44]);
+  if (offset > 0 && offset < s.st_size)
+    device = (char *) data + offset;
+  else
+    device = "";
+
+  offset = ((((((data[51] << 8)
+               | data[50]) << 8)
+             | data[49]) << 8)
+           | data[48]);
+  if (offset > 0 && offset < s.st_size)
+    face = (char *) data + offset;
+  else
+    face = "";
+
+  ++fonts;
+
+  fontdatalength = 58 + strlen (device) + strlen (face);
+  fontdata = (unsigned char *) res_alloc (fontdatalength);
+  memcpy (fontdata, data, 56);
+  strcpy ((char *) fontdata + 56, device);
+  strcpy ((char *) fontdata + 57 + strlen (device), face);
+
+  fd = (struct fontdir *) res_alloc (sizeof *fd);
+  fd->next = NULL;
+  fd->index = fonts;
+  fd->length = fontdatalength;
+  fd->data = fontdata;
+
+  for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = fd;
+
+  /* For the single fontdirs resource, we always use the resource
+     information of the last font.  I don't know what else to do.  */
+  fontdirs_resinfo = *resinfo;
+}
+
+/* Define the fontdirs resource.  This is called after the entire rc
+   file has been parsed, if any font resources were seen.  */
+
+static void
+define_fontdirs ()
+{
+  struct res_resource *r;
+  struct res_id id;
+
+  id.named = 0;
+  id.u.id = 1;
+
+  r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
+
+  r->type = RES_TYPE_FONTDIR;
+  r->u.fontdir = fontdirs;
+  r->res_info = fontdirs_resinfo;
+}
+
+/* Define an icon resource.  An icon file may contain a set of
+   bitmaps, each representing the same icon at various different
+   resolutions.  They each get written out with a different ID.  The
+   real icon resource is then a group resource which can be used to
+   select one of the actual icon bitmaps.  */
+
+void
+define_icon (id, resinfo, filename)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     const char *filename;
+{
+  FILE *e;
+  char *real_filename;
+  int type, count, i;
+  struct icondir *icondirs;
+  int first_icon;
+  struct res_resource *r;
+  struct group_icon *first, **pp;
+
+  e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
+
+  /* The start of an icon file is a three word structure.  The first
+     word is ignored.  The second word is the type of data.  The third
+     word is the number of entries.  */
+
+  get_word (e, real_filename);
+  type = get_word (e, real_filename);
+  count = get_word (e, real_filename);
+  if (type != 1)
+    fatal (_("icon file `%s' does not contain icon data"), real_filename);
+
+  /* Read in the icon directory entries.  */
+
+  icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
+
+  for (i = 0; i < count; i++)
+    {
+      icondirs[i].width = getc (e);
+      icondirs[i].height = getc (e);
+      icondirs[i].colorcount = getc (e);
+      getc (e);
+      icondirs[i].u.icon.planes = get_word (e, real_filename);
+      icondirs[i].u.icon.bits = get_word (e, real_filename);
+      icondirs[i].bytes = get_long (e, real_filename);
+      icondirs[i].offset = get_long (e, real_filename);
+
+      if (feof (e))
+       unexpected_eof (real_filename);
+    }
+
+  /* Define each icon as a unique resource.  */
+
+  first_icon = icons;
+
+  for (i = 0; i < count; i++)
+    {
+      unsigned char *data;
+      struct res_id name;
+
+      if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
+       fatal (_("%s: fseek to %lu failed: %s"), real_filename,
+              icondirs[i].offset, strerror (errno));
+
+      data = (unsigned char *) res_alloc (icondirs[i].bytes);
+
+      get_data (e, data, icondirs[i].bytes, real_filename);
+
+      ++icons;
+
+      name.named = 0;
+      name.u.id = icons;
+
+      r = define_standard_resource (&resources, RT_ICON, name,
+                                   resinfo->language, 0);
+      r->type = RES_TYPE_ICON;
+      r->u.data.length = icondirs[i].bytes;
+      r->u.data.data = data;
+      r->res_info = *resinfo;
+    }
+
+  fclose (e);
+  free (real_filename);
+
+  /* Define an icon group resource.  */
+
+  first = NULL;
+  pp = &first;
+  for (i = 0; i < count; i++)
+    {
+      struct group_icon *cg;
+
+      /* For some reason, at least in some files the planes and bits
+         are zero.  We instead set them from the color.  This is
+         copied from rcl.  */
+
+      cg = (struct group_icon *) res_alloc (sizeof *cg);
+      cg->next = NULL;
+      cg->width = icondirs[i].width;
+      cg->height = icondirs[i].height;
+      cg->colors = icondirs[i].colorcount;
+
+      cg->planes = 1;
+      cg->bits = 0;
+      while ((1 << cg->bits) < cg->colors)
+       ++cg->bits;
+
+      cg->bytes = icondirs[i].bytes;
+      cg->index = first_icon + i + 1;
+
+      *pp = cg;
+      pp = &(*pp)->next;
+    }
+
+  free (icondirs);
+
+  r = define_standard_resource (&resources, RT_GROUP_ICON, id,
+                               resinfo->language, 0);
+  r->type = RES_TYPE_GROUP_ICON;
+  r->u.group_icon = first;
+  r->res_info = *resinfo;
+}
+
+/* Define a menu resource.  */
+
+void
+define_menu (id, resinfo, menuitems)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     struct menuitem *menuitems;
+{
+  struct menu *m;
+  struct res_resource *r;
+
+  m = (struct menu *) res_alloc (sizeof *m);
+  m->items = menuitems;
+  m->help = 0;
+
+  r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
+  r->type = RES_TYPE_MENU;
+  r->u.menu = m;
+  r->res_info = *resinfo;
+}
+
+/* Define a menu item.  This does not define a resource, but merely
+   allocates and fills in a structure.  */
+
+struct menuitem *
+define_menuitem (text, menuid, type, state, help, menuitems)
+     const char *text;
+     int menuid;
+     unsigned long type;
+     unsigned long state;
+     unsigned long help;
+     struct menuitem *menuitems;
+{
+  struct menuitem *mi;
+
+  mi = (struct menuitem *) res_alloc (sizeof *mi);
+  mi->next = NULL;
+  mi->type = type;
+  mi->state = state;
+  mi->id = menuid;
+  if (text == NULL)
+    mi->text = NULL;
+  else
+    unicode_from_ascii ((int *) NULL, &mi->text, text);
+  mi->help = help;
+  mi->popup = menuitems;
+  return mi;
+}
+
+/* Define a messagetable resource.  */
+
+void
+define_messagetable (id, resinfo, filename)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     const char *filename;
+{
+  FILE *e;
+  char *real_filename;
+  struct stat s;
+  unsigned char *data;
+  struct res_resource *r;
+
+  e = open_file_search (filename, FOPEN_RB, "messagetable file",
+                       &real_filename);
+
+  if (stat (real_filename, &s) < 0)
+    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
+          strerror (errno));
+
+  data = (unsigned char *) res_alloc (s.st_size);
+
+  get_data (e, data, s.st_size, real_filename);
+
+  fclose (e);
+  free (real_filename);
+
+  r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
+                               resinfo->language, 0);
+
+  r->type = RES_TYPE_MESSAGETABLE;
+  r->u.data.length = s.st_size;
+  r->u.data.data = data;
+  r->res_info = *resinfo;
+}
+
+/* Define an rcdata resource.  */
+
+void
+define_rcdata (id, resinfo, data)
+     struct res_id id;
+     const struct res_res_info *resinfo;
+     struct rcdata_item *data;
+{
+  struct res_resource *r;
+
+  r = define_standard_resource (&resources, RT_RCDATA, id,
+                               resinfo->language, 0);
+  r->type = RES_TYPE_RCDATA;
+  r->u.rcdata = data;
+  r->res_info = *resinfo;
+}
+
+/* Create an rcdata item holding a string.  */
+
+struct rcdata_item *
+define_rcdata_string (string, len)
+     const char *string;
+     unsigned long len;
+{
+  struct rcdata_item *ri;
+  char *s;
+
+  ri = (struct rcdata_item *) res_alloc (sizeof *ri);
+  ri->next = NULL;
+  ri->type = RCDATA_STRING;
+  ri->u.string.length = len;
+  s = (char *) res_alloc (len);
+  memcpy (s, string, len);
+  ri->u.string.s = s;
+
+  return ri;
+}
+
+/* Create an rcdata item holding a number.  */
+
+struct rcdata_item *
+define_rcdata_number (val, dword)
+     unsigned long val;
+     int dword;
+{
+  struct rcdata_item *ri;
+
+  ri = (struct rcdata_item *) res_alloc (sizeof *ri);
+  ri->next = NULL;
+  ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
+  ri->u.word = val;
+
+  return ri;
+}
+
+/* Define a stringtable resource.  This is called for each string
+   which appears in a STRINGTABLE statement.  */
+
+void
+define_stringtable (resinfo, stringid, string)
+     const struct res_res_info *resinfo;
+     unsigned long stringid;
+     const char *string;
+{
+  struct res_id id;
+  struct res_resource *r;
+
+  id.named = 0;
+  id.u.id = (stringid >> 4) + 1;
+  r = define_standard_resource (&resources, RT_STRING, id,
+                               resinfo->language, 1);
+
+  if (r->type == RES_TYPE_UNINITIALIZED)
+    {
+      int i;
+
+      r->type = RES_TYPE_STRINGTABLE;
+      r->u.stringtable = ((struct stringtable *)
+                         res_alloc (sizeof (struct stringtable)));
+      for (i = 0; i < 16; i++)
+       {
+         r->u.stringtable->strings[i].length = 0;
+         r->u.stringtable->strings[i].string = NULL;
+       }
+
+      r->res_info = *resinfo;
+    }
+
+  unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
+                     &r->u.stringtable->strings[stringid & 0xf].string,
+                     string);
+}
+
+/* Define a user data resource where the data is in the rc file.  */
+
+void
+define_user_data (id, type, resinfo, data)
+     struct res_id id;
+     struct res_id type;
+     const struct res_res_info *resinfo;
+     struct rcdata_item *data;
+{
+  struct res_id ids[3];
+  struct res_resource *r;
+
+  ids[0] = type;
+  ids[1] = id;
+  ids[2].named = 0;
+  ids[2].u.id = resinfo->language;
+
+  r = define_resource (&resources, 3, ids, 0);
+  r->type = RES_TYPE_USERDATA;
+  r->u.userdata = data;
+  r->res_info = *resinfo;
+}
+
+/* Define a user data resource where the data is in a file.  */
+
+void
+define_user_file (id, type, resinfo, filename)
+     struct res_id id;
+     struct res_id type;
+     const struct res_res_info *resinfo;
+     const char *filename;
+{
+  FILE *e;
+  char *real_filename;
+  struct stat s;
+  unsigned char *data;
+  struct res_id ids[3];
+  struct res_resource *r;
+
+  e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
+
+  if (stat (real_filename, &s) < 0)
+    fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
+          strerror (errno));
+
+  data = (unsigned char *) res_alloc (s.st_size);
+
+  get_data (e, data, s.st_size, real_filename);
+
+  fclose (e);
+  free (real_filename);
+
+  ids[0] = type;
+  ids[1] = id;
+  ids[2].named = 0;
+  ids[2].u.id = resinfo->language;
+
+  r = define_resource (&resources, 3, ids, 0);
+  r->type = RES_TYPE_USERDATA;
+  r->u.userdata = ((struct rcdata_item *)
+                  res_alloc (sizeof (struct rcdata_item)));
+  r->u.userdata->next = NULL;
+  r->u.userdata->type = RCDATA_BUFFER;
+  r->u.userdata->u.buffer.length = s.st_size;
+  r->u.userdata->u.buffer.data = data;
+  r->res_info = *resinfo;
+}
+
+/* Define a versioninfo resource.  */
+
+void
+define_versioninfo (id, language, fixedverinfo, verinfo)
+     struct res_id id;
+     int language;
+     struct fixed_versioninfo *fixedverinfo;
+     struct ver_info *verinfo;
+{
+  struct res_resource *r;
+
+  r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
+  r->type = RES_TYPE_VERSIONINFO;
+  r->u.versioninfo = ((struct versioninfo *)
+                     res_alloc (sizeof (struct versioninfo)));
+  r->u.versioninfo->fixed = fixedverinfo;
+  r->u.versioninfo->var = verinfo;
+  r->res_info.language = language;
+}
+
+/* Add string version info to a list of version information.  */
+
+struct ver_info *
+append_ver_stringfileinfo (verinfo, language, strings)
+     struct ver_info *verinfo;
+     const char *language;
+     struct ver_stringinfo *strings;
+{
+  struct ver_info *vi, **pp;
+
+  vi = (struct ver_info *) res_alloc (sizeof *vi);
+  vi->next = NULL;
+  vi->type = VERINFO_STRING;
+  unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
+  vi->u.string.strings = strings;
+
+  for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = vi;
+
+  return verinfo;
+}
+
+/* Add variable version info to a list of version information.  */
+
+struct ver_info *
+append_ver_varfileinfo (verinfo, key, var)
+     struct ver_info *verinfo;
+     const char *key;
+     struct ver_varinfo *var;
+{
+  struct ver_info *vi, **pp;
+
+  vi = (struct ver_info *) res_alloc (sizeof *vi);
+  vi->next = NULL;
+  vi->type = VERINFO_VAR;
+  unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
+  vi->u.var.var = var;
+
+  for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = vi;
+
+  return verinfo;
+}
+
+/* Append version string information to a list.  */
+
+struct ver_stringinfo *
+append_verval (strings, key, value)
+     struct ver_stringinfo *strings;
+     const char *key;
+     const char *value;
+{
+  struct ver_stringinfo *vs, **pp;
+
+  vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
+  vs->next = NULL;
+  unicode_from_ascii ((int *) NULL, &vs->key, key);
+  unicode_from_ascii ((int *) NULL, &vs->value, value);
+
+  for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = vs;
+
+  return strings;
+}
+
+/* Append version variable information to a list.  */
+
+struct ver_varinfo *
+append_vertrans (var, language, charset)
+     struct ver_varinfo *var;
+     unsigned long language;
+     unsigned long charset;
+{
+  struct ver_varinfo *vv, **pp;
+
+  vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
+  vv->next = NULL;
+  vv->language = language;
+  vv->charset = charset;
+
+  for (pp = &var; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = vv;
+
+  return var;
+}
+\f
+/* Local functions used to write out an rc file.  */
+
+static void indent PARAMS ((FILE *, int));
+static void write_rc_directory
+  PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
+          const struct res_id *, int *, int));
+static void write_rc_subdir
+  PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
+          const struct res_id *, int *, int));
+static void write_rc_resource
+  PARAMS ((FILE *, const struct res_id *, const struct res_id *,
+          const struct res_resource *, int *));
+static void write_rc_accelerators
+  PARAMS ((FILE *, const struct accelerator *));
+static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
+static void write_rc_group_cursor
+  PARAMS ((FILE *, const struct group_cursor *));
+static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
+static void write_rc_dialog_control
+  PARAMS ((FILE *, const struct dialog_control *));
+static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
+static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
+static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
+static void write_rc_menuitems
+  PARAMS ((FILE *, const struct menuitem *, int, int));
+static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
+static void write_rc_stringtable
+  PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
+static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
+static void write_rc_filedata
+  PARAMS ((FILE *, unsigned long, const unsigned char *));
+
+/* Indent a given number of spaces.  */
+
+static void
+indent (e, c)
+     FILE *e;
+     int c;
+{
+  int i;
+
+  for (i = 0; i < c; i++)
+    putc (' ', e);
+}
+
+/* Dump the resources we have read in the format of an rc file.
+
+   Actually, we don't use the format of an rc file, because it's way
+   too much of a pain--for example, we'd have to write icon resources
+   into a file and refer to that file.  We just generate a readable
+   format that kind of looks like an rc file, and is useful for
+   understanding the contents of a resource file.  Someday we may want
+   to generate an rc file which the rc compiler can read; if that day
+   comes, this code will have to be fixed up.  */
+
+void
+write_rc_file (filename, resources)
+     const char *filename;
+     const struct res_directory *resources;
+{
+  FILE *e;
+  int language;
+
+  if (filename == NULL)
+    e = stdout;
+  else
+    {
+      e = fopen (filename, FOPEN_WT);
+      if (e == NULL)
+       fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
+    }
+
+  language = -1;
+  write_rc_directory (e, resources, (const struct res_id *) NULL,
+                     (const struct res_id *) NULL, &language, 1);
+}
+
+/* Write out a directory.  E is the file to write to.  RD is the
+   directory.  TYPE is a pointer to the level 1 ID which serves as the
+   resource type.  NAME is a pointer to the level 2 ID which serves as
+   an individual resource name.  LANGUAGE is a pointer to the current
+   language.  LEVEL is the level in the tree.  */
+
+static void
+write_rc_directory (e, rd, type, name, language, level)
+     FILE *e;
+     const struct res_directory *rd;
+     const struct res_id *type;
+     const struct res_id *name;
+     int *language;
+     int level;
+{
+  const struct res_entry *re;
+
+  /* Print out some COFF information that rc files can't represent.  */
+
+  if (rd->time != 0)
+    fprintf (e, "// Time stamp: %lu\n", rd->time);
+  if (rd->characteristics != 0)
+    fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
+  if (rd->major != 0 || rd->minor != 0)
+    fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
+
+  for (re = rd->entries;  re != NULL; re = re->next)
+    {
+      switch (level)
+       {
+       case 1:
+         /* If we're at level 1, the key of this resource is the
+             type.  This normally duplicates the information we have
+             stored with the resource itself, but we need to remember
+             the type if this is a user define resource type.  */
+         type = &re->id;
+         break;
+
+       case 2:
+         /* If we're at level 2, the key of this resource is the name
+            we are going to use in the rc printout. */
+         name = &re->id;
+         break;
+
+       case 3:
+         /* If we're at level 3, then this key represents a language.
+            Use it to update the current language.  */
+         if (! re->id.named
+             && re->id.u.id != (unsigned long) (unsigned int) *language
+             && (re->id.u.id & 0xffff) == re->id.u.id)
+           {
+             fprintf (e, "LANGUAGE %lu, %lu\n",
+                      re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
+             *language = re->id.u.id;
+           }
+         break;
+
+       default:
+         break;
+       }
+
+      if (re->subdir)
+       write_rc_subdir (e, re, type, name, language, level);
+      else
+       {
+         if (level == 3)
+           {
+             /* This is the normal case: the three levels are
+                 TYPE/NAME/LANGUAGE.  NAME will have been set at level
+                 2, and represents the name to use.  We probably just
+                 set LANGUAGE, and it will probably match what the
+                 resource itself records if anything.  */
+             write_rc_resource (e, type, name, re->u.res, language);
+           }
+         else
+           {
+             fprintf (e, "// Resource at unexpected level %d\n", level);
+             write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
+                                language);
+           }
+       }
+    }
+}
+
+/* Write out a subdirectory entry.  E is the file to write to.  RE is
+   the subdirectory entry.  TYPE and NAME are pointers to higher level
+   IDs, or NULL.  LANGUAGE is a pointer to the current language.
+   LEVEL is the level in the tree.  */
+
+static void
+write_rc_subdir (e, re, type, name, language, level)
+     FILE *e;
+     const struct res_entry *re;
+     const struct res_id *type;
+     const struct res_id *name;
+     int *language;
+     int level;
+{
+  fprintf (e, "\n");
+  switch (level)
+    {
+    case 1:
+      fprintf (e, "// Type: ");
+      if (re->id.named)
+       res_id_print (e, re->id, 1);
+      else
+       {
+         const char *s;
+
+         switch (re->id.u.id)
+           {
+           case RT_CURSOR: s = "cursor"; break;
+           case RT_BITMAP: s = "bitmap"; break;
+           case RT_ICON: s = "icon"; break;
+           case RT_MENU: s = "menu"; break;
+           case RT_DIALOG: s = "dialog"; break;
+           case RT_STRING: s = "stringtable"; break;
+           case RT_FONTDIR: s = "fontdir"; break;
+           case RT_FONT: s = "font"; break;
+           case RT_ACCELERATOR: s = "accelerators"; break;
+           case RT_RCDATA: s = "rcdata"; break;
+           case RT_MESSAGETABLE: s = "messagetable"; break;
+           case RT_GROUP_CURSOR: s = "group cursor"; break;
+           case RT_GROUP_ICON: s = "group icon"; break;
+           case RT_VERSION: s = "version"; break;
+           case RT_DLGINCLUDE: s = "dlginclude"; break;
+           case RT_PLUGPLAY: s = "plugplay"; break;
+           case RT_VXD: s = "vxd"; break;
+           case RT_ANICURSOR: s = "anicursor"; break;
+           case RT_ANIICON: s = "aniicon"; break;
+           default: s = NULL; break;
+           }
+
+         if (s != NULL)
+           fprintf (e, "%s", s);
+         else
+           res_id_print (e, re->id, 1);
+       }
+      fprintf (e, "\n");
+      break;
+
+    case 2:
+      fprintf (e, "// Name: ");
+      res_id_print (e, re->id, 1);
+      fprintf (e, "\n");
+      break;
+
+    case 3:
+      fprintf (e, "// Language: ");
+      res_id_print (e, re->id, 1);
+      fprintf (e, "\n");
+      break;
+
+    default:
+      fprintf (e, "// Level %d: ", level);
+      res_id_print (e, re->id, 1);
+      fprintf (e, "\n");
+    }          
+
+  write_rc_directory (e, re->u.dir, type, name, language, level + 1);
+}
+
+/* Write out a single resource.  E is the file to write to.  TYPE is a
+   pointer to the type of the resource.  NAME is a pointer to the name
+   of the resource; it will be NULL if there is a level mismatch.  RES
+   is the resource data.  LANGUAGE is a pointer to the current
+   language.  */
+
+static void
+write_rc_resource (e, type, name, res, language)
+     FILE *e;
+     const struct res_id *type;
+     const struct res_id *name;
+     const struct res_resource *res;
+     int *language;
+{
+  const char *s;
+  int rt;
+  int menuex = 0;
+
+  fprintf (e, "\n");
+
+  switch (res->type)
+    {
+    default:
+      abort ();
+
+    case RES_TYPE_ACCELERATOR:
+      s = "ACCELERATOR";
+      rt = RT_ACCELERATOR;
+      break;
+
+    case RES_TYPE_BITMAP:
+      s = "BITMAP";
+      rt = RT_BITMAP;
+      break;
+
+    case RES_TYPE_CURSOR:
+      s = "CURSOR";
+      rt = RT_CURSOR;
+      break;
+
+    case RES_TYPE_GROUP_CURSOR:
+      s = "GROUP_CURSOR";
+      rt = RT_GROUP_CURSOR;
+      break;
+
+    case RES_TYPE_DIALOG:
+      if (extended_dialog (res->u.dialog))
+       s = "DIALOGEX";
+      else
+       s = "DIALOG";
+      rt = RT_DIALOG;
+      break;
+
+    case RES_TYPE_FONT:
+      s = "FONT";
+      rt = RT_FONT;
+      break;
+
+    case RES_TYPE_FONTDIR:
+      s = "FONTDIR";
+      rt = RT_FONTDIR;
+      break;
+
+    case RES_TYPE_ICON:
+      s = "ICON";
+      rt = RT_ICON;
+      break;
+
+    case RES_TYPE_GROUP_ICON:
+      s = "GROUP_ICON";
+      rt = RT_GROUP_ICON;
+      break;
+
+    case RES_TYPE_MENU:
+      if (extended_menu (res->u.menu))
+       {
+         s = "MENUEX";
+         menuex = 1;
+       }
+      else
+       {
+         s = "MENU";
+         menuex = 0;
+       }
+      rt = RT_MENU;
+      break;
+
+    case RES_TYPE_MESSAGETABLE:
+      s = "MESSAGETABLE";
+      rt = RT_MESSAGETABLE;
+      break;
+
+    case RES_TYPE_RCDATA:
+      s = "RCDATA";
+      rt = RT_RCDATA;
+      break;
+
+    case RES_TYPE_STRINGTABLE:
+      s = "STRINGTABLE";
+      rt = RT_STRING;
+      break;
+
+    case RES_TYPE_USERDATA:
+      s = NULL;
+      rt = 0;
+      break;
+
+    case RES_TYPE_VERSIONINFO:
+      s = "VERSIONINFO";
+      rt = RT_VERSION;
+      break;
+    }
+
+  if (rt != 0
+      && type != NULL
+      && (type->named || type->u.id != (unsigned long) rt))
+    {
+      fprintf (e, "// Unexpected resource type mismatch: ");
+      res_id_print (e, *type, 1);
+      fprintf (e, " != %d", rt);
+    }
+
+  if (res->coff_info.codepage != 0)
+    fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
+  if (res->coff_info.reserved != 0)
+    fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
+
+  if (name != NULL)
+    res_id_print (e, *name, 0);
+  else
+    fprintf (e, "??Unknown-Name??");
+
+  fprintf (e, " ");
+  if (s != NULL)
+    fprintf (e, "%s", s);
+  else if (type != NULL)
+    res_id_print (e, *type, 0);
+  else
+    fprintf (e, "??Unknown-Type??");
+
+  if (res->res_info.memflags != 0)
+    {
+      if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
+       fprintf (e, " MOVEABLE");
+      if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
+       fprintf (e, " PURE");
+      if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
+       fprintf (e, " PRELOAD");
+      if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
+       fprintf (e, " DISCARDABLE");
+    }
+
+  if (res->type == RES_TYPE_DIALOG)
+    {
+      fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
+              res->u.dialog->width, res->u.dialog->height);
+      if (res->u.dialog->ex != NULL
+         && res->u.dialog->ex->help != 0)
+       fprintf (e, ", %lu", res->u.dialog->ex->help);
+    }
+
+  fprintf (e, "\n");
+
+  if ((res->res_info.language != 0 && res->res_info.language != *language)
+      || res->res_info.characteristics != 0
+      || res->res_info.version != 0)
+    {
+      int modifiers;
+
+      switch (res->type)
+       {
+       case RES_TYPE_ACCELERATOR:
+       case RES_TYPE_DIALOG:
+       case RES_TYPE_MENU:
+       case RES_TYPE_RCDATA:
+       case RES_TYPE_STRINGTABLE:
+         modifiers = 1;
+         break;
+
+       default:
+         modifiers = 0;
+         break;
+       }
+
+      if (res->res_info.language != 0 && res->res_info.language != *language)
+       fprintf (e, "%sLANGUAGE %d, %d\n",
+                modifiers ? "// " : "",
+                res->res_info.language & 0xff,
+                (res->res_info.language >> 8) & 0xff);
+      if (res->res_info.characteristics != 0)
+       fprintf (e, "%sCHARACTERISTICS %lu\n",
+                modifiers ? "// " : "",
+                res->res_info.characteristics);
+      if (res->res_info.version != 0)
+       fprintf (e, "%sVERSION %lu\n",
+                modifiers ? "// " : "",
+                res->res_info.version);
+    }
+
+  switch (res->type)
+    {
+    default:
+      abort ();
+
+    case RES_TYPE_ACCELERATOR:
+      write_rc_accelerators (e, res->u.acc);
+      break;
+
+    case RES_TYPE_CURSOR:
+      write_rc_cursor (e, res->u.cursor);
+      break;
+
+    case RES_TYPE_GROUP_CURSOR:
+      write_rc_group_cursor (e, res->u.group_cursor);
+      break;
+
+    case RES_TYPE_DIALOG:
+      write_rc_dialog (e, res->u.dialog);
+      break;
+
+    case RES_TYPE_FONTDIR:
+      write_rc_fontdir (e, res->u.fontdir);
+      break;
+
+    case RES_TYPE_GROUP_ICON:
+      write_rc_group_icon (e, res->u.group_icon);
+      break;
+
+    case RES_TYPE_MENU:
+      write_rc_menu (e, res->u.menu, menuex);
+      break;
+
+    case RES_TYPE_RCDATA:
+      write_rc_rcdata (e, res->u.rcdata, 0);
+      break;
+
+    case RES_TYPE_STRINGTABLE:
+      write_rc_stringtable (e, name, res->u.stringtable);
+      break;
+
+    case RES_TYPE_USERDATA:
+      write_rc_rcdata (e, res->u.userdata, 0);
+      break;
+
+    case RES_TYPE_VERSIONINFO:
+      write_rc_versioninfo (e, res->u.versioninfo);
+      break;
+
+    case RES_TYPE_BITMAP:
+    case RES_TYPE_FONT:
+    case RES_TYPE_ICON:
+    case RES_TYPE_MESSAGETABLE:
+      write_rc_filedata (e, res->u.data.length, res->u.data.data);
+      break;
+    }
+}
+
+/* Write out accelerator information.  */
+
+static void
+write_rc_accelerators (e, accelerators)
+     FILE *e;
+     const struct accelerator *accelerators;
+{
+  const struct accelerator *acc;
+
+  fprintf (e, "BEGIN\n");
+  for (acc = accelerators; acc != NULL; acc = acc->next)
+    {
+      int printable;
+
+      fprintf (e, "  ");
+
+      if ((acc->key & 0x7f) == acc->key
+         && isprint ((unsigned char) acc->key)
+         && (acc->flags & ACC_VIRTKEY) == 0)
+       {
+         fprintf (e, "\"%c\"", acc->key);
+         printable = 1;
+       }
+      else
+       {
+         fprintf (e, "%d", acc->key);
+         printable = 0;
+       }
+
+      fprintf (e, ", %d", acc->id);
+
+      if (! printable)
+       {
+         if ((acc->flags & ACC_VIRTKEY) != 0)
+           fprintf (e, ", VIRTKEY");
+         else
+           fprintf (e, ", ASCII");
+       }
+
+      if ((acc->flags & ACC_SHIFT) != 0)
+       fprintf (e, ", SHIFT");
+      if ((acc->flags & ACC_CONTROL) != 0)
+       fprintf (e, ", CONTROL");
+      if ((acc->flags & ACC_ALT) != 0)
+       fprintf (e, ", ALT");
+
+      fprintf (e, "\n");
+    }
+
+  fprintf (e, "END\n");
+}
+
+/* Write out cursor information.  This would normally be in a separate
+   file, which the rc file would include.  */
+
+static void
+write_rc_cursor (e, cursor)
+     FILE *e;
+     const struct cursor *cursor;
+{
+  fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
+          cursor->yhotspot);
+  write_rc_filedata (e, cursor->length, cursor->data);
+}
+
+/* Write out group cursor data.  This would normally be built from the
+   cursor data.  */
+
+static void
+write_rc_group_cursor (e, group_cursor)
+     FILE *e;
+     const struct group_cursor *group_cursor;
+{
+  const struct group_cursor *gc;
+
+  for (gc = group_cursor; gc != NULL; gc = gc->next)
+    {
+      fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
+            gc->width, gc->height, gc->planes, gc->bits);
+      fprintf (e, "// data bytes: %lu; index: %d\n",
+              gc->bytes, gc->index);
+    }
+}
+
+/* Write dialog data.  */
+
+static void
+write_rc_dialog (e, dialog)
+     FILE *e;
+     const struct dialog *dialog;
+{
+  const struct dialog_control *control;
+
+  if (dialog->style != 0)
+    fprintf (e, "STYLE 0x%lx\n", dialog->style);
+  if (dialog->exstyle != 0)
+    fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
+  if ((dialog->class.named && dialog->class.u.n.length > 0)
+      || dialog->class.u.id != 0)
+    {
+      fprintf (e, "CLASS ");
+      res_id_print (e, dialog->class, 0);
+      fprintf (e, "\n");
+    }
+  if (dialog->caption != NULL)
+    {
+      fprintf (e, "CAPTION \"");
+      unicode_print (e, dialog->caption, -1);
+      fprintf (e, "\"\n");
+    }
+  if ((dialog->menu.named && dialog->menu.u.n.length > 0)
+      || dialog->menu.u.id != 0)
+    {
+      fprintf (e, "MENU ");
+      res_id_print (e, dialog->menu, 0);
+      fprintf (e, "\n");
+    }
+  if (dialog->font != NULL)
+    {
+      fprintf (e, "FONT %d, \"", dialog->pointsize);
+      unicode_print (e, dialog->font, -1);
+      fprintf (e, "\"");
+      if (dialog->ex != NULL
+         && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
+       fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
+      fprintf (e, "\n");
+    }
+
+  fprintf (e, "BEGIN\n");
+
+  for (control = dialog->controls; control != NULL; control = control->next)
+    write_rc_dialog_control (e, control);
+
+  fprintf (e, "END\n");
+}
+
+/* For each predefined control keyword, this table provides the class
+   and the style.  */
+
+struct control_info
+{
+  const char *name;
+  unsigned short class;
+  unsigned long style;
+};
+
+static const struct control_info control_info[] =
+{
+  { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
+  { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
+  { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
+  { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
+  { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
+  { "CTEXT", CTL_STATIC, SS_CENTER },
+  { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
+  { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
+  { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
+  { "ICON", CTL_STATIC, SS_ICON },
+  { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
+  { "LTEXT", CTL_STATIC, SS_LEFT },
+  { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
+  { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
+  { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
+  { "RTEXT", CTL_STATIC, SS_RIGHT },
+  { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
+  { "STATE3", CTL_BUTTON, BS_3STATE },
+  /* It's important that USERBUTTON come after all the other button
+     types, so that it won't be matched too early.  */
+  { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
+  { NULL, 0, 0 }
+};
+
+/* Write a dialog control.  */
+
+static void
+write_rc_dialog_control (e, control)
+     FILE *e;
+     const struct dialog_control *control;
+{
+  const struct control_info *ci;
+
+  fprintf (e, "  ");
+
+  if (control->class.named)
+    ci = NULL;
+  else
+    {
+      for (ci = control_info; ci->name != NULL; ++ci)
+       if (ci->class == control->class.u.id
+           && (ci->style == (unsigned long) -1
+               || ci->style == (control->style & 0xff)))
+         break;
+    }
+  if (ci == NULL)
+    fprintf (e, "CONTROL");
+  else if (ci->name != NULL)
+    fprintf (e, "%s", ci->name);
+  else
+    fprintf (e, "CONTROL");
+  
+  if (control->text.named || control->text.u.id != 0)
+    {
+      fprintf (e, " ");
+      res_id_print (e, control->text, 1);
+      fprintf (e, ",");
+    }
+
+  fprintf (e, " %d, ", control->id);
+
+  if (ci == NULL)
+    {
+      if (control->class.named)
+       fprintf (e, "\"");
+      res_id_print (e, control->class, 0);
+      if (control->class.named)
+       fprintf (e, "\"");
+      fprintf (e, ", 0x%lx, ", control->style);
+    }
+
+  fprintf (e, "%d, %d", control->x, control->y);
+
+  if (control->style != SS_ICON
+      || control->exstyle != 0
+      || control->width != 0
+      || control->height != 0
+      || control->help != 0)
+    {
+      fprintf (e, ", %d, %d", control->width, control->height);
+
+      /* FIXME: We don't need to print the style if it is the default.
+        More importantly, in certain cases we actually need to turn
+        off parts of the forced style, by using NOT.  */
+      fprintf (e, ", 0x%lx", control->style);
+
+      if (control->exstyle != 0 || control->help != 0)
+       fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
+    }
+
+  fprintf (e, "\n");
+
+  if (control->data != NULL)
+    write_rc_rcdata (e, control->data, 2);
+}
+
+/* Write out font directory data.  This would normally be built from
+   the font data.  */
+
+static void
+write_rc_fontdir (e, fontdir)
+     FILE *e;
+     const struct fontdir *fontdir;
+{
+  const struct fontdir *fc;
+
+  for (fc = fontdir; fc != NULL; fc = fc->next)
+    {
+      fprintf (e, "// Font index: %d\n", fc->index);
+      write_rc_filedata (e, fc->length, fc->data);
+    }
+}
+
+/* Write out group icon data.  This would normally be built from the
+   icon data.  */
+
+static void
+write_rc_group_icon (e, group_icon)
+     FILE *e;
+     const struct group_icon *group_icon;
+{
+  const struct group_icon *gi;
+
+  for (gi = group_icon; gi != NULL; gi = gi->next)
+    {
+      fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
+              gi->width, gi->height, gi->colors, gi->planes, gi->bits);
+      fprintf (e, "// data bytes: %lu; index: %d\n",
+              gi->bytes, gi->index);
+    }
+}
+
+/* Write out a menu resource.  */
+
+static void
+write_rc_menu (e, menu, menuex)
+     FILE *e;
+     const struct menu *menu;
+     int menuex;
+{
+  if (menu->help != 0)
+    fprintf (e, "// Help ID: %lu\n", menu->help);
+  write_rc_menuitems (e, menu->items, menuex, 0);
+}
+
+/* Write out menuitems.  */
+
+static void
+write_rc_menuitems (e, menuitems, menuex, ind)
+     FILE *e;
+     const struct menuitem *menuitems;
+     int menuex;
+     int ind;
+{
+  const struct menuitem *mi;
+
+  indent (e, ind);
+  fprintf (e, "BEGIN\n");
+
+  for (mi = menuitems; mi != NULL; mi = mi->next)
+    {
+      indent (e, ind + 2);
+
+      if (mi->popup == NULL)
+       fprintf (e, "MENUITEM");
+      else
+       fprintf (e, "POPUP");
+
+      if (! menuex
+         && mi->popup == NULL
+         && mi->text == NULL
+         && mi->type == 0
+         && mi->id == 0)
+       {
+         fprintf (e, " SEPARATOR\n");
+         continue;
+       }
+
+      if (mi->text == NULL)
+       fprintf (e, " \"\"");
+      else
+       {
+         fprintf (e, " \"");
+         unicode_print (e, mi->text, -1);
+         fprintf (e, "\"");
+       }
+
+      if (! menuex)
+       {
+         if (mi->popup == NULL)
+           fprintf (e, ", %d", mi->id);
+
+         if ((mi->type & MENUITEM_CHECKED) != 0)
+           fprintf (e, ", CHECKED");
+         if ((mi->type & MENUITEM_GRAYED) != 0)
+           fprintf (e, ", GRAYED");
+         if ((mi->type & MENUITEM_HELP) != 0)
+           fprintf (e, ", HELP");
+         if ((mi->type & MENUITEM_INACTIVE) != 0)
+           fprintf (e, ", INACTIVE");
+         if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
+           fprintf (e, ", MENUBARBREAK");
+         if ((mi->type & MENUITEM_MENUBREAK) != 0)
+           fprintf (e, ", MENUBREAK");
+       }
+      else
+       {
+         if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
+           {
+             fprintf (e, ", %d", mi->id);
+             if (mi->type != 0 || mi->state != 0 || mi->help != 0)
+               {
+                 fprintf (e, ", %lu", mi->type);
+                 if (mi->state != 0 || mi->help != 0)
+                   {
+                     fprintf (e, ", %lu", mi->state);
+                     if (mi->help != 0)
+                       fprintf (e, ", %lu", mi->help);
+                   }
+               }
+           }
+       }
+
+      fprintf (e, "\n");
+
+      if (mi->popup != NULL)
+       write_rc_menuitems (e, mi->popup, menuex, ind + 2);
+    }
+
+  indent (e, ind);
+  fprintf (e, "END\n");
+}
+
+/* Write out an rcdata resource.  This is also used for other types of
+   resources that need to print arbitrary data.  */
+
+static void
+write_rc_rcdata (e, rcdata, ind)
+     FILE *e;
+     const struct rcdata_item *rcdata;
+     int ind;
+{
+  const struct rcdata_item *ri;
+
+  indent (e, ind);
+  fprintf (e, "BEGIN\n");
+
+  for (ri = rcdata; ri != NULL; ri = ri->next)
+    {
+      if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
+       continue;
+
+      indent (e, ind + 2);
+
+      switch (ri->type)
+       {
+       default:
+         abort ();
+
+       case RCDATA_WORD:
+         fprintf (e, "%d", ri->u.word);
+         break;
+
+       case RCDATA_DWORD:
+         fprintf (e, "%luL", ri->u.dword);
+         break;
+
+       case RCDATA_STRING:
+         {
+           const char *s;
+           unsigned long i;
+
+           fprintf (e, "\"");
+           s = ri->u.string.s;
+           for (i = 0; i < ri->u.string.length; i++)
+             {
+               if (isprint ((unsigned char) *s))
+                 putc (*s, e);
+               else
+                 fprintf (e, "\\%03o", *s);
+             }
+           fprintf (e, "\"");
+           break;
+         }
+
+       case RCDATA_WSTRING:
+         fprintf (e, "L\"");
+         unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
+         fprintf (e, "\"");
+         break;
+
+       case RCDATA_BUFFER:
+         {
+           unsigned long i;
+           int first;
+
+           /* Assume little endian data.  */
+
+           first = 1;
+           for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
+             {
+               unsigned long l;
+
+               l = ((((((ri->u.buffer.data[i + 3] << 8)
+                        | ri->u.buffer.data[i + 2]) << 8)
+                      | ri->u.buffer.data[i + 1]) << 8)
+                    | ri->u.buffer.data[i]);
+               if (first)
+                 first = 0;
+               else
+                 {
+                   fprintf (e, ",\n");
+                   indent (e, ind + 2);
+                 }
+               fprintf (e, "%luL", l);
+             }
+
+           if (i + 1 < ri->u.buffer.length)
+             {
+               int i;
+
+               i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
+               if (first)
+                 first = 0;
+               else
+                 {
+                   fprintf (e, ",\n");
+                   indent (e, ind + 2);
+                 }
+               fprintf (e, "%d", i);
+               i += 2;
+             }
+
+           if (i < ri->u.buffer.length)
+             {
+               if (first)
+                 first = 0;
+               else
+                 {
+                   fprintf (e, ",\n");
+                   indent (e, ind + 2);
+                 }
+               if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
+                   && isprint (ri->u.buffer.data[i]))
+                 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
+               else
+                 fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]);
+             }
+
+           break;
+         }
+       }
+
+      if (ri->next != NULL)
+       fprintf (e, ",");
+      fprintf (e, "\n");
+    }
+
+  indent (e, ind);
+  fprintf (e, "END\n");
+}
+
+/* Write out a stringtable resource.  */
+
+static void
+write_rc_stringtable (e, name, stringtable)
+     FILE *e;
+     const struct res_id *name;
+     const struct stringtable *stringtable;
+{
+  unsigned long offset;
+  int i;
+
+  if (name != NULL && ! name->named)
+    offset = (name->u.id - 1) << 4;
+  else
+    {
+      fprintf (e, "// %s string table name\n",
+              name == NULL ? "Missing" : "Invalid");
+      offset = 0;
+    }
+
+  fprintf (e, "BEGIN\n");
+
+  for (i = 0; i < 16; i++)
+    {
+      if (stringtable->strings[i].length != 0)
+       {
+         fprintf (e, "  %lu, \"", offset + i);
+         unicode_print (e, stringtable->strings[i].string,
+                        stringtable->strings[i].length);
+         fprintf (e, "\"\n");
+       }
+    }
+
+  fprintf (e, "END\n");
+}
+
+/* Write out a versioninfo resource.  */
+
+static void
+write_rc_versioninfo (e, versioninfo)
+     FILE *e;
+     const struct versioninfo *versioninfo;
+{
+  const struct fixed_versioninfo *f;
+  const struct ver_info *vi;
+
+  f = versioninfo->fixed;
+  if (f->file_version_ms != 0 || f->file_version_ls != 0)
+    fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
+            (f->file_version_ms >> 16) & 0xffff,
+            f->file_version_ms & 0xffff,
+            (f->file_version_ls >> 16) & 0xffff,
+            f->file_version_ls & 0xffff);
+  if (f->product_version_ms != 0 || f->product_version_ls != 0)
+    fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
+            (f->product_version_ms >> 16) & 0xffff,
+            f->product_version_ms & 0xffff,
+            (f->product_version_ls >> 16) & 0xffff,
+            f->product_version_ls & 0xffff);
+  if (f->file_flags_mask != 0)
+    fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
+  if (f->file_flags != 0)
+    fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
+  if (f->file_os != 0)
+    fprintf (e, " FILEOS 0x%lx\n", f->file_os);
+  if (f->file_type != 0)
+    fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
+  if (f->file_subtype != 0)
+    fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
+  if (f->file_date_ms != 0 || f->file_date_ls != 0)
+    fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
+
+  fprintf (e, "BEGIN\n");
+
+  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
+    {
+      switch (vi->type)
+       {
+       case VERINFO_STRING:
+         {
+           const struct ver_stringinfo *vs;
+
+           fprintf (e, "  BLOCK \"StringFileInfo\"\n");
+           fprintf (e, "  BEGIN\n");
+           fprintf (e, "    BLOCK \"");
+           unicode_print (e, vi->u.string.language, -1);
+           fprintf (e, "\"\n");
+           fprintf (e, "    BEGIN\n");
+
+           for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
+             {
+               fprintf (e, "      VALUE \"");
+               unicode_print (e, vs->key, -1);
+               fprintf (e, "\", \"");
+               unicode_print (e, vs->value, -1);
+               fprintf (e, "\"\n");
+             }
+
+           fprintf (e, "    END\n");
+           fprintf (e, "  END\n");
+           break;
+         }
+
+       case VERINFO_VAR:
+         {
+           const struct ver_varinfo *vv;
+
+           fprintf (e, "  BLOCK \"VarFileInfo\"\n");
+           fprintf (e, "  BEGIN\n");
+           fprintf (e, "    VALUE \"");
+           unicode_print (e, vi->u.var.key, -1);
+           fprintf (e, "\"");
+
+           for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
+             fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
+                      vv->charset);
+
+           fprintf (e, "\n  END\n");
+
+           break;
+         }
+       }
+    }
+
+  fprintf (e, "END\n");
+}
+
+/* Write out data which would normally be read from a file.  */
+
+static void
+write_rc_filedata (e, length, data)
+     FILE *e;
+     unsigned long length;
+     const unsigned char *data;
+{
+  unsigned long i;
+
+  for (i = 0; i + 15 < length; i += 16)
+    {
+      fprintf (e, "// %4lx: ", i);
+      fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
+              data[i + 0], data[i + 1], data[i + 2], data[i + 3],
+              data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
+      fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+              data[i +  8], data[i +  9], data[i + 10], data[i + 11],
+              data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
+    }
+
+  if (i < length)
+    {
+      fprintf (e, "// %4lx:", i);
+      while (i < length)
+       {
+         fprintf (e, " %02x", data[i]);
+         ++i;
+       }
+      fprintf (e, "\n");
+    }
+}
diff --git a/binutils/resres.c b/binutils/resres.c
new file mode 100644 (file)
index 0000000..39264f4
--- /dev/null
@@ -0,0 +1,656 @@
+/* resres.c: read_res_file and write_res_file implementation for windres.
+
+   Copyright 1998, 1999 Free Software Foundation, Inc.
+   Written by Anders Norlander <anorland@hem2.passagen.se>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "windres.h"
+
+#include <assert.h>
+#include <time.h>
+
+struct res_hdr
+  {
+    unsigned long data_size;
+    unsigned long header_size;
+  };
+
+static void write_res_directory
+  PARAMS ((const struct res_directory *,
+          const struct res_id *, const struct res_id *,
+          int *, int));
+static void write_res_resource
+  PARAMS ((const struct res_id *, const struct res_id *,
+          const struct res_resource *, int *));
+static void write_res_bin
+  PARAMS ((const struct res_resource *, const struct res_id *,
+          const struct res_id *, const struct res_res_info *));
+
+static void write_res_id PARAMS ((const struct res_id *));
+static void write_res_info PARAMS ((const struct res_res_info *));
+static void write_res_data PARAMS ((const void *, size_t, int));
+static void write_res_header
+  PARAMS ((unsigned long, const struct res_id *, const struct res_id *,
+          const struct res_res_info *));
+
+static int read_resource_entry PARAMS ((void));
+static void read_res_data PARAMS ((void *, size_t, int));
+static void read_res_id PARAMS ((struct res_id *));
+static unichar *read_unistring PARAMS ((int *));
+static void skip_null_resource PARAMS ((void));
+
+static unsigned long get_id_size PARAMS ((const struct res_id *));
+static void res_align_file PARAMS ((void));
+
+static void
+  res_add_resource
+  PARAMS ((struct res_resource *, const struct res_id *,
+          const struct res_id *, int, int));
+
+void
+  res_append_resource
+  PARAMS ((struct res_directory **, struct res_resource *,
+          int, const struct res_id *, int));
+
+static struct res_directory *resources = NULL;
+
+static FILE *fres;
+static const char *filename;
+
+extern char *program_name;
+
+/* Read resource file */
+struct res_directory *
+read_res_file (fn)
+     const char *fn;
+{
+  filename = fn;
+  fres = fopen (filename, "rb");
+  if (fres == NULL)
+    fatal ("can't open `%s' for output: %s", filename, strerror (errno));
+
+  skip_null_resource ();
+
+  while (read_resource_entry ())
+    ;
+
+  fclose (fres);
+
+  return resources;
+}
+
+/* Write resource file */
+void
+write_res_file (fn, resdir)
+     const char *fn;
+     const struct res_directory *resdir;
+{
+  int language;
+  static const unsigned char sign[] =
+  {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+   0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+  long fpos;
+
+  filename = fn;
+
+  fres = fopen (filename, "wb");
+  if (fres == NULL)
+    fatal ("can't open `%s' for output: %s", filename, strerror (errno));
+
+  /* Write 32 bit resource signature */
+  write_res_data (sign, sizeof (sign), 1);
+
+  /* write resources */
+
+  language = -1;
+  write_res_directory (resdir, (const struct res_id *) NULL,
+                      (const struct res_id *) NULL, &language, 1);
+
+  /* end file on DWORD boundary */
+  fpos = ftell (fres);
+  if (fpos % 4)
+    write_res_data (sign, fpos % 4, 1);
+
+  fclose (fres);
+}
+
+/* Read a resource entry, returns 0 when all resources are read */
+static int
+read_resource_entry (void)
+{
+  struct res_id type;
+  struct res_id name;
+  struct res_res_info resinfo;
+  struct res_hdr reshdr;
+  long version;
+  void *buff;
+
+  struct res_resource *r;
+
+  res_align_file ();
+
+  /* Read header */
+  if (fread (&reshdr, sizeof (reshdr), 1, fres) != 1)
+    return 0;
+
+  /* read resource type */
+  read_res_id (&type);
+  /* read resource id */
+  read_res_id (&name);
+
+  res_align_file ();
+
+  /* Read additional resource header */
+  read_res_data (&resinfo.version, sizeof (resinfo.version), 1);
+  read_res_data (&resinfo.memflags, sizeof (resinfo.memflags), 1);
+  read_res_data (&resinfo.language, sizeof (resinfo.language), 1);
+  read_res_data (&version, sizeof (version), 1);
+  read_res_data (&resinfo.characteristics, sizeof (resinfo.characteristics), 1);
+
+  res_align_file ();
+
+  /* Allocate buffer for data */
+  buff = res_alloc (reshdr.data_size);
+  /* Read data */
+  read_res_data (buff, reshdr.data_size, 1);
+  /* Convert binary data to resource */
+  r = bin_to_res (type, buff, reshdr.data_size, 0);
+  r->res_info = resinfo;
+  /* Add resource to resource directory */
+  res_add_resource (r, &type, &name, resinfo.language, 0);
+
+  return 1;
+}
+
+/* write resource directory to binary resource file */
+static void
+write_res_directory (rd, type, name, language, level)
+     const struct res_directory *rd;
+     const struct res_id *type;
+     const struct res_id *name;
+     int *language;
+     int level;
+{
+  const struct res_entry *re;
+
+  for (re = rd->entries; re != NULL; re = re->next)
+    {
+      switch (level)
+       {
+       case 1:
+         /* If we're at level 1, the key of this resource is the
+            type.  This normally duplicates the information we have
+            stored with the resource itself, but we need to remember
+            the type if this is a user define resource type.  */
+         type = &re->id;
+         break;
+
+       case 2:
+         /* If we're at level 2, the key of this resource is the name
+            we are going to use in the rc printout. */
+         name = &re->id;
+         break;
+
+       case 3:
+         /* If we're at level 3, then this key represents a language.
+            Use it to update the current language.  */
+         if (!re->id.named
+             && re->id.u.id != *language
+             && (re->id.u.id & 0xffff) == re->id.u.id)
+           {
+             *language = re->id.u.id;
+           }
+         break;
+
+       default:
+         break;
+       }
+
+      if (re->subdir)
+       write_res_directory (re->u.dir, type, name, language, level + 1);
+      else
+       {
+         if (level == 3)
+           {
+             /* This is the normal case: the three levels are
+                TYPE/NAME/LANGUAGE.  NAME will have been set at level
+                2, and represents the name to use.  We probably just
+                set LANGUAGE, and it will probably match what the
+                resource itself records if anything.  */
+             write_res_resource (type, name, re->u.res, language);
+           }
+         else
+           {
+             fprintf (stderr, "// Resource at unexpected level %d\n", level);
+             write_res_resource (type, (struct res_id *) NULL, re->u.res,
+                                 language);
+           }
+       }
+    }
+
+}
+
+static void
+write_res_resource (type, name, res, language)
+     const struct res_id *type;
+     const struct res_id *name;
+     const struct res_resource *res;
+     int *language;
+{
+  int rt;
+
+  switch (res->type)
+    {
+    default:
+      abort ();
+
+    case RES_TYPE_ACCELERATOR:
+      rt = RT_ACCELERATOR;
+      break;
+
+    case RES_TYPE_BITMAP:
+      rt = RT_BITMAP;
+      break;
+
+    case RES_TYPE_CURSOR:
+      rt = RT_CURSOR;
+      break;
+
+    case RES_TYPE_GROUP_CURSOR:
+      rt = RT_GROUP_CURSOR;
+      break;
+
+    case RES_TYPE_DIALOG:
+      rt = RT_DIALOG;
+      break;
+
+    case RES_TYPE_FONT:
+      rt = RT_FONT;
+      break;
+
+    case RES_TYPE_FONTDIR:
+      rt = RT_FONTDIR;
+      break;
+
+    case RES_TYPE_ICON:
+      rt = RT_ICON;
+      break;
+
+    case RES_TYPE_GROUP_ICON:
+      rt = RT_GROUP_ICON;
+      break;
+
+    case RES_TYPE_MENU:
+      rt = RT_MENU;
+      break;
+
+    case RES_TYPE_MESSAGETABLE:
+      rt = RT_MESSAGETABLE;
+      break;
+
+    case RES_TYPE_RCDATA:
+      rt = RT_RCDATA;
+      break;
+
+    case RES_TYPE_STRINGTABLE:
+      rt = RT_STRING;
+      break;
+
+    case RES_TYPE_USERDATA:
+      rt = 0;
+      break;
+
+    case RES_TYPE_VERSIONINFO:
+      rt = RT_VERSION;
+      break;
+    }
+
+  if (rt != 0
+      && type != NULL
+      && (type->named || type->u.id != rt))
+    {
+      fprintf (stderr, "// Unexpected resource type mismatch: ");
+      res_id_print (stderr, *type, 1);
+      fprintf (stderr, " != %d", rt);
+      abort ();
+    }
+
+  write_res_bin (res, type, name, &res->res_info);
+  return;
+}
+
+/* Write a resource in binary resource format */
+static void
+write_res_bin (res, type, name, resinfo)
+     const struct res_resource *res;
+     const struct res_id *type;
+     const struct res_id *name;
+     const struct res_res_info *resinfo;
+{
+  unsigned long datasize = 0;
+  const struct bindata *bin_rep, *data;
+
+  bin_rep = res_to_bin (res, 0);
+  for (data = bin_rep; data != NULL; data = data->next)
+    datasize += data->length;
+
+  write_res_header (datasize, type, name, resinfo);
+
+  for (data = bin_rep; data != NULL; data = data->next)
+    write_res_data (data->data, data->length, 1);
+}
+
+/* Get number of bytes needed to store an id in binary format */
+static unsigned long
+get_id_size (id)
+     const struct res_id *id;
+{
+  if (id->named)
+    return sizeof (unichar) * (id->u.n.length + 1);
+  else
+    return sizeof (unichar) * 2;
+}
+
+/* Write a resource header */
+static void
+write_res_header (datasize, type, name, resinfo)
+     unsigned long datasize;
+     const struct res_id *type;
+     const struct res_id *name;
+     const struct res_res_info *resinfo;
+{
+  struct res_hdr reshdr;
+  reshdr.data_size = datasize;
+  reshdr.header_size = 24 + get_id_size (type) + get_id_size (name);
+
+  res_align_file ();
+  write_res_data (&reshdr, sizeof (reshdr), 1);
+  write_res_id (type);
+  write_res_id (name);
+
+  res_align_file ();
+
+  write_res_info (resinfo);
+  res_align_file ();
+}
+
+
+/* Write data to file, abort on failure */
+static void
+write_res_data (data, size, count)
+     const void *data;
+     size_t size;
+     int count;
+{
+  if (fwrite (data, size, count, fres) != count)
+    fatal ("%s: %s: could not write to file", program_name, filename);
+}
+
+/* Read data from file, abort on failure */
+static void
+read_res_data (data, size, count)
+     void *data;
+     size_t size;
+     int count;
+{
+  if (fread (data, size, count, fres) != count)
+    fatal ("%s: %s: unexpected end of file", program_name, filename);
+}
+
+/* Write a resource id */
+static void
+write_res_id (id)
+     const struct res_id *id;
+{
+  if (id->named)
+    {
+      unsigned long len = id->u.n.length;
+      unichar null_term = 0;
+      write_res_data (id->u.n.name, len * sizeof (unichar), 1);
+      write_res_data (&null_term, sizeof (null_term), 1);
+    }
+  else
+    {
+      unsigned short i = 0xFFFF;
+      write_res_data (&i, sizeof (i), 1);
+      i = id->u.id;
+      write_res_data (&i, sizeof (i), 1);
+    }
+}
+
+/* Write resource info */
+static void
+write_res_info (info)
+     const struct res_res_info *info;
+{
+  write_res_data (&info->version, sizeof (info->version), 1);
+  write_res_data (&info->memflags, sizeof (info->memflags), 1);
+  write_res_data (&info->language, sizeof (info->language), 1);
+  write_res_data (&info->version, sizeof (info->version), 1);
+  write_res_data (&info->characteristics, sizeof (info->characteristics), 1);
+}
+
+/* read a resource identifier */
+void 
+read_res_id (id)
+     struct res_id *id;
+{
+  unsigned short ord;
+  unichar *id_s = NULL;
+  int len;
+
+  read_res_data (&ord, sizeof (ord), 1);
+  if (ord == 0xFFFF)           /* an ordinal id */
+    {
+      read_res_data (&ord, sizeof (ord), 1);
+      id->named = 0;
+      id->u.id = ord;
+    }
+  else
+    /* named id */
+    {
+      if (fseek (fres, -sizeof (ord), SEEK_CUR) != 0)
+       fatal ("%s: %s: could not seek in file", program_name, filename);
+      id_s = read_unistring (&len);
+      id->named = 1;
+      id->u.n.length = len;
+      id->u.n.name = id_s;
+    }
+}
+
+/* Read a null terminated UNICODE string */
+static unichar *
+read_unistring (len)
+     int *len;
+{
+  unichar *s;
+  unichar c;
+  unichar *p;
+  int l;
+
+  *len = 0;
+  l = 0;
+
+  /* there are hardly any names longer than 256 characters */
+  p = s = (unichar *) xmalloc (sizeof (unichar) * 256);
+  do
+    {
+      read_res_data (&c, sizeof (c), 1);
+      *p++ = c;
+      if (c != 0)
+       l++;
+    }
+  while (c != 0);
+  *len = l;
+  return s;
+}
+
+/* align file on DWORD boundary */
+static void
+res_align_file (void)
+{
+  if (fseek (fres, ftell (fres) % 4, SEEK_CUR) != 0)
+    fatal ("%s: %s: unable to align file", program_name, filename);
+}
+
+/* Check if file is a win32 binary resource file, if so
+   skip past the null resource. Returns 0 if successful, -1 on
+   error.
+ */
+static void
+skip_null_resource (void)
+{
+  struct res_hdr reshdr =
+  {0, 0};
+  read_res_data (&reshdr, sizeof (reshdr), 1);
+  if ((reshdr.data_size != 0) || (reshdr.header_size != 0x20))
+    goto skip_err;
+
+  /* Subtract size of HeaderSize and DataSize */
+  if (fseek (fres, reshdr.header_size - 8, SEEK_CUR) != 0)
+    goto skip_err;
+
+  return;
+
+skip_err:
+  fprintf (stderr, "%s: %s: Not a valid WIN32 resource file\n", program_name,
+          filename);
+  xexit (1);
+}
+
+/* Add a resource to resource directory */
+void
+res_add_resource (r, type, id, language, dupok)
+     struct res_resource *r;
+     const struct res_id *type;
+     const struct res_id *id;
+     int language;
+     int dupok;
+{
+  struct res_id a[3];
+
+  a[0] = *type;
+  a[1] = *id;
+  a[2].named = 0;
+  a[2].u.id = language;
+  res_append_resource (&resources, r, 3, a, dupok);
+}
+
+/* Append a resource to resource directory.
+   This is just copied from define_resource
+   and modified to add an existing resource.
+ */
+void
+res_append_resource (resources, resource, cids, ids, dupok)
+     struct res_directory **resources;
+     struct res_resource *resource;
+     int cids;
+     const struct res_id *ids;
+     int dupok;
+{
+  struct res_entry *re = NULL;
+  int i;
+
+  assert (cids > 0);
+  for (i = 0; i < cids; i++)
+    {
+      struct res_entry **pp;
+
+      if (*resources == NULL)
+       {
+         static unsigned long timeval;
+
+         /* Use the same timestamp for every resource created in a
+            single run.  */
+         if (timeval == 0)
+           timeval = time (NULL);
+
+         *resources = ((struct res_directory *)
+                       res_alloc (sizeof **resources));
+         (*resources)->characteristics = 0;
+         (*resources)->time = timeval;
+         (*resources)->major = 0;
+         (*resources)->minor = 0;
+         (*resources)->entries = NULL;
+       }
+
+      for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
+       if (res_id_cmp ((*pp)->id, ids[i]) == 0)
+         break;
+
+      if (*pp != NULL)
+       re = *pp;
+      else
+       {
+         re = (struct res_entry *) res_alloc (sizeof *re);
+         re->next = NULL;
+         re->id = ids[i];
+         if ((i + 1) < cids)
+           {
+             re->subdir = 1;
+             re->u.dir = NULL;
+           }
+         else
+           {
+             re->subdir = 0;
+             re->u.res = NULL;
+           }
+
+         *pp = re;
+       }
+
+      if ((i + 1) < cids)
+       {
+         if (!re->subdir)
+           {
+             fprintf (stderr, "%s: ", program_name);
+             res_ids_print (stderr, i, ids);
+             fprintf (stderr, ": expected to be a directory\n");
+             xexit (1);
+           }
+
+         resources = &re->u.dir;
+       }
+    }
+
+  if (re->subdir)
+    {
+      fprintf (stderr, "%s: ", program_name);
+      res_ids_print (stderr, cids, ids);
+      fprintf (stderr, ": expected to be a leaf\n");
+      xexit (1);
+    }
+
+  if (re->u.res != NULL)
+    {
+      if (dupok)
+       return;
+
+      fprintf (stderr, "%s: warning: ", program_name);
+      res_ids_print (stderr, cids, ids);
+      fprintf (stderr, ": duplicate value\n");
+    }
+
+  re->u.res = resource;
+}
diff --git a/binutils/sanity.sh b/binutils/sanity.sh
new file mode 100755 (executable)
index 0000000..942cabf
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+### quick sanity test for the binutils.
+###
+### This file was written and is maintained by K. Richard Pixley,
+### rich@cygnus.com.
+
+### fail on errors
+set -e
+
+### first arg is directory in which binaries to be tested reside.
+case "$1" in
+"") BIN=. ;;
+*)  BIN="$1" ;;
+esac
+
+### size
+for i in size objdump nm ar strip ranlib ; do
+       ${BIN}/size ${BIN}/$i > /dev/null
+done
+
+### objdump
+for i in size objdump nm ar strip ranlib ; do
+       ${BIN}/objdump -ahifdrtxsl ${BIN}/$i > /dev/null
+done
+
+### nm
+for i in size objdump nm ar strip ranlib ; do
+       ${BIN}/nm ${BIN}/$i > /dev/null
+done
+
+### strip
+TMPDIR=./binutils-$$
+mkdir ${TMPDIR}
+
+cp ${BIN}/strip ${TMPDIR}/strip
+
+for i in size objdump nm ar ranlib ; do
+       cp ${BIN}/$i ${TMPDIR}/$i
+       ${BIN}/strip ${TMPDIR}/$i
+       cp ${BIN}/$i ${TMPDIR}/$i
+       ${TMPDIR}/strip ${TMPDIR}/$i
+done
+
+### ar
+
+### ranlib
+
+rm -rf ${TMPDIR}
+
+exit 0
diff --git a/binutils/size.1 b/binutils/size.1
new file mode 100644 (file)
index 0000000..3b19bd2
--- /dev/null
@@ -0,0 +1,161 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH size 1 "5 November 1991" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+size \- list section sizes and total size.
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B size
+.RB "[\|" \-A \||\| \-B \||\| \c
+.BI "\-\-format=" compatibility\c
+\&\|]
+.RB "[\|" \-\-help "\|]" 
+.RB "[\|" \-d \||\| \-o \||\| \-x\c
+\||\|\c
+.BI "\-\-radix=" number\c
+\&\|]
+.RB "[\|" \c
+.BI "\-\-target=" bfdname\c
+\&\|]
+.RB "[\|" \-V \||\| \-\-version "\|]"  
+.I objfile\c
+\&.\|.\|.
+.ad b
+.hy 1
+.SH DESCRIPTION
+The GNU \c
+.B size\c
+\& utility lists the section sizes\(em\&and the total
+size\(em\&for each of the object files
+.I objfile
+in its argument list.
+By default, one line of output is generated for each object file or each
+module in an archive.
+
+.SH OPTIONS
+.TP
+.B \-A
+.TP
+.B \-B
+.TP
+.BI "\-\-format " "compatibility"
+Using one of these options, you can choose whether the output from GNU
+\c
+.B size\c
+\& resembles output from System V \c
+.B size\c
+\& (using `\|\c
+.B \-A\c
+\|',
+or `\|\c
+.B \-\-format=sysv\c
+\|'), or Berkeley \c
+.B size\c
+\& (using `\|\c
+.B \-B\c
+\|', or
+`\|\c
+.B \-\-format=berkeley\c
+\|').  The default is the one-line format similar to
+Berkeley's.  
+
+.TP
+.B \-\-help
+Show a summary of acceptable arguments and options.
+
+.TP
+.B \-d
+.TP
+.B \-o
+.TP
+.B \-x
+.TP
+.BI "\-\-radix " "number"
+Using one of these options, you can control whether the size of each
+section is given in decimal (`\|\c
+.B \-d\c
+\|', or `\|\c
+.B \-\-radix 10\c
+\|'); octal
+(`\|\c
+.B \-o\c
+\|', or `\|\c
+.B \-\-radix 8\c
+\|'); or hexadecimal (`\|\c
+.B \-x\c
+\|', or
+`\|\c
+.B \-\-radix 16\c
+\|').  In `\|\c
+.B \-\-radix \c
+.I number\c
+\&\c
+\|', only the three
+values (8, 10, 16) are supported.  The total size is always given in two
+radices; decimal and hexadecimal for `\|\c
+.B \-d\c
+\|' or `\|\c
+.B \-x\c
+\|' output, or
+octal and hexadecimal if you're using `\|\c
+.B \-o\c
+\|'.
+
+.TP
+.BI "\-\-target " "bfdname"
+You can specify a particular object-code format for \c
+.I objfile\c
+\& as
+\c
+.I bfdname\c
+\&.  This may not be necessary; \c
+.I size\c
+\& can
+automatically recognize many formats.   See 
+.BR objdump ( 1 ) 
+for information
+on listing available formats.
+
+.TP
+.B \-V
+.TP
+.B \-\-version
+Display version number information on \c
+.B size\c
+\& itself.
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'" 
+entry in 
+.BR info ;
+.IR "The GNU Binary Utilities" ,
+ Roland H. Pesch (October 1991); 
+.BR ar "(" 1 "),"
+.BR objdump ( 1 ).
+
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/size.c b/binutils/size.c
new file mode 100644 (file)
index 0000000..f57c7ed
--- /dev/null
@@ -0,0 +1,515 @@
+/* size.c -- report size of various sections of an executable file.
+   Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+
+This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+\f
+/* Extensions/incompatibilities:
+   o - BSD output has filenames at the end.
+   o - BSD output can appear in different radicies.
+   o - SysV output has less redundant whitespace.  Filename comes at end.
+   o - SysV output doesn't show VMA which is always the same as the PMA.
+   o - We also handle core files.
+   o - We also handle archives.
+   If you write shell scripts which manipulate this info then you may be
+   out of luck; there's no --compatibility or --pedantic option.
+*/
+
+#include "bfd.h"
+#include "getopt.h"
+#include "bucomm.h"
+#include "libiberty.h"
+
+#ifndef BSD_DEFAULT
+#define BSD_DEFAULT 1
+#endif
+
+/* Program options.  */
+
+enum
+  {
+    decimal, octal, hex
+  } radix = decimal;
+int berkeley_format = BSD_DEFAULT;     /* 0 means use AT&T-style output.  */
+int show_version = 0;
+int show_help = 0;
+
+/* Program exit status.  */
+int return_code = 0;
+
+static char *target = NULL;
+
+/* Static declarations */
+
+static void usage PARAMS ((FILE *, int));
+static void display_file PARAMS ((char *filename));
+static void display_bfd PARAMS ((bfd *));
+static void display_archive PARAMS ((bfd *));
+static int size_number PARAMS ((bfd_size_type));
+#if 0
+static void lprint_number PARAMS ((int, bfd_size_type));
+#endif
+static void rprint_number PARAMS ((int, bfd_size_type));
+static void print_berkeley_format PARAMS ((bfd *));
+static void sysv_internal_sizer PARAMS ((bfd *, asection *, PTR));
+static void sysv_internal_printer PARAMS ((bfd *, asection *, PTR));
+static void print_sysv_format PARAMS ((bfd *));
+static void print_sizes PARAMS ((bfd * file));
+static void berkeley_sum PARAMS ((bfd *, sec_ptr, PTR));
+\f
+static void
+usage (stream, status)
+     FILE *stream;
+     int status;
+{
+  fprintf (stream, _("\
+Usage: %s [-ABdoxV] [--format=berkeley|sysv] [--radix=8|10|16]\n\
+       [--target=bfdname] [--version] [--help] [file...]\n"), program_name);
+#if BSD_DEFAULT
+  fputs (_("default is --format=berkeley\n"), stream);
+#else
+  fputs (_("default is --format=sysv\n"), stream);
+#endif
+  list_supported_targets (program_name, stream);
+  if (status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (status);
+}
+
+struct option long_options[] =
+{
+  {"format", required_argument, 0, 200},
+  {"radix", required_argument, 0, 201},
+  {"target", required_argument, 0, 202},
+  {"version", no_argument, &show_version, 1},
+  {"help", no_argument, &show_help, 1},
+  {0, no_argument, 0, 0}
+};
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int temp;
+  int c;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = *argv;
+  xmalloc_set_program_name (program_name);
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  while ((c = getopt_long (argc, argv, "ABVdox", long_options,
+                          (int *) 0)) != EOF)
+    switch (c)
+      {
+      case 200:                /* --format */
+       switch (*optarg)
+         {
+         case 'B':
+         case 'b':
+           berkeley_format = 1;
+           break;
+         case 'S':
+         case 's':
+           berkeley_format = 0;
+           break;
+         default:
+           fprintf (stderr, _("invalid argument to --format: %s\n"), optarg);
+           usage (stderr, 1);
+         }
+       break;
+
+      case 202:                /* --target */
+       target = optarg;
+       break;
+
+      case 201:                /* --radix */
+#ifdef ANSI_LIBRARIES
+       temp = strtol (optarg, NULL, 10);
+#else
+       temp = atol (optarg);
+#endif
+       switch (temp)
+         {
+         case 10:
+           radix = decimal;
+           break;
+         case 8:
+           radix = octal;
+           break;
+         case 16:
+           radix = hex;
+           break;
+         default:
+           printf (_("Invalid radix: %s\n"), optarg);
+           usage (stderr, 1);
+         }
+       break;
+
+      case 'A':
+       berkeley_format = 0;
+       break;
+      case 'B':
+       berkeley_format = 1;
+       break;
+      case 'V':
+       show_version = 1;
+       break;
+      case 'd':
+       radix = decimal;
+       break;
+      case 'x':
+       radix = hex;
+       break;
+      case 'o':
+       radix = octal;
+       break;
+      case 0:
+       break;
+      case '?':
+       usage (stderr, 1);
+      }
+
+  if (show_version)
+    print_version ("size");
+  if (show_help)
+    usage (stdout, 0);
+
+  if (optind == argc)
+    display_file ("a.out");
+  else
+    for (; optind < argc;)
+      display_file (argv[optind++]);
+
+  return return_code;
+}
+\f
+/* Display stats on file or archive member ABFD.  */
+
+static void
+display_bfd (abfd)
+     bfd *abfd;
+{
+  char **matching;
+
+  if (bfd_check_format (abfd, bfd_archive))
+    /* An archive within an archive.  */
+    return;
+
+  if (bfd_check_format_matches (abfd, bfd_object, &matching))
+    {
+      print_sizes (abfd);
+      printf ("\n");
+      return;
+    }
+
+  if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+    {
+      bfd_nonfatal (bfd_get_filename (abfd));
+      list_matching_formats (matching);
+      free (matching);
+      return_code = 3;
+      return;
+    }
+
+  if (bfd_check_format_matches (abfd, bfd_core, &matching))
+    {
+      CONST char *core_cmd;
+
+      print_sizes (abfd);
+      fputs (" (core file", stdout);
+
+      core_cmd = bfd_core_file_failing_command (abfd);
+      if (core_cmd)
+       printf (" invoked as %s", core_cmd);
+
+      puts (")\n");
+      return;
+    }
+
+  bfd_nonfatal (bfd_get_filename (abfd));
+
+  if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+    {
+      list_matching_formats (matching);
+      free (matching);
+    }
+
+  return_code = 3;
+}
+
+static void
+display_archive (file)
+     bfd *file;
+{
+  bfd *arfile = (bfd *) NULL;
+
+  for (;;)
+    {
+      bfd_set_error (bfd_error_no_error);
+
+      arfile = bfd_openr_next_archived_file (file, arfile);
+      if (arfile == NULL)
+       {
+         if (bfd_get_error () != bfd_error_no_more_archived_files)
+           {
+             bfd_nonfatal (bfd_get_filename (file));
+             return_code = 2;
+           }
+         break;
+       }
+
+      display_bfd (arfile);
+      /* Don't close the archive elements; we need them for next_archive */
+    }
+}
+
+static void
+display_file (filename)
+     char *filename;
+{
+  bfd *file = bfd_openr (filename, target);
+  if (file == NULL)
+    {
+      bfd_nonfatal (filename);
+      return_code = 1;
+      return;
+    }
+
+  if (bfd_check_format (file, bfd_archive) == true)
+    display_archive (file);
+  else
+    display_bfd (file);
+
+  if (bfd_close (file) == false)
+    {
+      bfd_nonfatal (filename);
+      return_code = 1;
+      return;
+    }
+}
+\f
+/* This is what lexical functions are for.  */
+
+static int
+size_number (num)
+     bfd_size_type num;
+{
+  char buffer[40];
+  sprintf (buffer,
+          (radix == decimal ? "%lu" :
+          ((radix == octal) ? "0%lo" : "0x%lx")),
+          (unsigned long) num);
+
+  return strlen (buffer);
+}
+
+#if 0
+
+/* This is not used.  */
+
+static void
+lprint_number (width, num)
+     int width;
+     bfd_size_type num;
+{
+  char buffer[40];
+  sprintf (buffer,
+          (radix == decimal ? "%lu" :
+          ((radix == octal) ? "0%lo" : "0x%lx")),
+          (unsigned long) num);
+
+  printf ("%-*s", width, buffer);
+}
+
+#endif
+
+static void
+rprint_number (width, num)
+     int width;
+     bfd_size_type num;
+{
+  char buffer[40];
+  sprintf (buffer,
+          (radix == decimal ? "%lu" :
+          ((radix == octal) ? "0%lo" : "0x%lx")),
+          (unsigned long) num);
+
+  printf ("%*s", width, buffer);
+}
+
+static bfd_size_type bsssize;
+static bfd_size_type datasize;
+static bfd_size_type textsize;
+
+static void
+berkeley_sum (abfd, sec, ignore)
+     bfd *abfd;
+     sec_ptr sec;
+     PTR ignore;
+{
+  flagword flags;
+  bfd_size_type size;
+
+  flags = bfd_get_section_flags (abfd, sec);
+  if ((flags & SEC_ALLOC) == 0)
+    return;
+
+  size = bfd_get_section_size_before_reloc (sec);
+  if ((flags & SEC_CODE) != 0 || (flags & SEC_READONLY) != 0)
+    textsize += size;
+  else if ((flags & SEC_HAS_CONTENTS) != 0)
+    datasize += size;
+  else
+    bsssize += size;
+}
+
+static void 
+print_berkeley_format (abfd)
+     bfd *abfd;
+{
+  static int files_seen = 0;
+  bfd_size_type total;
+
+  bsssize = 0;
+  datasize = 0;
+  textsize = 0;
+
+  bfd_map_over_sections (abfd, berkeley_sum, (PTR) NULL);
+
+  if (files_seen++ == 0)
+#if 0
+    /* Intel doesn't like bss/stk because they don't have core files.  */
+    puts ((radix == octal) ? "   text\t   data\tbss/stk\t    oct\t    hex\tfilename" :
+         "   text\t   data\tbss/stk\t    dec\t    hex\tfilename");
+#else
+    puts ((radix == octal) ? "   text\t   data\t    bss\t    oct\t    hex\tfilename" :
+         "   text\t   data\t    bss\t    dec\t    hex\tfilename");
+#endif
+
+  total = textsize + datasize + bsssize;
+
+  rprint_number (7, textsize);
+  putchar ('\t');
+  rprint_number (7, datasize);
+  putchar ('\t');
+  rprint_number (7, bsssize);
+  printf (((radix == octal) ? "\t%7lo\t%7lx\t" : "\t%7lu\t%7lx\t"),
+         (unsigned long) total, (unsigned long) total);
+
+  fputs (bfd_get_filename (abfd), stdout);
+  if (bfd_my_archive (abfd))
+    printf (" (ex %s)", bfd_get_filename (bfd_my_archive (abfd)));
+}
+
+/* I REALLY miss lexical functions! */
+bfd_size_type svi_total = 0;
+bfd_vma svi_maxvma = 0;
+int svi_namelen = 0;
+int svi_vmalen = 0;
+int svi_sizelen = 0;
+
+static void
+sysv_internal_sizer (file, sec, ignore)
+     bfd *file;
+     sec_ptr sec;
+     PTR ignore;
+{
+  bfd_size_type size = bfd_section_size (file, sec);
+  if (!bfd_is_abs_section (sec)
+      && !bfd_is_com_section (sec)
+      && !bfd_is_und_section (sec))
+    {
+      int namelen = strlen (bfd_section_name (file, sec));
+      if (namelen > svi_namelen)
+       svi_namelen = namelen;
+
+      svi_total += size;
+      if (bfd_section_vma (file, sec) > svi_maxvma)
+       svi_maxvma = bfd_section_vma (file, sec);
+    }
+}
+
+static void
+sysv_internal_printer (file, sec, ignore)
+     bfd *file;
+     sec_ptr sec;
+     PTR ignore;
+{
+  bfd_size_type size = bfd_section_size (file, sec);
+  if (!bfd_is_abs_section (sec)
+      && !bfd_is_com_section (sec)
+      && !bfd_is_und_section (sec))
+    {
+      svi_total += size;
+
+      printf ("%-*s   ", svi_namelen, bfd_section_name (file, sec));
+      rprint_number (svi_sizelen, size);
+      printf ("   ");
+      rprint_number (svi_vmalen, bfd_section_vma (file, sec));
+      printf ("\n");
+    }
+}
+
+static void
+print_sysv_format (file)
+     bfd *file;
+{
+  /* size all of the columns */
+  svi_total = 0;
+  svi_maxvma = 0;
+  svi_namelen = 0;
+  bfd_map_over_sections (file, sysv_internal_sizer, (PTR) NULL);
+  svi_vmalen = size_number ((bfd_size_type)svi_maxvma);
+  if ((size_t) svi_vmalen < sizeof ("addr") - 1)
+    svi_vmalen = sizeof ("addr")-1;
+
+  svi_sizelen = size_number (svi_total);
+  if ((size_t) svi_sizelen < sizeof ("size") - 1)
+    svi_sizelen = sizeof ("size")-1;
+
+  svi_total = 0;
+  printf ("%s  ", bfd_get_filename (file));
+  if (bfd_my_archive (file))
+    printf (" (ex %s)", bfd_get_filename (bfd_my_archive (file)));
+
+  printf (":\n%-*s   %*s   %*s\n", svi_namelen, "section",
+         svi_sizelen, "size", svi_vmalen, "addr");
+  bfd_map_over_sections (file, sysv_internal_printer, (PTR) NULL);
+
+  printf ("%-*s   ", svi_namelen, "Total");
+  rprint_number (svi_sizelen, svi_total);
+  printf ("\n\n");
+}
+
+static void
+print_sizes (file)
+     bfd *file;
+{
+  if (berkeley_format)
+    print_berkeley_format (file);
+  else
+    print_sysv_format (file);
+}
diff --git a/binutils/srconv.c b/binutils/srconv.c
new file mode 100644 (file)
index 0000000..8b0f2b7
--- /dev/null
@@ -0,0 +1,2036 @@
+/* srconv.c -- Sysroff conversion program
+   Copyright (C) 1994, 95, 96, 98, 1999 Free Software Foundation, Inc.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* Written by Steve Chamberlain (sac@cygnus.com)
+
+   This program can be used to convert a coff object file
+   into a Hitachi OM/LM (Sysroff) format.
+
+   All debugging information is preserved */
+
+#include <bfd.h>
+#include "bucomm.h"
+#include "sysroff.h"
+#include "coffgrok.h"
+#include <libiberty.h>
+#include <getopt.h>
+
+#include "coff/internal.h"
+#include "../bfd/libcoff.h"
+
+#define PROGRAM_VERSION "1.5"
+/*#define FOOP1 1 */
+
+static int addrsize;
+static char *toolname;
+static char **rnames;
+
+static void wr_cs ();
+static void walk_tree_scope ();
+static void wr_globals ();
+static int find_base ();
+
+static FILE *file;
+static bfd *abfd;
+static int debug = 0;
+static int quick = 0;
+static int noprescan = 0;
+static struct coff_ofile *tree;
+/* Obsolete ?? 
+   static int absolute_p;
+ */
+
+static int segmented_p;
+static int code;
+
+static int ids1[20000];
+static int ids2[20000];
+
+static int base1 = 0x18;
+static int base2 = 0x2018;
+
+static int
+get_member_id (x)
+     int x;
+{
+  if (ids2[x])
+    {
+      return ids2[x];
+    }
+  ids2[x] = base2++;
+  return ids2[x];
+}
+
+static int
+get_ordinary_id (x)
+     int x;
+{
+  if (ids1[x])
+    {
+      return ids1[x];
+    }
+  ids1[x] = base1++;
+  return ids1[x];
+}
+static char *
+section_translate (n)
+     char *n;
+{
+  if (strcmp (n, ".text") == 0)
+    return "P";
+  if (strcmp (n, ".data") == 0)
+    return "D";
+  if (strcmp (n, ".bss") == 0)
+    return "B";
+  return n;
+}
+
+
+
+#define DATE "940201073000";   /* Just a time on my birthday */
+
+
+static
+char *
+strip_suffix (name)
+     char *name;
+{
+  int i;
+  char *res;
+  for (i = 0; name[i] != 0 && name[i] != '.'; i++)
+    ;
+  res = (char *) xmalloc (i + 1);
+  memcpy (res, name, i);
+  res[i] = 0;
+  return res;
+}
+
+
+/* IT LEN stuff CS */
+static void
+checksum (file, ptr, size, code)
+     FILE *file;
+     char *ptr;
+     int size;
+     int code;
+{
+  int j;
+  int last;
+  int sum = 0;
+  int bytes = size / 8;
+  last = !(code & 0xff00);
+  if (size & 0x7)
+    abort ();
+  ptr[0] = code | (last ? 0x80 : 0);
+  ptr[1] = bytes + 1;
+
+  for (j = 0; j < bytes; j++)
+    {
+      sum += ptr[j];
+    }
+  /* Glue on a checksum too */
+  ptr[bytes] = ~sum;
+  fwrite (ptr, bytes + 1, 1, file);
+}
+
+
+
+
+static void
+writeINT (n, ptr, idx, size, file)
+     int n;
+     char *ptr;
+     int *idx;
+     int size;
+     FILE *file;
+{
+  int byte = *idx / 8;
+
+  if (size == -2)
+    size = addrsize;
+  else if (size == -1)
+    size = 0;
+
+  if (byte > 240)
+    {
+      /* Lets write out that record and do another one */
+      checksum (file, ptr, *idx, code | 0x1000);
+      *idx = 16;
+      byte = *idx / 8;
+    }
+  switch (size)
+    {
+    case 0:
+      break;
+    case 1:
+      ptr[byte] = n;
+      break;
+    case 2:
+      ptr[byte + 0] = n >> 8;
+      ptr[byte + 1] = n;
+      break;
+    case 4:
+      ptr[byte + 0] = n >> 24;
+      ptr[byte + 1] = n >> 16;
+      ptr[byte + 2] = n >> 8;
+      ptr[byte + 3] = n >> 0;
+      break;
+    default:
+      abort ();
+    }
+  *idx += size * 8;
+}
+
+
+static void
+writeBITS (val, ptr, idx, size)
+     int val;
+     char *ptr;
+     int *idx;
+     int size;
+{
+  int byte = *idx / 8;
+  int bit = *idx % 8;
+  int old;
+  *idx += size;
+
+  old = ptr[byte];
+  /* Turn off all about to change bits */
+  old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1));
+  /* Turn on the bits we want */
+  old |= (val & ((1 << size) - 1)) << (8 - bit - size);
+  ptr[byte] = old;
+}
+
+static void
+writeBARRAY (data, ptr, idx, size, file)
+     barray data;
+     char *ptr;
+     int *idx;
+     int size;
+     FILE *file;
+{
+  int i;
+  writeINT (data.len, ptr, idx, 1, file);
+  for (i = 0; i < data.len; i++)
+    {
+      writeINT (data.data[i], ptr, idx, 1, file);
+    }
+}
+
+
+static void
+writeCHARS (string, ptr, idx, size, file)
+     char *string;
+     char *ptr;
+     int *idx;
+     int size;
+     FILE *file;
+{
+  int i = *idx / 8;
+
+  if (i > 240)
+    {
+      /* Lets write out that record and do another one */
+      checksum (file, ptr, *idx, code | 0x1000);
+      *idx = 16;
+      i = *idx / 8;
+    }
+
+  if (size == 0)
+    {
+      /* Variable length string */
+      size = strlen (string);
+      ptr[i++] = size;
+    }
+
+  /* BUG WAITING TO HAPPEN */
+  memcpy (ptr + i, string, size);
+  i += size;
+  *idx = i * 8;
+}
+
+#define SYSROFF_SWAP_OUT
+#include "sysroff.c"
+
+
+static char *rname_sh[] =
+{
+  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
+};
+
+static char *rname_h8300[] =
+{
+  "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR"
+};
+
+static void
+wr_tr ()
+{
+  /* The TR block is not normal - it doesn't have any contents. */
+
+  static char b[] = {
+    0xff,                      /* IT */
+    0x03,                      /* RL */
+    0xfd,                      /* CS */
+  };
+  fwrite (b, 1, sizeof (b), file);
+}
+
+static void
+wr_un (ptr, sfile, first, nsecs)
+     struct coff_ofile *ptr;
+     struct coff_sfile *sfile;
+     int first;
+     int nsecs;
+{
+  struct IT_un un;
+
+  struct coff_symbol *s;
+
+  un.spare1 = 0;
+
+  if (bfd_get_file_flags (abfd) & EXEC_P)
+    un.format = FORMAT_LM;
+  else
+    un.format = FORMAT_OM;
+  un.spare1 = 0;
+
+
+#if 1
+  un.nsections = ptr->nsections - 1;   /*  Don't count the abs section */
+#else
+  /*NEW - only count sections with size */
+  un.nsections = nsecs;
+#endif
+
+  un.nextdefs = 0;
+  un.nextrefs = 0;
+  /* Count all the undefined and defined variables with global scope */
+
+  if (first)
+    {
+      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
+       {
+         if (s->visible->type == coff_vis_ext_def
+             || s->visible->type == coff_vis_common)
+           un.nextdefs++;
+
+         if (s->visible->type == coff_vis_ext_ref)
+           un.nextrefs++;
+       }
+    }
+  un.tool = toolname;
+  un.tcd = DATE;
+  un.linker = "L_GX00";
+  un.lcd = DATE;
+  un.name = sfile->name;
+  sysroff_swap_un_out (file, &un);
+}
+
+
+static void
+wr_hd (p)
+     struct coff_ofile *p;
+{
+  struct IT_hd hd;
+
+  hd.spare1 = 0;
+  if (bfd_get_file_flags (abfd) & EXEC_P)
+    {
+      hd.mt = MTYPE_ABS_LM;
+    }
+  else
+    {
+      hd.mt = MTYPE_OMS_OR_LMS;
+    }
+  hd.cd = DATE;
+
+  hd.nu = p->nsources;         /* Always one unit */
+  hd.code = 0;                 /* Always ASCII */
+  hd.ver = "0200";             /* Version 2.00 */
+  switch (bfd_get_arch (abfd))
+    {
+    case bfd_arch_h8300:
+      hd.au = 8;
+      hd.si = 0;
+      hd.spcsz = 32;
+      hd.segsz = 0;
+      hd.segsh = 0;
+      switch (bfd_get_mach (abfd))
+       {
+       case bfd_mach_h8300:
+         hd.cpu = "H8300";
+         hd.afl = 2;
+         addrsize = 2;
+         toolname = "C_H8/300";
+         break;
+       case bfd_mach_h8300h:
+         hd.cpu = "H8300H";
+         hd.afl = 4;
+         addrsize = 4;
+         toolname = "C_H8/300H";
+         break;
+       case bfd_mach_h8300s:
+         hd.cpu = "H8300S";
+         hd.afl = 4;
+         addrsize = 4;
+         toolname = "C_H8/300S";
+         break;
+       default:
+         abort();
+       }
+      rnames = rname_h8300;
+      break;
+    case bfd_arch_sh:
+      hd.au = 8;
+      hd.si = 0;
+      hd.afl = 4;
+      hd.spcsz = 32;
+      hd.segsz = 0;
+      hd.segsh = 0;
+      hd.cpu = "SH";
+      addrsize = 4;
+      toolname = "C_SH";
+      rnames = rname_sh;
+      break;
+    default:
+      abort ();
+    }
+
+  if (! bfd_get_file_flags(abfd) & EXEC_P)
+    {
+      hd.ep = 0;
+    }
+  else
+    {
+      hd.ep = 1;
+      hd.uan = 0;
+      hd.sa = 0;
+      hd.sad = 0;
+      hd.address = bfd_get_start_address (abfd);
+    }
+
+  hd.os = "";
+  hd.sys = "";
+  hd.mn = strip_suffix (bfd_get_filename (abfd));
+
+  sysroff_swap_hd_out (file, &hd);
+}
+
+
+static void
+wr_sh (p, sec)
+     struct coff_ofile *p;
+     struct coff_section *sec;
+{
+  struct IT_sh sh;
+  sh.unit = 0;
+  sh.section = sec->number;
+#ifdef FOOP1
+  sh.section = 0;
+#endif
+  sysroff_swap_sh_out (file, &sh);
+}
+
+
+static void
+wr_ob (p, section)
+     struct coff_ofile *p;
+     struct coff_section *section;
+{
+  bfd_size_type i;
+  int first = 1;
+  unsigned char stuff[200];
+
+  i = 0;
+  while (i < section->bfd_section->_raw_size)
+    {
+      struct IT_ob ob;
+      int todo = 200;          /* Copy in 200 byte lumps */
+      ob.spare = 0;
+      if (i + todo > section->bfd_section->_raw_size)
+       todo = section->bfd_section->_raw_size - i;
+
+      if (first)
+       {
+         ob.saf = 1;
+         if (bfd_get_file_flags (abfd) & EXEC_P)
+           ob.address = section->address;
+         else
+           ob.address = 0;
+
+         first = 0;
+       }
+      else
+       {
+         ob.saf = 0;
+       }
+
+      ob.cpf = 0;              /* Never compress */
+      ob.data.len = todo;
+      bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo);
+      ob.data.data = stuff;
+      sysroff_swap_ob_out (file, &ob /*, i + todo < section->size */ );
+      i += todo;
+    }
+  /* Now fill the rest with blanks */
+  while (i < (bfd_size_type) section->size)
+    {
+      struct IT_ob ob;
+      int todo = 200;          /* Copy in 200 byte lumps */
+      ob.spare = 0;
+      if (i + todo > (bfd_size_type) section->size)
+       todo = section->size - i;
+      ob.saf = 0;
+
+      ob.cpf = 0;              /* Never compress */
+      ob.data.len = todo;
+      memset (stuff, 0, todo);
+      ob.data.data = stuff;
+      sysroff_swap_ob_out (file, &ob);
+      i += todo;
+    }
+  /* Now fill the rest with blanks */
+
+}
+
+static void
+wr_rl (ptr, sec)
+     struct coff_ofile *ptr;
+     struct coff_section *sec;
+{
+  int nr = sec->nrelocs;
+  int i;
+  for (i = 0; i < nr; i++)
+    {
+      struct coff_reloc *r = sec->relocs + i;
+      struct coff_symbol *ref;
+      struct IT_rl rl;
+      rl.apol = 0;
+      rl.boundary = 0;
+      rl.segment = 1;
+      rl.sign = 0;
+      rl.check = 0;
+      rl.addr = r->offset;
+      rl.bitloc = 0;
+      rl.flen = 32;            /* SH Specific */
+      /* What sort of reloc ? Look in the section to find out */
+      ref = r->symbol;
+      if (ref->visible->type == coff_vis_ext_ref)
+       {
+         rl.bcount = 4;        /* Always 4 for us */
+         rl.op = OP_EXT_REF;
+         rl.symn = ref->er_number;
+       }
+      else if (ref->visible->type == coff_vis_common)
+       {
+         rl.bcount = 11;       /* Always 11 for us */
+         rl.op = OP_SEC_REF;
+         rl.secn = ref->where->section->number;
+         rl.copcode_is_3 = 3;
+         rl.alength_is_4 = 4;
+         rl.addend = ref->where->offset - ref->where->section->address;
+         rl.aopcode_is_0x20 = 0x20;
+       }
+
+      else
+       {
+         rl.bcount = 11;       /* Always 11 for us */
+         rl.op = OP_SEC_REF;
+         rl.secn = ref->where->section->number;
+         rl.copcode_is_3 = 3;
+         rl.alength_is_4 = 4;
+         rl.addend = -ref->where->section->address;
+         rl.aopcode_is_0x20 = 0x20;
+       }
+      rl.end = 0xff;
+      if (rl.op == OP_SEC_REF
+         || rl.op == OP_EXT_REF)
+       {
+         sysroff_swap_rl_out (file, &rl);
+       }
+    }
+}
+
+static void
+wr_object_body (p)
+     struct coff_ofile *p;
+{
+  int i;
+  for (i = 1; i < p->nsections; i++)
+    {
+      wr_sh (p, p->sections + i);
+      wr_ob (p, p->sections + i);
+      wr_rl (p, p->sections + i);
+    }
+}
+
+static void
+wr_dps_start (sfile, section, scope, type, nest)
+     struct coff_sfile *sfile;
+     struct coff_section *section;
+     struct coff_scope *scope;
+     int type;
+     int nest;
+{
+  struct IT_dps dps;
+  dps.end = 0;
+  dps.opt = 0;
+  dps.type = type;
+  if (scope->sec)
+    {
+      dps.san = scope->sec->number;
+      dps.address = scope->offset - find_base (sfile, scope->sec);
+      dps.block_size = scope->size;
+      if (debug)
+       {
+         printf ("DPS %s %d %x\n",
+                 sfile->name,
+                 nest,
+                 dps.address);
+
+       }
+    }
+  else
+    {
+      dps.san = 0;
+      dps.address = 0;
+      dps.block_size = 0;
+    }
+
+  dps.nesting = nest;
+  dps.neg = 0x1001;
+  sysroff_swap_dps_out (file, &dps);
+}
+
+static void
+wr_dps_end (section, scope, type)
+     struct coff_section *section;
+     struct coff_scope *scope;
+     int type;
+{
+  struct IT_dps dps;
+  dps.end = 1;
+  dps.type = type;
+  sysroff_swap_dps_out (file, &dps);
+}
+
+static int *
+nints (x)
+     int x;
+{
+  return (int *) (xcalloc (sizeof (int), x));
+}
+
+static void walk_tree_symbol ();
+static void
+walk_tree_type_1 (sfile, symbol, type, nest)
+     struct coff_sfile *sfile;
+     struct coff_symbol *symbol;
+     struct coff_type *type;
+     int nest;
+{
+  switch (type->type)
+    {
+    case coff_secdef_type:
+    case coff_basic_type:
+      {
+       struct IT_dbt dbt;
+
+       switch (type->u.basic)
+         {
+         case T_NULL:
+         case T_VOID:
+           dbt.btype = BTYPE_VOID;
+           dbt.sign = BTYPE_UNSPEC;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         case T_CHAR:
+           dbt.btype = BTYPE_CHAR;
+           dbt.sign = BTYPE_UNSPEC;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         case T_SHORT:
+         case T_INT:
+         case T_LONG:
+           dbt.btype = BTYPE_INT;
+           dbt.sign = SIGN_SIGNED;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         case T_FLOAT:
+           dbt.btype = BTYPE_FLOAT;
+           dbt.fptype = FPTYPE_SINGLE;
+           break;
+         case T_DOUBLE:
+           dbt.btype = BTYPE_FLOAT;
+           dbt.fptype = FPTYPE_DOUBLE;
+           break;
+         case T_LNGDBL:
+           dbt.btype = BTYPE_FLOAT;
+           dbt.fptype = FPTYPE_EXTENDED;
+           break;
+         case T_UCHAR:
+           dbt.btype = BTYPE_CHAR;
+           dbt.sign = SIGN_UNSIGNED;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         case T_USHORT:
+         case T_UINT:
+         case T_ULONG:
+           dbt.btype = BTYPE_INT;
+           dbt.sign = SIGN_UNSIGNED;
+           dbt.fptype = FPTYPE_NOTSPEC;
+           break;
+         }
+       dbt.bitsize = type->size;
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+       break;
+      }
+    case coff_pointer_type:
+      {
+       struct IT_dpt dpt;
+       walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1);
+       dpt.neg = 0x1001;
+       sysroff_swap_dpt_out (file, &dpt);
+       break;
+      }
+
+    case coff_function_type:
+      {
+       struct IT_dfp dfp;
+       struct coff_symbol *param;
+       dfp.end = 0;
+       dfp.spare = 0;
+       dfp.nparams = type->u.function.parameters->nvars;
+       dfp.neg = 0x1001;
+
+       walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1);
+
+       sysroff_swap_dfp_out (file, &dfp);
+
+       for (param = type->u.function.parameters->vars_head;
+            param;
+            param = param->next)
+         {
+           walk_tree_symbol (sfile, 0, param, nest);
+         }
+       dfp.end = 1;
+       sysroff_swap_dfp_out (file, &dfp);
+       break;
+      }
+
+    case coff_structdef_type:
+      {
+       struct IT_dbt dbt;
+       struct IT_dds dds;
+       struct coff_symbol *member;
+       dds.spare = 0;
+       dbt.btype = BTYPE_STRUCT;
+       dbt.bitsize = type->size;
+       dbt.sign = SIGN_UNSPEC;
+       dbt.fptype = FPTYPE_NOTSPEC;
+       dbt.sid = get_member_id (type->u.astructdef.idx);
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+       dds.end = 0;
+       dds.neg = 0x1001;
+       sysroff_swap_dds_out (file, &dds);
+       for (member = type->u.astructdef.elements->vars_head;
+            member;
+            member = member->next)
+         {
+           walk_tree_symbol (sfile, 0, member, nest + 1);
+         }
+
+       dds.end = 1;
+       sysroff_swap_dds_out (file, &dds);
+
+      }
+      break;
+    case coff_structref_type:
+      {
+       struct IT_dbt dbt;
+       dbt.btype = BTYPE_TAG;
+       dbt.bitsize = type->size;
+       dbt.sign = SIGN_UNSPEC;
+       dbt.fptype = FPTYPE_NOTSPEC;
+       if (type->u.astructref.ref)
+         {
+           dbt.sid = get_member_id (type->u.astructref.ref->number);
+         }
+       else
+         {
+           dbt.sid = 0;
+         }
+
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+      }
+      break;
+    case coff_array_type:
+      {
+       struct IT_dar dar;
+       int j;
+       int dims = 1;           /* Only output one dimension at a time */
+       dar.dims = dims;
+       dar.variable = nints (dims);
+       dar.subtype = nints (dims);
+       dar.spare = nints (dims);
+       dar.max_variable = nints (dims);
+       dar.maxspare = nints (dims);
+       dar.max = nints (dims);
+       dar.min_variable = nints (dims);
+       dar.min = nints (dims);
+       dar.minspare = nints (dims);
+       dar.neg = 0x1001;
+       dar.length = type->size / type->u.array.dim;
+       for (j = 0; j < dims; j++)
+         {
+           dar.variable[j] = VARIABLE_FIXED;
+           dar.subtype[j] = SUB_INTEGER;
+           dar.spare[j] = 0;
+           dar.max_variable[j] = 0;
+           dar.max[j] = type->u.array.dim;
+           dar.min_variable[j] = 0;
+           dar.min[j] = 1;     /* Why isn't this 0 ? */
+         }
+       walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1);
+       sysroff_swap_dar_out (file, &dar);
+      }
+      break;
+    case coff_enumdef_type:
+      {
+       struct IT_dbt dbt;
+       struct IT_den den;
+       struct coff_symbol *member;
+       dbt.btype = BTYPE_ENUM;
+       dbt.bitsize = type->size;
+       dbt.sign = SIGN_UNSPEC;
+       dbt.fptype = FPTYPE_NOTSPEC;
+       dbt.sid = get_member_id (type->u.aenumdef.idx);
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+
+       den.end = 0;
+       den.neg = 0x1001;
+       den.spare = 0;
+       sysroff_swap_den_out (file, &den);
+       for (member = type->u.aenumdef.elements->vars_head;
+            member;
+            member = member->next)
+         {
+           walk_tree_symbol (sfile, 0, member, nest + 1);
+         }
+
+       den.end = 1;
+       sysroff_swap_den_out (file, &den);
+      }
+      break;
+
+      break;
+    case coff_enumref_type:
+      {
+       struct IT_dbt dbt;
+       dbt.btype = BTYPE_TAG;
+       dbt.bitsize = type->size;
+       dbt.sign = SIGN_UNSPEC;
+       dbt.fptype = FPTYPE_NOTSPEC;
+       dbt.sid = get_member_id (type->u.aenumref.ref->number);
+       dbt.neg = 0x1001;
+       sysroff_swap_dbt_out (file, &dbt);
+      }
+      break;
+    default:
+      abort ();
+    }
+}
+
+/* Obsolete ? 
+   static void
+   dty_start ()
+   {
+   struct IT_dty dty;
+   dty.end = 0;
+   dty.neg = 0x1001;
+   dty.spare = 0;
+   sysroff_swap_dty_out (file, &dty);
+   }
+
+   static void
+   dty_stop ()
+   {
+   struct IT_dty dty;
+   dty.end = 0;
+   dty.neg = 0x1001;
+   dty.end = 1;
+   sysroff_swap_dty_out (file, &dty);
+   }
+
+
+   static void
+   dump_tree_structure (sfile, symbol, type, nest)
+   struct coff_sfile *sfile;
+   struct coff_symbol *symbol;
+   struct coff_type *type;
+   int nest;
+   {
+   if (symbol->type->type == coff_function_type)
+   {
+
+
+   }
+
+   }
+ */
+
+static void
+walk_tree_type (sfile, symbol, type, nest)
+
+     struct
+     coff_sfile *sfile;
+     struct coff_symbol *symbol;
+     struct coff_type *type;
+     int nest;
+{
+  if (symbol->type->type == coff_function_type)
+    {
+
+      struct IT_dty dty;
+      dty.end = 0;
+      dty.neg = 0x1001;
+
+      sysroff_swap_dty_out (file, &dty);
+      walk_tree_type_1 (sfile, symbol, type, nest);
+      dty.end = 1;
+      sysroff_swap_dty_out (file, &dty);
+
+      wr_dps_start (sfile,
+                   symbol->where->section,
+                   symbol->type->u.function.code,
+                   BLOCK_TYPE_FUNCTION, nest);
+      wr_dps_start (sfile, symbol->where->section,
+                   symbol->type->u.function.code,
+                   BLOCK_TYPE_BLOCK, nest);
+      walk_tree_scope (symbol->where->section,
+                      sfile,
+                      symbol->type->u.function.code,
+                      nest + 1, BLOCK_TYPE_BLOCK);
+
+      wr_dps_end (symbol->where->section,
+                 symbol->type->u.function.code,
+                 BLOCK_TYPE_BLOCK);
+      wr_dps_end (symbol->where->section,
+                 symbol->type->u.function.code, BLOCK_TYPE_FUNCTION);
+
+    }
+  else
+    {
+      struct IT_dty dty;
+      dty.end = 0;
+      dty.neg = 0x1001;
+      sysroff_swap_dty_out (file, &dty);
+      walk_tree_type_1 (sfile, symbol, type, nest);
+      dty.end = 1;
+      sysroff_swap_dty_out (file, &dty);
+    }
+
+}
+
+
+
+static void
+walk_tree_symbol (sfile, section, symbol, nest)
+     struct coff_sfile *sfile;
+     struct coff_section *section;
+     struct coff_symbol *symbol;
+     int nest;
+{
+  struct IT_dsy dsy;
+
+  memset(&dsy, 0, sizeof(dsy));
+  dsy.nesting = nest;
+
+  switch (symbol->type->type)
+    {
+    case coff_function_type:
+      dsy.type = STYPE_FUNC;
+      dsy.assign = 1;
+      break;
+    case coff_structref_type:
+    case coff_pointer_type:
+    case coff_array_type:
+    case coff_basic_type:
+    case coff_enumref_type:
+      dsy.type = STYPE_VAR;
+      dsy.assign = 1;
+      break;
+    case coff_enumdef_type:
+      dsy.type = STYPE_TAG;
+      dsy.assign = 0;
+      dsy.magic = 2;
+      break;
+    case coff_structdef_type:
+      dsy.type = STYPE_TAG;
+      dsy.assign = 0;
+      dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1;
+      break;
+    case coff_secdef_type:
+      return;
+    default:
+      abort ();
+    }
+
+  if (symbol->where->where == coff_where_member_of_struct)
+    {
+      dsy.assign = 0;
+      dsy.type = STYPE_MEMBER;
+    }
+  if (symbol->where->where == coff_where_member_of_enum)
+    {
+      dsy.type = STYPE_ENUM;
+      dsy.assign = 0;
+      dsy.evallen = 4;
+      dsy.evalue = symbol->where->offset;
+    }
+
+  if (symbol->type->type == coff_structdef_type
+      || symbol->where->where == coff_where_entag
+      || symbol->where->where == coff_where_strtag)
+    {
+      dsy.snumber = get_member_id (symbol->number);
+    }
+  else
+    {
+      dsy.snumber = get_ordinary_id (symbol->number);
+    }
+
+
+  dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name;
+
+  switch (symbol->visible->type)
+    {
+    case coff_vis_common:
+    case coff_vis_ext_def:
+      dsy.ainfo = AINFO_STATIC_EXT_DEF;
+      break;
+    case coff_vis_ext_ref:
+      dsy.ainfo = AINFO_STATIC_EXT_REF;
+      break;
+    case coff_vis_int_def:
+      dsy.ainfo = AINFO_STATIC_INT;
+      break;
+    case coff_vis_auto:
+    case coff_vis_autoparam:
+      dsy.ainfo = AINFO_AUTO;
+      break;
+    case coff_vis_register:
+    case coff_vis_regparam:
+      dsy.ainfo = AINFO_REG;
+      break;
+      break;
+    case coff_vis_tag:
+    case coff_vis_member_of_struct:
+    case coff_vis_member_of_enum:
+      break;
+    default:
+      abort ();
+    }
+
+  dsy.dlength = symbol->type->size;
+  switch (symbol->where->where)
+    {
+    case coff_where_memory:
+
+      dsy.section = symbol->where->section->number;
+#ifdef FOOP
+      dsy.section = 0;
+#endif
+      break;
+    case coff_where_member_of_struct:
+    case coff_where_member_of_enum:
+    case coff_where_stack:
+    case coff_where_register:
+    case coff_where_unknown:
+    case coff_where_strtag:
+
+    case coff_where_entag:
+    case coff_where_typedef:
+      break;
+    default:
+      abort ();
+    }
+
+  switch (symbol->where->where)
+    {
+    case coff_where_memory:
+      dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section);
+      break;
+    case coff_where_stack:
+      dsy.address = symbol->where->offset;
+      break;
+    case coff_where_member_of_struct:
+
+
+      if (symbol->where->bitsize)
+       {
+         int bits = (symbol->where->offset * 8 + symbol->where->bitoffset);
+         dsy.bitunit = 1;
+         dsy.field_len = symbol->where->bitsize;
+         dsy.field_off = (bits / 32) * 4;
+         dsy.field_bitoff = bits % 32;
+       }
+      else
+       {
+         dsy.bitunit = 0;
+
+         dsy.field_len = symbol->type->size;
+         dsy.field_off = symbol->where->offset;
+       }
+      break;
+    case coff_where_member_of_enum:
+      /*      dsy.bitunit = 0;
+         dsy.field_len  = symbol->type->size;
+         dsy.field_off = symbol->where->offset; */
+      break;
+    case coff_where_register:
+    case coff_where_unknown:
+    case coff_where_strtag:
+
+    case coff_where_entag:
+    case coff_where_typedef:
+      break;
+    default:
+      abort ();
+    }
+
+  if (symbol->where->where == coff_where_register)
+    dsy.reg = rnames[symbol->where->offset];
+
+  switch (symbol->visible->type)
+    {
+    case coff_vis_common:
+      /* We do this 'cause common C symbols are treated as extdefs */
+    case coff_vis_ext_def:
+    case coff_vis_ext_ref:
+
+      dsy.ename = symbol->name;
+      break;
+
+    case coff_vis_regparam:
+    case coff_vis_autoparam:
+      dsy.type = STYPE_PARAMETER;
+      break;
+
+    case coff_vis_int_def:
+
+    case coff_vis_auto:
+    case coff_vis_register:
+    case coff_vis_tag:
+    case coff_vis_member_of_struct:
+    case coff_vis_member_of_enum:
+      break;
+    default:
+      abort ();
+    }
+
+  dsy.sfn = 0;
+  dsy.sln = 2;
+
+  dsy.neg = 0x1001;
+
+
+  sysroff_swap_dsy_out (file, &dsy);
+
+  walk_tree_type (sfile, symbol, symbol->type, nest);
+}
+
+
+static void
+walk_tree_scope (section, sfile, scope, nest, type)
+     struct coff_section *section;
+     struct coff_sfile *sfile;
+     struct coff_scope *scope;
+     int nest;
+     int type;
+{
+  struct coff_symbol *vars;
+  struct coff_scope *child;
+
+  if (scope->vars_head
+      || (scope->list_head && scope->list_head->vars_head))
+    {
+      wr_dps_start (sfile, section, scope, type, nest);
+
+      if (nest == 0)
+       wr_globals (tree, sfile, nest + 1);
+
+      for (vars = scope->vars_head; vars; vars = vars->next)
+       {
+         walk_tree_symbol (sfile, section, vars, nest);
+       }
+
+      for (child = scope->list_head; child; child = child->next)
+       {
+         walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK);
+       }
+
+      wr_dps_end (section, scope, type);
+    }
+}
+static void
+walk_tree_sfile (section, sfile)
+     struct coff_section *section;
+     struct coff_sfile *sfile;
+{
+  walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT);
+
+}
+
+static void
+wr_program_structure (p, sfile)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+{
+
+  walk_tree_sfile (p->sections + 4, sfile);
+
+}
+
+static void
+wr_du (p, sfile, n)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+     int n;
+{
+  struct IT_du du;
+  int lim;
+#if 0
+  struct coff_symbol *symbol;
+  static int incit = 0x500000;
+  int used = 0;
+#endif
+  int i;
+  int j;
+  unsigned int *lowest = (unsigned *) nints (p->nsections);
+  unsigned int *highest = (unsigned *) nints (p->nsections);
+  du.format = bfd_get_file_flags (abfd) & EXEC_P ? 0 : 1;
+  du.optimized = 0;
+  du.stackfrmt = 0;
+  du.spare = 0;
+  du.unit = n;
+  du.sections = p->nsections - 1;
+  du.san = (int *) xcalloc (sizeof (int), du.sections);
+  du.address = nints (du.sections);
+  du.length = nints (du.sections);
+
+  for (i = 0; i < du.sections; i++)
+    {
+      lowest[i] = ~0;
+      highest[i] = 0;
+    }
+
+  /* Look through all the symbols and try and work out the extents in this
+     source file */
+#if 0
+  for (symbol = sfile->scope->vars_head;
+       symbol;
+       symbol = symbol->next)
+    {
+      if (symbol->type->type == coff_secdef_type)
+       {
+         unsigned int low = symbol->where->offset;
+         unsigned int high = symbol->where->offset + symbol->type->size - 1;
+         struct coff_section *section = symbol->where->section;
+
+         int sn = section->number;
+         if (low < lowest[sn])
+           lowest[sn] = low;
+         if (high > highest[sn])
+           highest[sn] = high;
+       }
+    }
+
+
+  for (i = 0; i < du.sections; i++)
+    {
+      if (highest[i] == 0)
+       {
+         lowest[i] = highest[i] = incit;
+       }
+      du.san[used] = i;
+      du.length[used] = highest[i] - lowest[i];
+      du.address[used] = bfd_get_file_flags (abfd) & EXEC_P ? lowest[i] : 0;
+      if (debug)
+       {
+         printf (" section %6s 0x%08x..0x%08x\n",
+                 p->sections[i + 1].name,
+                 lowest[i],
+                 highest[i]);
+       }
+      used++;
+    }
+
+#endif
+  lim = du.sections;
+  for (j = 0; j < lim; j++)
+    {
+      int src = j;
+      int dst = j;
+      du.san[dst] = dst;
+      if (sfile->section[src].init)
+       {
+         du.length[dst]
+           = sfile->section[src].high - sfile->section[src].low + 1;
+         du.address[dst]
+           = sfile->section[src].low;
+       }
+      else
+       {
+         du.length[dst] = 0;
+         du.address[dst] = 0;
+       }
+      if (debug)
+       {
+         if (sfile->section[src].parent)
+           {
+             printf (" section %6s 0x%08x..0x%08x\n",
+                     sfile->section[src].parent->name,
+                     du.address[dst],
+                     du.address[dst] + du.length[dst] - 1);
+           }
+       }
+      du.sections = dst + 1;
+    }
+
+  du.tool = "c_gcc";
+  du.date = DATE;
+
+  sysroff_swap_du_out (file, &du);
+}
+
+static void
+wr_dus (p, sfile)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+{
+
+  struct IT_dus dus;
+
+  dus.efn = 0x1001;
+  dus.ns = 1;                  /* p->nsources; sac 14 jul 94 */
+  dus.drb = nints (dus.ns);
+  dus.fname = (char **) xcalloc (sizeof (char *), dus.ns);
+  dus.spare = nints (dus.ns);
+  dus.ndir = 0;
+  /* Find the filenames */
+#if 0
+  i = 0;
+
+  for (sfile = p->source_head;
+       sfile;
+       sfile = sfile->next)
+    {
+      dus.drb[i] = 0;
+      dus.spare[i] = 0;
+      dus.fname[i] = sfile->name;
+      i++;
+    }
+#else
+  dus.drb[0] = 0;
+  dus.fname[0] = sfile->name;
+#endif
+
+  sysroff_swap_dus_out (file, &dus);
+
+}
+
+/* Find the offset of the .text section for this sfile in the
+   .text section for the output file */
+
+static int
+find_base (sfile, section)
+     struct coff_sfile *sfile;
+     struct coff_section *section;
+{
+  return sfile->section[section->number].low;
+}
+static void
+wr_dln (p, sfile, n)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+     int n;
+
+{
+#if 0
+  if (n == 0)
+    {
+      /* Count up all the linenumbers */
+      struct coff_symbol *sy;
+      int lc = 0;
+      struct IT_dln dln;
+
+      int idx;
+
+      for (sy = p->symbol_list_head;
+          sy;
+          sy = sy->next_in_ofile_list)
+       {
+         struct coff_type *t = sy->type;
+         if (t->type == coff_function_type)
+           {
+             struct coff_line *l = t->u.function.lines;
+             lc += l->nlines;
+           }
+       }
+
+      dln.sfn = nints (lc);
+      dln.sln = nints (lc);
+      dln.lln = nints (lc);
+      dln.section = nints (lc);
+
+      dln.from_address = nints (lc);
+      dln.to_address = nints (lc);
+
+
+      dln.neg = 0x1001;
+
+      dln.nln = lc;
+
+      /* Run through once more and fill up the structure */
+      idx = 0;
+      for (sy = p->symbol_list_head;
+          sy;
+          sy = sy->next_in_ofile_list)
+       {
+         if (sy->type->type == coff_function_type)
+           {
+             int i;
+             struct coff_line *l = sy->type->u.function.lines;
+             for (i = 0; i < l->nlines; i++)
+               {
+                 dln.section[idx] = sy->where->section->number;
+                 dln.sfn[idx] = n;
+                 dln.sln[idx] = l->lines[i];
+                 dln.from_address[idx] = l->addresses[i];
+                 if (idx)
+                   dln.to_address[idx - 1] = dln.from_address[idx];
+                 idx++;
+               }
+           }
+         n++;
+       }
+      sysroff_swap_dln_out (file, &dln);
+    }
+
+#endif
+#if 1
+  /* Count up all the linenumbers */
+
+  struct coff_symbol *sy;
+  int lc = 0;
+  struct IT_dln dln;
+
+  int idx;
+
+  for (sy = sfile->scope->vars_head;
+       sy;
+       sy = sy->next)
+    {
+      struct coff_type *t = sy->type;
+      if (t->type == coff_function_type)
+       {
+         struct coff_line *l = t->u.function.lines;
+         if (l)
+           lc += l->nlines;
+       }
+    }
+
+  dln.sfn = nints (lc);
+  dln.sln = nints (lc);
+  dln.cc = nints (lc);
+  dln.section = nints (lc);
+
+  dln.from_address = nints (lc);
+  dln.to_address = nints (lc);
+
+
+  dln.neg = 0x1001;
+
+  dln.nln = lc;
+
+  /* Run through once more and fill up the structure */
+  idx = 0;
+  for (sy = sfile->scope->vars_head;
+       sy;
+       sy = sy->next)
+    {
+      if (sy->type->type == coff_function_type)
+       {
+         int i;
+         struct coff_line *l = sy->type->u.function.lines;
+         if (l)
+           {
+             int base = find_base (sfile, sy->where->section);
+             for (i = 0; i < l->nlines; i++)
+               {
+                 dln.section[idx] = sy->where->section->number;
+                 dln.sfn[idx] = 0;
+                 dln.sln[idx] = l->lines[i];
+                 dln.from_address[idx] =
+                   l->addresses[i] + sy->where->section->address - base;
+                 dln.cc[idx] = 0;
+                 if (idx)
+                   dln.to_address[idx - 1] = dln.from_address[idx];
+                 idx++;
+
+               }
+             dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2;
+           }
+       }
+    }
+  if (lc)
+    sysroff_swap_dln_out (file, &dln);
+#endif
+}
+
+/* Write the global symbols out to the debug info */
+static void
+wr_globals (p, sfile, n)
+     struct coff_ofile *p;
+     struct coff_sfile *sfile;
+     int n;
+{
+  struct coff_symbol *sy;
+  for (sy = p->symbol_list_head;
+       sy;
+       sy = sy->next_in_ofile_list)
+    {
+      if (sy->visible->type == coff_vis_ext_def
+         || sy->visible->type == coff_vis_ext_ref)
+       {
+         /* Only write out symbols if they belong to
+            the current source file */
+         if (sy->sfile == sfile)
+           walk_tree_symbol (sfile, 0, sy, 0);
+
+       }
+    }
+}
+
+static void
+wr_debug (p)
+     struct coff_ofile *p;
+{
+  struct coff_sfile *sfile;
+  int n = 0;
+  for (sfile = p->source_head;
+       sfile;
+       sfile = sfile->next)
+
+    {
+      if (debug)
+       {
+         printf ("%s\n", sfile->name);
+       }
+      wr_du (p, sfile, n);
+      wr_dus (p, sfile);
+      wr_program_structure (p, sfile);
+      wr_dln (p, sfile, n);
+      n++;
+    }
+}
+
+static void
+wr_cs ()
+{
+  /* It seems that the CS struct is not normal - the size is wrong
+     heres one I prepared earlier.. */
+  static char b[] = {
+    0x80,                      /* IT */
+    0x21,                      /* RL */
+    0x00,                      /* number of chars in variable length part */
+    0x80,                      /* hd */ 
+    0x00,                      /* hs */ 
+    0x80,                      /* un */ 
+    0x00,                      /* us */ 
+    0x80,                      /* sc */ 
+    0x00,                      /* ss */ 
+    0x80,                      /* er */ 
+    0x80,                      /* ed */ 
+    0x80,                      /* sh */ 
+    0x80,                      /* ob */ 
+    0x80,                      /* rl */ 
+    0x80,                      /* du */
+    0x80,                      /* dps */
+    0x80,                      /* dsy */
+    0x80,                      /* dty */
+    0x80,                      /* dln */
+    0x80,                      /* dso */
+    0x80,                      /* dus */
+    0x00,                      /* dss */
+    0x80,                      /* dbt */
+    0x00,                      /* dpp */
+    0x80,                      /* dfp */
+    0x80,                      /* den */
+    0x80,                      /* dds */
+    0x80,                      /* dar */
+    0x80,                      /* dpt */
+    0x00,                      /* dul */
+    0x00,                      /* dse */
+    0x00,                      /* dot */
+    0xDE                       /* CS */
+  };
+  fwrite (b, 1, sizeof (b), file);
+}
+
+/* Write out the SC records for a unit.  Create an SC
+   for all the sections which appear in the output file, even
+   if there isn't an equivalent one on the input */
+
+static int
+wr_sc (ptr, sfile)
+     struct coff_ofile *ptr;
+     struct coff_sfile *sfile;
+{
+  int i;
+int scount = 0;
+  /* First work out the total number of sections */
+
+  int total_sec = ptr->nsections;
+
+  struct myinfo
+    {
+      struct coff_section *sec;
+      struct coff_symbol *symbol;
+    };
+  struct coff_symbol *symbol;
+
+  struct myinfo *info
+    = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo));
+
+
+
+  for (i = 0; i < total_sec; i++)
+    {
+      info[i].sec = ptr->sections + i;
+      info[i].symbol = 0;
+    }
+
+  for (symbol = sfile->scope->vars_head;
+       symbol;
+       symbol = symbol->next)
+    {
+
+      if (symbol->type->type == coff_secdef_type)
+       {
+         for (i = 0; i < total_sec; i++)
+           {
+             if (symbol->where->section == info[i].sec)
+               {
+                 info[i].symbol = symbol;
+                 break;
+               }
+           }
+       }
+    }
+
+  /* Now output all the section info, and fake up some stuff for sections
+     we don't have */
+
+  for (i = 1; i < total_sec; i++)
+    {
+      struct IT_sc sc;
+      char *name;
+      symbol = info[i].symbol;
+      sc.spare = 0;
+      sc.spare1 = 0;
+      if (!symbol)
+       {
+         /* Don't have a symbol set aside for this section, which means that nothing
+            in this file does anything for the section. */
+         sc.format = !(bfd_get_file_flags (abfd) & EXEC_P);
+         sc.addr = 0;
+         sc.length = 0;
+         name = info[i].sec->name;
+       }
+      else
+       {
+         if (bfd_get_file_flags (abfd) & EXEC_P)
+           {
+             sc.format = 0;
+             sc.addr = symbol->where->offset;
+           }
+         else
+           {
+             sc.format = 1;
+             sc.addr = 0;
+           }
+         sc.length = symbol->type->size;
+         name = symbol->name;
+       }
+
+      sc.align = 4;
+
+      sc.concat = CONCAT_SIMPLE;
+      sc.read = 3;
+      sc.write = 3;
+      sc.exec = 3;
+      sc.init = 3;
+      sc.mode = 3;
+      sc.spare = 0;
+      sc.segadd = 0;
+      sc.spare1 = 0;           /* If not zero, then it doesn't work */
+      sc.name = section_translate (name);
+      if (strlen (sc.name) == 1)
+       {
+         switch (sc.name[0])
+           {
+           case 'D':
+           case 'B':
+             sc.contents = CONTENTS_DATA;
+             break;
+           default:
+             sc.contents = CONTENTS_CODE;
+           }
+       }
+      else
+       {
+         sc.contents = CONTENTS_CODE;
+       }
+#if 0
+      /* NEW */
+      if (sc.length) {
+#endif
+       sysroff_swap_sc_out (file, &sc);
+       scount++;
+#if 0
+      }
+#endif
+    }
+return scount;
+}
+
+
+/* Write out the ER records for a unit. */
+static void
+wr_er (ptr, sfile, first)
+     struct coff_ofile *ptr;
+     struct coff_sfile *sfile;
+     int first;
+{
+  int idx = 0;
+  struct coff_symbol *sym;
+  if (first)
+    {
+      for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list)
+       {
+         if (sym->visible->type == coff_vis_ext_ref)
+           {
+             struct IT_er er;
+             er.spare = 0;
+             er.type = ER_NOTSPEC;
+             er.name = sym->name;
+             sysroff_swap_er_out (file, &er);
+             sym->er_number = idx++;
+           }
+       }
+    }
+}
+
+/* Write out the ED records for a unit. */
+static void
+wr_ed (ptr, sfile, first)
+     struct coff_ofile *ptr;
+     struct coff_sfile *sfile;
+     int first;
+{
+  struct coff_symbol *s;
+  if (first)
+    {
+      for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list)
+       {
+         if (s->visible->type == coff_vis_ext_def
+             || s->visible->type == coff_vis_common)
+           {
+             struct IT_ed ed;
+
+             ed.section = s->where->section->number;
+             ed.spare = 0;
+             if (s->where->section->data)
+               {
+                 ed.type = ED_TYPE_DATA;
+               }
+             else if (s->where->section->code & SEC_CODE)
+               {
+                 ed.type = ED_TYPE_ENTRY;
+               }
+             else
+               {
+                 ed.type = ED_TYPE_NOTSPEC;
+                 ed.type = ED_TYPE_DATA;
+               }
+             ed.address = s->where->offset - s->where->section->address;
+             ed.name = s->name;
+             sysroff_swap_ed_out (file, &ed);
+           }
+       }
+    }
+}
+
+static void
+wr_unit_info (ptr)
+     struct coff_ofile *ptr;
+{
+  struct coff_sfile *sfile;
+  int first = 1;
+  for (sfile = ptr->source_head;
+       sfile;
+       sfile = sfile->next)
+    {
+      long p1;
+      long p2;
+      int nsecs;
+      p1 = ftell (file);
+      wr_un (ptr, sfile, first, 0);
+      nsecs = wr_sc (ptr, sfile);
+      p2 = ftell (file);
+      fseek (file, p1, SEEK_SET);
+      wr_un (ptr, sfile, first, nsecs);
+      fseek (file, p2, SEEK_SET); 
+      wr_er (ptr, sfile, first);
+      wr_ed (ptr, sfile, first);
+      first = 0;
+    }
+}
+
+static void
+wr_module (p)
+     struct coff_ofile *p;
+{
+  wr_cs ();
+  wr_hd (p);
+  wr_unit_info (p);
+  wr_object_body (p);
+  wr_debug (p);
+  wr_tr ();
+}
+
+static int
+align (x)
+     int x;
+{
+  return (x + 3) & ~3;
+}
+
+/* Find all the common variables and turn them into
+   ordinary defs - dunno why, but thats what hitachi does with 'em */
+
+static void
+prescan (tree)
+     struct coff_ofile *tree;
+{
+  struct coff_symbol *s;
+  struct coff_section *common_section;
+  /* Find the common section - always section 3 */
+  common_section = tree->sections + 3;
+  for (s = tree->symbol_list_head;
+       s;
+       s = s->next_in_ofile_list)
+    {
+      if (s->visible->type == coff_vis_common)
+       {
+         struct coff_where *w = s->where;
+         /*      s->visible->type = coff_vis_ext_def; leave it as common */
+         common_section->size = align (common_section->size);
+         w->offset = common_section->size + common_section->address;
+         w->section = common_section;
+         common_section->size += s->type->size;
+         common_section->size = align (common_section->size);
+       }
+    }
+}
+
+char *program_name;
+
+static void
+show_usage (file, status)
+     FILE *file;
+     int status;
+{
+  fprintf (file, _("Usage: %s [-dhVq] in-file [out-file]\n"), program_name);
+  exit (status);
+}
+
+static void
+show_help ()
+{
+  printf (_("%s: Convert a COFF object file into a SYSROFF object file\n"),
+         program_name);
+  show_usage (stdout, 0);
+}
+
+
+
+int
+main (ac, av)
+     int ac;
+     char *av[];
+{
+  int opt;
+  static struct option long_options[] =
+  {
+    {"debug", no_argument, 0, 'd'},
+    {"quick", no_argument, 0, 'q'},
+    {"noprescan", no_argument, 0, 'n'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {NULL, no_argument, 0, 0}
+  };
+  char **matching;
+  char *input_file;
+  char *output_file;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = av[0];
+  xmalloc_set_program_name (program_name);
+
+  while ((opt = getopt_long (ac, av, "dhVqn", long_options,
+                            (int *) NULL))
+        != EOF)
+    {
+      switch (opt)
+       {
+       case 'q':
+         quick = 1;
+         break;
+       case 'n':
+         noprescan = 1;
+         break;
+       case 'd':
+         debug = 1;
+         break;
+       case 'h':
+         show_help ();
+         /*NOTREACHED */
+       case 'V':
+         printf (_("GNU %s version %s\n"), program_name, PROGRAM_VERSION);
+         exit (0);
+         /*NOTREACHED */
+       case 0:
+         break;
+       default:
+         show_usage (stderr, 1);
+         /*NOTREACHED */
+       }
+    }
+
+  /* The input and output files may be named on the command line.  */
+  output_file = NULL;
+  if (optind < ac)
+    {
+      input_file = av[optind];
+      ++optind;
+      if (optind < ac)
+       {
+         output_file = av[optind];
+         ++optind;
+         if (optind < ac)
+           show_usage (stderr, 1);
+         if (strcmp (input_file, output_file) == 0)
+           {
+             fprintf (stderr,
+                      _("%s: input and output files must be different\n"),
+                      program_name);
+             exit (1);
+           }
+       }
+    }
+  else
+    input_file = 0;
+
+  if (!input_file)
+    {
+      fprintf (stderr, _("%s: no input file specified\n"),
+              program_name);
+      exit (1);
+    }
+
+  if (!output_file)
+    {
+      /* Take a .o off the input file and stick on a .obj.  If
+         it doesn't end in .o, then stick a .obj on anyway */
+
+      int len = strlen (input_file);
+      output_file = xmalloc (len + 5);
+      strcpy (output_file, input_file);
+      if (len > 3
+         && output_file[len - 2] == '.'
+         && output_file[len - 1] == 'o')
+       {
+         output_file[len] = 'b';
+         output_file[len + 1] = 'j';
+         output_file[len + 2] = 0;
+       }
+      else
+       {
+         strcat (output_file, ".obj");
+       }
+    }
+
+  abfd = bfd_openr (input_file, 0);
+
+  if (!abfd)
+    bfd_fatal (input_file);
+
+  if (!bfd_check_format_matches (abfd, bfd_object, &matching))
+    {
+      bfd_nonfatal (input_file);
+      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
+       {
+         list_matching_formats (matching);
+         free (matching);
+       }
+      exit (1);
+    }
+
+  file = fopen (output_file, FOPEN_WB);
+
+  if (!file)
+    {
+      fprintf (stderr, _("%s: unable to open output file %s\n"),
+              program_name, output_file);
+      exit (1);
+    }
+
+  if (debug)
+    printf ("ids %d %d\n", base1, base2);
+  tree = coff_grok (abfd);
+  if (!noprescan)
+    prescan (tree);
+  wr_module (tree);
+  return 0;
+}
diff --git a/binutils/stabs.c b/binutils/stabs.c
new file mode 100644 (file)
index 0000000..a47b3bd
--- /dev/null
@@ -0,0 +1,5188 @@
+/* stabs.c -- Parse stabs debugging information
+   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file contains code which parses stabs debugging information.
+   The organization of this code is based on the gdb stabs reading
+   code.  The job it does is somewhat different, because it is not
+   trying to identify the correct address for anything.  */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "demangle.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* Meaningless definition needs by aout64.h.  FIXME.  */
+#define BYTES_IN_WORD 4
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+
+#ifndef DIR_SEPARATOR
+#ifdef _WIN32
+#define DIR_SEPARATOR '\\'
+#else
+#define DIR_SEPARATOR '/'
+#endif
+#endif
+
+/* The number of predefined XCOFF types.  */
+
+#define XCOFF_TYPE_COUNT 34
+
+/* This structure is used as a handle so that the stab parsing doesn't
+   need to use any static variables.  */
+
+struct stab_handle
+{
+  /* The BFD.  */
+  bfd *abfd;
+  /* True if this is stabs in sections.  */
+  boolean sections;
+  /* The symbol table.  */
+  asymbol **syms;
+  /* The number of symbols.  */
+  long symcount;
+  /* The accumulated file name string.  */
+  char *so_string;
+  /* The value of the last N_SO symbol.  */
+  bfd_vma so_value;
+  /* The value of the start of the file, so that we can handle file
+     relative N_LBRAC and N_RBRAC symbols.  */
+  bfd_vma file_start_offset;
+  /* The offset of the start of the function, so that we can handle
+     function relative N_LBRAC and N_RBRAC symbols.  */
+  bfd_vma function_start_offset;
+  /* The version number of gcc which compiled the current compilation
+     unit, 0 if not compiled by gcc.  */
+  int gcc_compiled;
+  /* Whether an N_OPT symbol was seen that was not generated by gcc,
+     so that we can detect the SunPRO compiler.  */
+  boolean n_opt_found;
+  /* The main file name.  */
+  char *main_filename;
+  /* A stack of unfinished N_BINCL files.  */
+  struct bincl_file *bincl_stack;
+  /* A list of finished N_BINCL files.  */
+  struct bincl_file *bincl_list;
+  /* Whether we are inside a function or not.  */
+  boolean within_function;
+  /* The address of the end of the function, used if we have seen an
+     N_FUN symbol while in a function.  This is -1 if we have not seen
+     an N_FUN (the normal case).  */
+  bfd_vma function_end;
+  /* The depth of block nesting.  */
+  int block_depth;
+  /* List of pending variable definitions.  */
+  struct stab_pending_var *pending;
+  /* Number of files for which we have types.  */
+  unsigned int files;
+  /* Lists of types per file.  */
+  struct stab_types **file_types;
+  /* Predefined XCOFF types.  */
+  debug_type xcoff_types[XCOFF_TYPE_COUNT];
+  /* Undefined tags.  */
+  struct stab_tag *tags;
+  /* Set by parse_stab_type if it sees a structure defined as a cross
+     reference to itself.  Reset by parse_stab_type otherwise.  */
+  boolean self_crossref;
+};
+
+/* A list of these structures is used to hold pending variable
+   definitions seen before the N_LBRAC of a block.  */
+
+struct stab_pending_var
+{
+  /* Next pending variable definition.  */
+  struct stab_pending_var *next;
+  /* Name.  */
+  const char *name;
+  /* Type.  */
+  debug_type type;
+  /* Kind.  */
+  enum debug_var_kind kind;
+  /* Value.  */
+  bfd_vma val;
+};
+
+/* A list of these structures is used to hold the types for a single
+   file.  */
+
+struct stab_types
+{
+  /* Next set of slots for this file.  */
+  struct stab_types *next;
+  /* Types indexed by type number.  */
+#define STAB_TYPES_SLOTS (16)
+  debug_type types[STAB_TYPES_SLOTS];
+};
+
+/* We keep a list of undefined tags that we encounter, so that we can
+   fill them in if the tag is later defined.  */
+
+struct stab_tag
+{
+  /* Next undefined tag.  */
+  struct stab_tag *next;
+  /* Tag name.  */
+  const char *name;
+  /* Type kind.  */
+  enum debug_type_kind kind;
+  /* Slot to hold real type when we discover it.  If we don't, we fill
+     in an undefined tag type.  */
+  debug_type slot;
+  /* Indirect type we have created to point at slot.  */
+  debug_type type;
+};
+
+static char *savestring PARAMS ((const char *, int));
+static bfd_vma parse_number PARAMS ((const char **, boolean *));
+static void bad_stab PARAMS ((const char *));
+static void warn_stab PARAMS ((const char *, const char *));
+static boolean parse_stab_string
+  PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *));
+static debug_type parse_stab_type
+  PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+          debug_type **));
+static boolean parse_stab_type_number
+  PARAMS ((const char **, int *));
+static debug_type parse_stab_range_type
+  PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+          const int *));
+static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **));
+static debug_type parse_stab_sun_floating_type
+  PARAMS ((PTR, const char **));
+static debug_type parse_stab_enum_type PARAMS ((PTR, const char **));
+static debug_type parse_stab_struct_type
+  PARAMS ((PTR, struct stab_handle *, const char *, const char **, boolean,
+          const int *));
+static boolean parse_stab_baseclasses
+  PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **));
+static boolean parse_stab_struct_fields
+  PARAMS ((PTR, struct stab_handle *, const char **, debug_field **,
+          boolean *));
+static boolean parse_stab_cpp_abbrev
+  PARAMS ((PTR, struct stab_handle *, const char **, debug_field *));
+static boolean parse_stab_one_struct_field
+  PARAMS ((PTR, struct stab_handle *, const char **, const char *,
+          debug_field *, boolean *));
+static boolean parse_stab_members
+  PARAMS ((PTR, struct stab_handle *, const char *, const char **,
+          const int *, debug_method **));
+static debug_type parse_stab_argtypes
+  PARAMS ((PTR, struct stab_handle *, debug_type, const char *, const char *,
+          debug_type, const char *, boolean, boolean, const char **));
+static boolean parse_stab_tilde_field
+  PARAMS ((PTR, struct stab_handle *, const char **, const int *,
+          debug_type *, boolean *));
+static debug_type parse_stab_array_type
+  PARAMS ((PTR, struct stab_handle *, const char **, boolean));
+static void push_bincl PARAMS ((struct stab_handle *, const char *, bfd_vma));
+static const char *pop_bincl PARAMS ((struct stab_handle *));
+static boolean find_excl
+  PARAMS ((struct stab_handle *, const char *, bfd_vma));
+static boolean stab_record_variable
+  PARAMS ((PTR, struct stab_handle *, const char *, debug_type,
+          enum debug_var_kind, bfd_vma));
+static boolean stab_emit_pending_vars PARAMS ((PTR, struct stab_handle *));
+static debug_type *stab_find_slot
+  PARAMS ((struct stab_handle *, const int *));
+static debug_type stab_find_type
+  PARAMS ((PTR, struct stab_handle *, const int *));
+static boolean stab_record_type
+  PARAMS ((PTR, struct stab_handle *, const int *, debug_type));
+static debug_type stab_xcoff_builtin_type
+  PARAMS ((PTR, struct stab_handle *, int));
+static debug_type stab_find_tagged_type
+  PARAMS ((PTR, struct stab_handle *, const char *, int,
+          enum debug_type_kind));
+static debug_type *stab_demangle_argtypes
+  PARAMS ((PTR, struct stab_handle *, const char *, boolean *));
+
+/* Save a string in memory.  */
+
+static char *
+savestring (start, len)
+     const char *start;
+     int len;
+{
+  char *ret;
+
+  ret = (char *) xmalloc (len + 1);
+  memcpy (ret, start, len);
+  ret[len] = '\0';
+  return ret;
+}
+
+/* Read a number from a string.  */
+
+static bfd_vma
+parse_number (pp, poverflow)
+     const char **pp;
+     boolean *poverflow;
+{
+  unsigned long ul;
+  const char *orig;
+
+  if (poverflow != NULL)
+    *poverflow = false;
+
+  orig = *pp;
+
+  errno = 0;
+  ul = strtoul (*pp, (char **) pp, 0);
+  if (ul + 1 != 0 || errno == 0)
+    {
+      /* If bfd_vma is larger than unsigned long, and the number is
+         meant to be negative, we have to make sure that we sign
+         extend properly.  */
+      if (*orig == '-')
+       return (bfd_vma) (bfd_signed_vma) (long) ul;
+      return (bfd_vma) ul;
+    }
+
+  /* Note that even though strtoul overflowed, it should have set *pp
+     to the end of the number, which is where we want it.  */
+
+  if (sizeof (bfd_vma) > sizeof (unsigned long))
+    {
+      const char *p;
+      boolean neg;
+      int base;
+      bfd_vma over, lastdig;
+      boolean overflow;
+      bfd_vma v;
+
+      /* Our own version of strtoul, for a bfd_vma.  */
+
+      p = orig;
+
+      neg = false;
+      if (*p == '+')
+       ++p;
+      else if (*p == '-')
+       {
+         neg = true;
+         ++p;
+       }
+
+      base = 10;
+      if (*p == '0')
+       {
+         if (p[1] == 'x' || p[1] == 'X')
+           {
+             base = 16;
+             p += 2;
+           }
+         else
+           {
+             base = 8;
+             ++p;
+           }
+       }
+
+      over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
+      lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
+
+      overflow = false;
+      v = 0;
+      while (1)
+       {
+         int d;
+
+         d = *p++;
+         if (isdigit ((unsigned char) d))
+           d -= '0';
+         else if (isupper ((unsigned char) d))
+           d -= 'A';
+         else if (islower ((unsigned char) d))
+           d -= 'a';
+         else
+           break;
+
+         if (d >= base)
+           break;
+
+         if (v > over || (v == over && (bfd_vma) d > lastdig))
+           {
+             overflow = true;
+             break;
+           }
+       }
+
+      if (! overflow)
+       {
+         if (neg)
+           v = - v;
+         return v;
+       }
+    }
+
+  /* If we get here, the number is too large to represent in a
+     bfd_vma.  */
+
+  if (poverflow != NULL)
+    *poverflow = true;
+  else
+    warn_stab (orig, _("numeric overflow"));
+
+  return 0;
+}
+
+/* Give an error for a bad stab string.  */
+
+static void
+bad_stab (p)
+     const char *p;
+{
+  fprintf (stderr, _("Bad stab: %s\n"), p);
+}
+
+/* Warn about something in a stab string.  */
+
+static void
+warn_stab (p, err)
+     const char *p;
+     const char *err;
+{
+  fprintf (stderr, _("Warning: %s: %s\n"), err, p);
+}
+
+/* Create a handle to parse stabs symbols with.  */
+
+/*ARGSUSED*/
+PTR
+start_stab (dhandle, abfd, sections, syms, symcount)
+     PTR dhandle;
+     bfd *abfd;
+     boolean sections;
+     asymbol **syms;
+     long symcount;
+{
+  struct stab_handle *ret;
+
+  ret = (struct stab_handle *) xmalloc (sizeof *ret);
+  memset (ret, 0, sizeof *ret);
+  ret->abfd = abfd;
+  ret->sections = sections;
+  ret->syms = syms;
+  ret->symcount = symcount;
+  ret->files = 1;
+  ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
+  ret->file_types[0] = NULL;
+  ret->function_end = (bfd_vma) -1;
+  return (PTR) ret;
+}
+
+/* When we have processed all the stabs information, we need to go
+   through and fill in all the undefined tags.  */
+
+boolean
+finish_stab (dhandle, handle)
+     PTR dhandle;
+     PTR handle;
+{
+  struct stab_handle *info = (struct stab_handle *) handle;
+  struct stab_tag *st;
+
+  if (info->within_function)
+    {
+      if (! stab_emit_pending_vars (dhandle, info)
+         || ! debug_end_function (dhandle, info->function_end))
+       return false;
+      info->within_function = false;
+      info->function_end = (bfd_vma) -1;
+    }
+
+  for (st = info->tags; st != NULL; st = st->next)
+    {
+      enum debug_type_kind kind;
+
+      kind = st->kind;
+      if (kind == DEBUG_KIND_ILLEGAL)
+       kind = DEBUG_KIND_STRUCT;
+      st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
+      if (st->slot == DEBUG_TYPE_NULL)
+       return false;
+    }
+
+  return true;
+}
+
+/* Handle a single stabs symbol.  */
+
+boolean
+parse_stab (dhandle, handle, type, desc, value, string)
+     PTR dhandle;
+     PTR handle;
+     int type;
+     int desc;
+     bfd_vma value;
+     const char *string;
+{
+  struct stab_handle *info = (struct stab_handle *) handle;
+
+  /* gcc will emit two N_SO strings per compilation unit, one for the
+     directory name and one for the file name.  We just collect N_SO
+     strings as we see them, and start the new compilation unit when
+     we see a non N_SO symbol.  */
+  if (info->so_string != NULL
+      && (type != N_SO || *string == '\0' || value != info->so_value))
+    {
+      if (! debug_set_filename (dhandle, info->so_string))
+       return false;
+      info->main_filename = info->so_string;
+
+      info->gcc_compiled = 0;
+      info->n_opt_found = false;
+
+      /* Generally, for stabs in the symbol table, the N_LBRAC and
+        N_RBRAC symbols are relative to the N_SO symbol value.  */
+      if (! info->sections)
+       info->file_start_offset = info->so_value;
+
+      /* We need to reset the mapping from type numbers to types.  We
+        can't free the old mapping, because of the use of
+        debug_make_indirect_type.  */
+      info->files = 1;
+      info->file_types = ((struct stab_types **)
+                         xmalloc (sizeof *info->file_types));
+      info->file_types[0] = NULL;
+
+      info->so_string = NULL;
+
+      /* Now process whatever type we just got.  */
+    }
+
+  switch (type)
+    {
+    case N_FN:
+    case N_FN_SEQ:
+      break;
+
+    case N_LBRAC:
+      /* Ignore extra outermost context from SunPRO cc and acc.  */
+      if (info->n_opt_found && desc == 1)
+       break;
+
+      if (! info->within_function)
+       {
+         fprintf (stderr, _("N_LBRAC not within function\n"));
+         return false;
+       }
+
+      /* Start an inner lexical block.  */
+      if (! debug_start_block (dhandle,
+                              (value
+                               + info->file_start_offset
+                               + info->function_start_offset)))
+       return false;
+
+      /* Emit any pending variable definitions.  */
+      if (! stab_emit_pending_vars (dhandle, info))
+       return false;
+
+      ++info->block_depth;
+      break;
+
+    case N_RBRAC:
+      /* Ignore extra outermost context from SunPRO cc and acc.  */
+      if (info->n_opt_found && desc == 1)
+       break;
+
+      /* We shouldn't have any pending variable definitions here, but,
+         if we do, we probably need to emit them before closing the
+         block.  */
+      if (! stab_emit_pending_vars (dhandle, info))
+       return false;
+
+      /* End an inner lexical block.  */
+      if (! debug_end_block (dhandle,
+                            (value
+                             + info->file_start_offset
+                             + info->function_start_offset)))
+       return false;
+
+      --info->block_depth;
+      if (info->block_depth < 0)
+       {
+         fprintf (stderr, _("Too many N_RBRACs\n"));
+         return false;
+       }
+      break;
+
+    case N_SO:
+      /* This always ends a function.  */
+      if (info->within_function)
+       {
+         bfd_vma endval;
+
+         endval = value;
+         if (*string != '\0'
+             && info->function_end != (bfd_vma) -1
+             && info->function_end < endval)
+           endval = info->function_end;
+         if (! stab_emit_pending_vars (dhandle, info)
+             || ! debug_end_function (dhandle, endval))
+           return false;
+         info->within_function = false;
+         info->function_end = (bfd_vma) -1;
+       }
+
+      /* An empty string is emitted by gcc at the end of a compilation
+         unit.  */
+      if (*string == '\0')
+       return true;
+
+      /* Just accumulate strings until we see a non N_SO symbol.  If
+         the string starts with a directory separator or some other
+        form of absolute path specification, we discard the previously
+         accumulated strings.  */
+      if (info->so_string == NULL)
+       info->so_string = xstrdup (string);
+      else
+       {
+         char *f;
+
+         f = info->so_string;
+
+         if (   (string[0] == '/')
+             || (string[0] == DIR_SEPARATOR)
+             || (   (DIR_SEPARATOR == '\\')
+                 && (string[1] == ':')
+                 && (   (string[2] == DIR_SEPARATOR)
+                     || (string[2] == '/'))))
+           info->so_string = xstrdup (string);
+         else
+           info->so_string = concat (info->so_string, string,
+                                     (const char *) NULL);
+         free (f);
+       }
+
+      info->so_value = value;
+
+      break;
+
+    case N_SOL:
+      /* Start an include file.  */
+      if (! debug_start_source (dhandle, string))
+       return false;
+      break;
+
+    case N_BINCL:
+      /* Start an include file which may be replaced.  */
+      push_bincl (info, string, value);
+      if (! debug_start_source (dhandle, string))
+       return false;
+      break;
+
+    case N_EINCL:
+      /* End an N_BINCL include.  */
+      if (! debug_start_source (dhandle, pop_bincl (info)))
+       return false;
+      break;
+
+    case N_EXCL:
+      /* This is a duplicate of a header file named by N_BINCL which
+         was eliminated by the linker.  */
+      if (! find_excl (info, string, value))
+       return false;
+      break;
+
+    case N_SLINE:
+      if (! debug_record_line (dhandle, desc,
+                              value + info->function_start_offset))
+       return false;
+      break;
+
+    case N_BCOMM:
+      if (! debug_start_common_block (dhandle, string))
+       return false;
+      break;
+
+    case N_ECOMM:
+      if (! debug_end_common_block (dhandle, string))
+       return false;
+      break;
+
+    case N_FUN:
+      if (*string == '\0')
+       {
+         if (info->within_function)
+           {
+             /* This always marks the end of a function; we don't
+                 need to worry about info->function_end.  */
+             if (info->sections)
+               value += info->function_start_offset;
+             if (! stab_emit_pending_vars (dhandle, info)
+                 || ! debug_end_function (dhandle, value))
+               return false;
+             info->within_function = false;
+             info->function_end = (bfd_vma) -1;
+           }
+         break;
+       }
+
+      /* A const static symbol in the .text section will have an N_FUN
+         entry.  We need to use these to mark the end of the function,
+         in case we are looking at gcc output before it was changed to
+         always emit an empty N_FUN.  We can't call debug_end_function
+         here, because it might be a local static symbol.  */
+      if (info->within_function
+         && (info->function_end == (bfd_vma) -1
+             || value < info->function_end))
+       info->function_end = value;
+
+      /* Fall through.  */
+      /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
+         symbols, and if it does not start with :S, gdb relocates the
+         value to the start of the section.  gcc always seems to use
+         :S, so we don't worry about this.  */
+      /* Fall through.  */
+    default:
+      {
+       const char *colon;
+
+       colon = strchr (string, ':');
+       if (colon != NULL
+           && (colon[1] == 'f' || colon[1] == 'F'))
+         {
+           if (info->within_function)
+             {
+               bfd_vma endval;
+
+               endval = value;
+               if (info->function_end != (bfd_vma) -1
+                   && info->function_end < endval)
+                 endval = info->function_end;
+               if (! stab_emit_pending_vars (dhandle, info)
+                   || ! debug_end_function (dhandle, endval))
+                 return false;
+               info->function_end = (bfd_vma) -1;
+             }
+           /* For stabs in sections, line numbers and block addresses
+               are offsets from the start of the function.  */
+           if (info->sections)
+             info->function_start_offset = value;
+           info->within_function = true;
+         }
+
+       if (! parse_stab_string (dhandle, info, type, desc, value, string))
+         return false;
+      }
+      break;
+
+    case N_OPT:
+      if (string != NULL && strcmp (string, "gcc2_compiled.") == 0)
+       info->gcc_compiled = 2;
+      else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
+       info->gcc_compiled = 1;
+      else
+       info->n_opt_found = true;
+      break;
+
+    case N_OBJ:
+    case N_ENDM:
+    case N_MAIN:
+      break;
+    }
+
+  return true;
+}
+
+/* Parse the stabs string.  */
+
+static boolean
+parse_stab_string (dhandle, info, stabtype, desc, value, string)
+     PTR dhandle;
+     struct stab_handle *info;
+     int stabtype;
+     int desc;
+     bfd_vma value;
+     const char *string;
+{
+  const char *p;
+  char *name;
+  int type;
+  debug_type dtype;
+  boolean synonym;
+  boolean self_crossref;
+  unsigned int lineno;
+  debug_type *slot;
+
+  p = strchr (string, ':');
+  if (p == NULL)
+    return true;
+
+  while (p[1] == ':')
+    {
+      p += 2;
+      p = strchr (p, ':');
+      if (p == NULL)
+       {
+         bad_stab (string);
+         return false;
+       }
+    }
+
+  /* GCC 2.x puts the line number in desc.  SunOS apparently puts in
+     the number of bytes occupied by a type or object, which we
+     ignore.  */
+  if (info->gcc_compiled >= 2)
+    lineno = desc;
+  else
+    lineno = 0;
+
+  /* FIXME: Sometimes the special C++ names start with '.'.  */
+  name = NULL;
+  if (string[0] == '$')
+    {
+      switch (string[1])
+       {
+       case 't':
+         name = "this";
+         break;
+       case 'v':
+         /* Was: name = "vptr"; */
+         break;
+       case 'e':
+         name = "eh_throw";
+         break;
+       case '_':
+         /* This was an anonymous type that was never fixed up.  */
+         break;
+       case 'X':
+         /* SunPRO (3.0 at least) static variable encoding.  */
+         break;
+       default:
+         warn_stab (string, _("unknown C++ encoded name"));
+         break;
+       }
+    }
+
+  if (name == NULL)
+    {
+      if (p == string || (string[0] == ' ' && p == string + 1))
+       name = NULL;
+      else
+       name = savestring (string, p - string);
+    }
+
+  ++p;
+  if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+    type = 'l';
+  else
+    type = *p++;
+
+  switch (type)
+    {
+    case 'c':
+      /* c is a special case, not followed by a type-number.
+        SYMBOL:c=iVALUE for an integer constant symbol.
+        SYMBOL:c=rVALUE for a floating constant symbol.
+        SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+        e.g. "b:c=e6,0" for "const b = blob1"
+        (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;").  */
+      if (*p != '=')
+       {
+         bad_stab (string);
+         return false;
+       }
+      ++p;
+      switch (*p++)
+       {
+       case 'r':
+         /* Floating point constant.  */
+         if (! debug_record_float_const (dhandle, name, atof (p)))
+           return false;
+         break;
+       case 'i':
+         /* Integer constant.  */
+         /* Defining integer constants this way is kind of silly,
+            since 'e' constants allows the compiler to give not only
+            the value, but the type as well.  C has at least int,
+            long, unsigned int, and long long as constant types;
+            other languages probably should have at least unsigned as
+            well as signed constants.  */
+         if (! debug_record_int_const (dhandle, name, atoi (p)))
+           return false;
+         break;
+       case 'e':
+         /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
+            can be represented as integral.
+            e.g. "b:c=e6,0" for "const b = blob1"
+            (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;").  */
+         dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+                                  &p, (debug_type **) NULL);
+         if (dtype == DEBUG_TYPE_NULL)
+           return false;
+         if (*p != ',')
+           {
+             bad_stab (string);
+             return false;
+           }
+         if (! debug_record_typed_const (dhandle, name, dtype, atoi (p)))
+           return false;
+         break;
+       default:
+         bad_stab (string);
+         return false;
+       }
+
+      break;
+
+    case 'C':
+      /* The name of a caught exception.  */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+                              &p, (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! debug_record_label (dhandle, name, dtype, value))
+       return false;
+      break;
+
+    case 'f':
+    case 'F':
+      /* A function definition.  */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
+       return false;
+
+      /* Sun acc puts declared types of arguments here.  We don't care
+        about their actual types (FIXME -- we should remember the whole
+        function prototype), but the list may define some new types
+        that we have to remember, so we must scan it now.  */
+      while (*p == ';')
+       {
+         ++p;
+         if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL)
+             == DEBUG_TYPE_NULL)
+           return false;
+       }
+
+      break;
+
+    case 'G':
+      {
+       char leading;
+       long c;
+       asymbol **ps;
+
+       /* A global symbol.  The value must be extracted from the
+          symbol table.  */
+       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                                (debug_type **) NULL);
+       if (dtype == DEBUG_TYPE_NULL)
+         return false;
+       leading = bfd_get_symbol_leading_char (info->abfd);
+       for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
+         {
+           const char *n;
+
+           n = bfd_asymbol_name (*ps);
+           if (leading != '\0' && *n == leading)
+             ++n;
+           if (*n == *name && strcmp (n, name) == 0)
+             break;
+         }
+       if (c > 0)
+         value = bfd_asymbol_value (*ps);
+       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
+                                   value))
+         return false;
+      }
+      break;
+
+      /* This case is faked by a conditional above, when there is no
+        code letter in the dbx data.  Dbx data never actually
+        contains 'l'.  */
+    case 'l':
+    case 's':
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
+                                 value))
+       return false;
+      break;
+
+    case 'p':
+      /* A function parameter.  */
+      if (*p != 'F')
+       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                                (debug_type **) NULL);
+      else
+       {
+       /* pF is a two-letter code that means a function parameter in
+          Fortran.  The type-number specifies the type of the return
+          value.  Translate it into a pointer-to-function type.  */
+         ++p;
+         dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                                  (debug_type **) NULL);
+         if (dtype != DEBUG_TYPE_NULL)
+           {
+             debug_type ftype;
+
+             ftype = debug_make_function_type (dhandle, dtype,
+                                               (debug_type *) NULL, false);
+             dtype = debug_make_pointer_type (dhandle, ftype);
+           }
+       }
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
+                                   value))
+       return false;
+
+      /* FIXME: At this point gdb considers rearranging the parameter
+        address on a big endian machine if it is smaller than an int.
+        We have no way to do that, since we don't really know much
+        about the target.  */
+
+      break;
+
+    case 'P':
+      if (stabtype == N_FUN)
+       {
+         /* Prototype of a function referenced by this file.  */
+         while (*p == ';')
+           {
+             ++p;
+             if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                                  (debug_type **) NULL)
+                 == DEBUG_TYPE_NULL)
+               return false;
+           }
+         break;
+       }
+      /* Fall through.  */
+    case 'R':
+      /* Parameter which is in a register.  */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
+                                   value))
+       return false;
+      break;
+
+    case 'r':
+      /* Register variable (either global or local).  */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
+                                 value))
+       return false;
+
+      /* FIXME: At this point gdb checks to combine pairs of 'p' and
+        'r' stabs into a single 'P' stab.  */
+
+      break;
+
+    case 'S':
+      /* Static symbol at top level of file */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
+                                 value))
+       return false;
+      break;
+
+    case 't':
+      /* A typedef.  */
+      dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (name == NULL)
+       {
+         /* A nameless type.  Nothing to do.  */
+         return true;
+       }
+
+      dtype = debug_name_type (dhandle, name, dtype);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+
+      if (slot != NULL)
+       *slot = dtype;
+
+      break;
+
+    case 'T':
+      /* Struct, union, or enum tag.  For GNU C++, this can be be followed
+        by 't' which means we are typedef'ing it as well.  */
+      if (*p != 't')
+       {
+         synonym = false;
+         /* FIXME: gdb sets synonym to true if the current language
+             is C++.  */
+       }
+      else
+       {
+         synonym = true;
+         ++p;
+       }
+
+      dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (name == NULL)
+       return true;
+
+      /* INFO->SELF_CROSSREF is set by parse_stab_type if this type is
+         a cross reference to itself.  These are generated by some
+         versions of g++.  */
+      self_crossref = info->self_crossref;
+
+      dtype = debug_tag_type (dhandle, name, dtype);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (slot != NULL)
+       *slot = dtype;
+
+      /* See if we have a cross reference to this tag which we can now
+         fill in.  Avoid filling in a cross reference to ourselves,
+         because that would lead to circular debugging information.  */
+      if (! self_crossref)
+       {
+         register struct stab_tag **pst;
+
+         for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
+           {
+             if ((*pst)->name[0] == name[0]
+                 && strcmp ((*pst)->name, name) == 0)
+               {
+                 (*pst)->slot = dtype;
+                 *pst = (*pst)->next;
+                 break;
+               }
+           }
+       }
+
+      if (synonym)
+       {
+         dtype = debug_name_type (dhandle, name, dtype);
+         if (dtype == DEBUG_TYPE_NULL)
+           return false;
+
+         if (slot != NULL)
+           *slot = dtype;
+       }
+
+      break;
+
+    case 'V':
+      /* Static symbol of local scope */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      /* FIXME: gdb checks os9k_stabs here.  */
+      if (! stab_record_variable (dhandle, info, name, dtype,
+                                 DEBUG_LOCAL_STATIC, value))
+       return false;
+      break;
+
+    case 'v':
+      /* Reference parameter.  */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
+                                   value))
+       return false;
+      break;
+
+    case 'a':
+      /* Reference parameter which is in a register.  */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
+                                   value))
+       return false;
+      break;
+
+    case 'X':
+      /* This is used by Sun FORTRAN for "function result value".
+        Sun claims ("dbx and dbxtool interfaces", 2nd ed)
+        that Pascal uses it too, but when I tried it Pascal used
+        "x:3" (local symbol) instead.  */
+      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                              (debug_type **) NULL);
+      if (dtype == DEBUG_TYPE_NULL)
+       return false;
+      if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
+                                 value))
+       return false;
+      break;
+
+    default:
+      bad_stab (string);
+      return false;
+    }
+
+  /* FIXME: gdb converts structure values to structure pointers in a
+     couple of cases, depending upon the target.  */
+
+  return true;
+}
+
+/* Parse a stabs type.  The typename argument is non-NULL if this is a
+   typedef or a tag definition.  The pp argument points to the stab
+   string, and is updated.  The slotp argument points to a place to
+   store the slot used if the type is being defined.  */
+
+static debug_type
+parse_stab_type (dhandle, info, typename, pp, slotp)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char *typename;
+     const char **pp;
+     debug_type **slotp;
+{
+  const char *orig;
+  int typenums[2];
+  int size;
+  boolean stringp;
+  int descriptor;
+  debug_type dtype;
+
+  if (slotp != NULL)
+    *slotp = NULL;
+
+  orig = *pp;
+
+  size = -1;
+  stringp = false;
+
+  info->self_crossref = false;
+
+  /* Read type number if present.  The type number may be omitted.
+     for instance in a two-dimensional array declared with type
+     "ar1;1;10;ar1;1;10;4".  */
+  if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-')
+    {
+      /* 'typenums=' not present, type is anonymous.  Read and return
+        the definition, but don't put it in the type vector.  */
+      typenums[0] = typenums[1] = -1;
+    }
+  else
+    {
+      if (! parse_stab_type_number (pp, typenums))
+       return DEBUG_TYPE_NULL;
+
+      if (**pp != '=')
+       {
+         /* Type is not being defined here.  Either it already
+            exists, or this is a forward reference to it.  */
+         return stab_find_type (dhandle, info, typenums);
+       }
+
+      /* Only set the slot if the type is being defined.  This means
+         that the mapping from type numbers to types will only record
+         the name of the typedef which defines a type.  If we don't do
+         this, then something like
+            typedef int foo;
+            int i;
+        will record that i is of type foo.  Unfortunately, stabs
+        information is ambiguous about variable types.  For this code,
+            typedef int foo;
+            int i;
+            foo j;
+        the stabs information records both i and j as having the same
+        type.  This could be fixed by patching the compiler.  */
+      if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0)
+       *slotp = stab_find_slot (info, typenums);
+
+      /* Type is being defined here.  */
+      /* Skip the '='.  */
+      ++*pp;
+
+      while (**pp == '@')
+       {
+         const char *p = *pp + 1;
+         const char *attr;
+
+         if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+           {
+             /* Member type.  */
+             break;
+           }
+
+         /* Type attributes.  */
+         attr = p;
+
+         for (; *p != ';'; ++p)
+           {
+             if (*p == '\0')
+               {
+                 bad_stab (orig);
+                 return DEBUG_TYPE_NULL;
+               }
+           }
+         *pp = p + 1;
+
+         switch (*attr)
+           {
+           case 's':
+             size = atoi (attr + 1);
+             if (size <= 0)
+               size = -1;
+             break;
+
+           case 'S':
+             stringp = true;
+             break;
+
+           default:
+             /* Ignore unrecognized type attributes, so future
+                compilers can invent new ones.  */
+             break;
+           }
+       }
+    }
+
+  descriptor = **pp;
+  ++*pp;
+
+  switch (descriptor)
+    {
+    case 'x':
+      {
+       enum debug_type_kind code;
+       const char *q1, *q2, *p;
+
+       /* A cross reference to another type.  */
+
+       switch (**pp)
+         {
+         case 's':
+           code = DEBUG_KIND_STRUCT;
+           break;
+         case 'u':
+           code = DEBUG_KIND_UNION;
+           break;
+         case 'e':
+           code = DEBUG_KIND_ENUM;
+           break;
+         default:
+           /* Complain and keep going, so compilers can invent new
+              cross-reference types.  */
+           warn_stab (orig, _("unrecognized cross reference type"));
+           code = DEBUG_KIND_STRUCT;
+           break;
+         }
+       ++*pp;
+
+       q1 = strchr (*pp, '<');
+       p = strchr (*pp, ':');
+       if (p == NULL)
+         {
+           bad_stab (orig);
+           return DEBUG_TYPE_NULL;
+         }
+       while (q1 != NULL && p > q1 && p[1] == ':')
+         {
+           q2 = strchr (q1, '>');
+           if (q2 == NULL || q2 < p)
+             break;
+           p += 2;
+           p = strchr (p, ':');
+           if (p == NULL)
+             {
+               bad_stab (orig);
+               return DEBUG_TYPE_NULL;
+             }
+         }
+
+       /* Some versions of g++ can emit stabs like
+              fleep:T20=xsfleep:
+          which define structures in terms of themselves.  We need to
+          tell the caller to avoid building a circular structure.  */
+       if (typename != NULL
+           && strncmp (typename, *pp, p - *pp) == 0
+           && typename[p - *pp] == '\0')
+         info->self_crossref = true;
+
+       dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
+
+       *pp = p + 1;
+      }
+      break;
+
+    case '-':
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case '(':
+      {
+       const char *hold;
+       int xtypenums[2];
+
+       /* This type is defined as another type.  */
+
+       (*pp)--;
+       hold = *pp;
+
+       /* Peek ahead at the number to detect void.  */
+       if (! parse_stab_type_number (pp, xtypenums))
+         return DEBUG_TYPE_NULL;
+
+       if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
+         {
+           /* This type is being defined as itself, which means that
+               it is void.  */
+           dtype = debug_make_void_type (dhandle);
+         }
+       else
+         {
+           *pp = hold;
+
+           /* Go back to the number and have parse_stab_type get it.
+              This means that we can deal with something like
+              t(1,2)=(3,4)=... which the Lucid compiler uses.  */
+           dtype = parse_stab_type (dhandle, info, (const char *) NULL,
+                                    pp, (debug_type **) NULL);
+           if (dtype == DEBUG_TYPE_NULL)
+             return DEBUG_TYPE_NULL;
+         }
+
+       if (typenums[0] != -1)
+         {
+           if (! stab_record_type (dhandle, info, typenums, dtype))
+             return DEBUG_TYPE_NULL;
+         }
+
+       break;
+      }
+
+    case '*':
+      dtype = debug_make_pointer_type (dhandle,
+                                      parse_stab_type (dhandle, info,
+                                                       (const char *) NULL,
+                                                       pp,
+                                                       (debug_type **) NULL));
+      break;
+
+    case '&':
+      /* Reference to another type.  */
+      dtype = (debug_make_reference_type
+              (dhandle,
+               parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                (debug_type **) NULL)));
+      break;
+
+    case 'f':
+      /* Function returning another type.  */
+      /* FIXME: gdb checks os9k_stabs here.  */
+      dtype = (debug_make_function_type
+              (dhandle,
+               parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                (debug_type **) NULL),
+               (debug_type *) NULL, false));
+      break;
+
+    case 'k':
+      /* Const qualifier on some type (Sun).  */
+      /* FIXME: gdb accepts 'c' here if os9k_stabs.  */
+      dtype = debug_make_const_type (dhandle,
+                                    parse_stab_type (dhandle, info,
+                                                     (const char *) NULL,
+                                                     pp,
+                                                     (debug_type **) NULL));
+      break;
+
+    case 'B':
+      /* Volatile qual on some type (Sun).  */
+      /* FIXME: gdb accepts 'i' here if os9k_stabs.  */
+      dtype = (debug_make_volatile_type
+              (dhandle,
+               parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                (debug_type **) NULL)));
+      break;
+
+    case '@':
+      /* Offset (class & variable) type.  This is used for a pointer
+         relative to an object.  */
+      {
+       debug_type domain;
+       debug_type memtype;
+
+       /* Member type.  */
+
+       domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                 (debug_type **) NULL);
+       if (domain == DEBUG_TYPE_NULL)
+         return DEBUG_TYPE_NULL;
+
+       if (**pp != ',')
+         {
+           bad_stab (orig);
+           return DEBUG_TYPE_NULL;
+         }
+       ++*pp;
+
+       memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                  (debug_type **) NULL);
+       if (memtype == DEBUG_TYPE_NULL)
+         return DEBUG_TYPE_NULL;
+
+       dtype = debug_make_offset_type (dhandle, domain, memtype);
+      }
+      break;
+
+    case '#':
+      /* Method (class & fn) type.  */
+      if (**pp == '#')
+       {
+         debug_type return_type;
+
+         ++*pp;
+         return_type = parse_stab_type (dhandle, info, (const char *) NULL,
+                                        pp, (debug_type **) NULL);
+         if (return_type == DEBUG_TYPE_NULL)
+           return DEBUG_TYPE_NULL;
+         if (**pp != ';')
+           {
+             bad_stab (orig);
+             return DEBUG_TYPE_NULL;
+           }
+         ++*pp;
+         dtype = debug_make_method_type (dhandle, return_type,
+                                         DEBUG_TYPE_NULL,
+                                         (debug_type *) NULL, false);
+       }
+      else
+       {
+         debug_type domain;
+         debug_type return_type;
+         debug_type *args;
+         unsigned int n;
+         unsigned int alloc;
+         boolean varargs;
+
+         domain = parse_stab_type (dhandle, info, (const char *) NULL,
+                                   pp, (debug_type **) NULL);
+         if (domain == DEBUG_TYPE_NULL)
+           return DEBUG_TYPE_NULL;
+
+         if (**pp != ',')
+           {
+             bad_stab (orig);
+             return DEBUG_TYPE_NULL;
+           }
+         ++*pp;
+
+         return_type = parse_stab_type (dhandle, info, (const char *) NULL,
+                                        pp, (debug_type **) NULL);
+         if (return_type == DEBUG_TYPE_NULL)
+           return DEBUG_TYPE_NULL;
+
+         alloc = 10;
+         args = (debug_type *) xmalloc (alloc * sizeof *args);
+         n = 0;
+         while (**pp != ';')
+           {
+             if (**pp != ',')
+               {
+                 bad_stab (orig);
+                 return DEBUG_TYPE_NULL;
+               }
+             ++*pp;
+
+             if (n + 1 >= alloc)
+               {
+                 alloc += 10;
+                 args = ((debug_type *)
+                         xrealloc ((PTR) args, alloc * sizeof *args));
+               }
+
+             args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
+                                        pp, (debug_type **) NULL);
+             if (args[n] == DEBUG_TYPE_NULL)
+               return DEBUG_TYPE_NULL;
+             ++n;
+           }
+         ++*pp;
+
+         /* If the last type is not void, then this function takes a
+            variable number of arguments.  Otherwise, we must strip
+            the void type.  */
+         if (n == 0
+             || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID)
+           varargs = true;
+         else
+           {
+             --n;
+             varargs = false;
+           }
+
+         args[n] = DEBUG_TYPE_NULL;
+
+         dtype = debug_make_method_type (dhandle, return_type, domain, args,
+                                         varargs);
+       }
+      break;
+
+    case 'r':
+      /* Range type.  */
+      dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums);
+      break;
+
+    case 'b':
+      /* FIXME: gdb checks os9k_stabs here.  */
+      /* Sun ACC builtin int type.  */
+      dtype = parse_stab_sun_builtin_type (dhandle, pp);
+      break;
+
+    case 'R':
+      /* Sun ACC builtin float type.  */
+      dtype = parse_stab_sun_floating_type (dhandle, pp);
+      break;
+
+    case 'e':
+      /* Enumeration type.  */
+      dtype = parse_stab_enum_type (dhandle, pp);
+      break;
+
+    case 's':
+    case 'u':
+      /* Struct or union type.  */
+      dtype = parse_stab_struct_type (dhandle, info, typename, pp,
+                                     descriptor == 's', typenums);
+      break;
+
+    case 'a':
+      /* Array type.  */
+      if (**pp != 'r')
+       {
+         bad_stab (orig);
+         return DEBUG_TYPE_NULL;
+       }
+      ++*pp;
+
+      dtype = parse_stab_array_type (dhandle, info, pp, stringp);
+      break;
+
+    case 'S':
+      dtype = debug_make_set_type (dhandle,
+                                  parse_stab_type (dhandle, info,
+                                                   (const char *) NULL,
+                                                   pp,
+                                                   (debug_type **) NULL),
+                                  stringp);
+      break;
+
+    default:
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+
+  if (dtype == DEBUG_TYPE_NULL)
+    return DEBUG_TYPE_NULL;
+
+  if (typenums[0] != -1)
+    {
+      if (! stab_record_type (dhandle, info, typenums, dtype))
+       return DEBUG_TYPE_NULL;
+    }
+
+  if (size != -1)
+    {
+      if (! debug_record_type_size (dhandle, dtype, (unsigned int) size))
+       return false;
+    }
+
+  return dtype;
+}
+
+/* Read a number by which a type is referred to in dbx data, or
+   perhaps read a pair (FILENUM, TYPENUM) in parentheses.  Just a
+   single number N is equivalent to (0,N).  Return the two numbers by
+   storing them in the vector TYPENUMS.  */
+
+static boolean
+parse_stab_type_number (pp, typenums)
+     const char **pp;
+     int *typenums;
+{
+  const char *orig;
+
+  orig = *pp;
+
+  if (**pp != '(')
+    {
+      typenums[0] = 0;
+      typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+    }
+  else
+    {
+      ++*pp;
+      typenums[0] = (int) parse_number (pp, (boolean *) NULL);
+      if (**pp != ',')
+       {
+         bad_stab (orig);
+         return false;
+       }
+      ++*pp;
+      typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+      if (**pp != ')')
+       {
+         bad_stab (orig);
+         return false;
+       }
+      ++*pp;
+    }
+
+  return true;
+}
+
+/* Parse a range type.  */
+
+static debug_type
+parse_stab_range_type (dhandle, info, typename, pp, typenums)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char *typename;
+     const char **pp;
+     const int *typenums;
+{
+  const char *orig;
+  int rangenums[2];
+  boolean self_subrange;
+  debug_type index_type;
+  const char *s2, *s3;
+  bfd_signed_vma n2, n3;
+  boolean ov2, ov3;
+
+  orig = *pp;
+
+  index_type = DEBUG_TYPE_NULL;
+
+  /* First comes a type we are a subrange of.
+     In C it is usually 0, 1 or the type being defined.  */
+  if (! parse_stab_type_number (pp, rangenums))
+    return DEBUG_TYPE_NULL;
+
+  self_subrange = (rangenums[0] == typenums[0]
+                  && rangenums[1] == typenums[1]);
+
+  if (**pp == '=')
+    {
+      *pp = orig;
+      index_type = parse_stab_type (dhandle, info, (const char *) NULL,
+                                   pp, (debug_type **) NULL);
+      if (index_type == DEBUG_TYPE_NULL)
+       return DEBUG_TYPE_NULL;
+    }
+
+  if (**pp == ';')
+    ++*pp;
+
+  /* The remaining two operands are usually lower and upper bounds of
+     the range.  But in some special cases they mean something else.  */
+  s2 = *pp;
+  n2 = parse_number (pp, &ov2);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+  ++*pp;
+
+  s3 = *pp;
+  n3 = parse_number (pp, &ov3);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+  ++*pp;
+
+  if (ov2 || ov3)
+    {
+      /* gcc will emit range stabs for long long types.  Handle this
+         as a special case.  FIXME: This needs to be more general.  */
+#define LLLOW  "01000000000000000000000;"
+#define LLHIGH "0777777777777777777777;"
+#define ULLHIGH "01777777777777777777777;"
+      if (index_type == DEBUG_TYPE_NULL)
+       {
+         if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0
+             && strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0)
+           return debug_make_int_type (dhandle, 8, false);
+         if (! ov2
+             && n2 == 0
+             && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0)
+           return debug_make_int_type (dhandle, 8, true);
+       }
+
+      warn_stab (orig, _("numeric overflow"));
+    }
+
+  if (index_type == DEBUG_TYPE_NULL)
+    {
+      /* A type defined as a subrange of itself, with both bounds 0,
+         is void.  */
+      if (self_subrange && n2 == 0 && n3 == 0)
+       return debug_make_void_type (dhandle);
+
+      /* A type defined as a subrange of itself, with n2 positive and
+        n3 zero, is a complex type, and n2 is the number of bytes.  */
+      if (self_subrange && n3 == 0 && n2 > 0)
+       return debug_make_complex_type (dhandle, n2);
+
+      /* If n3 is zero and n2 is positive, this is a floating point
+         type, and n2 is the number of bytes.  */
+      if (n3 == 0 && n2 > 0)
+       return debug_make_float_type (dhandle, n2);
+
+      /* If the upper bound is -1, this is an unsigned int.  */
+      if (n2 == 0 && n3 == -1)
+       {
+         /* When gcc is used with -gstabs, but not -gstabs+, it will emit
+                long long int:t6=r1;0;-1;
+                long long unsigned int:t7=r1;0;-1;
+            We hack here to handle this reasonably.  */
+         if (typename != NULL)
+           {
+             if (strcmp (typename, "long long int") == 0)
+               return debug_make_int_type (dhandle, 8, false);
+             else if (strcmp (typename, "long long unsigned int") == 0)
+               return debug_make_int_type (dhandle, 8, true);
+           }
+         /* FIXME: The size here really depends upon the target.  */
+         return debug_make_int_type (dhandle, 4, true);
+       }
+
+      /* A range of 0 to 127 is char.  */
+      if (self_subrange && n2 == 0 && n3 == 127)
+       return debug_make_int_type (dhandle, 1, false);
+
+      /* FIXME: gdb checks for the language CHILL here.  */
+
+      if (n2 == 0)
+       {
+         if (n3 < 0)
+           return debug_make_int_type (dhandle, - n3, true);
+         else if (n3 == 0xff)
+           return debug_make_int_type (dhandle, 1, true);
+         else if (n3 == 0xffff)
+           return debug_make_int_type (dhandle, 2, true);
+         else if (n3 == 0xffffffff)
+           return debug_make_int_type (dhandle, 4, true);
+#ifdef BFD64
+         else if (n3 == ((((bfd_vma) 0xffffffff) << 32) | 0xffffffff))
+           return debug_make_int_type (dhandle, 8, true);
+#endif
+       }
+      else if (n3 == 0
+              && n2 < 0
+              && (self_subrange || n2 == -8))
+       return debug_make_int_type (dhandle, - n2, true);
+      else if (n2 == - n3 - 1 || n2 == n3 + 1)
+       {
+         if (n3 == 0x7f)
+           return debug_make_int_type (dhandle, 1, false);
+         else if (n3 == 0x7fff)
+           return debug_make_int_type (dhandle, 2, false);
+         else if (n3 == 0x7fffffff)
+           return debug_make_int_type (dhandle, 4, false);
+#ifdef BFD64
+         else if (n3 == ((((bfd_vma) 0x7fffffff) << 32) | 0xffffffff))
+           return debug_make_int_type (dhandle, 8, false);
+#endif
+       }
+    }
+
+  /* At this point I don't have the faintest idea how to deal with a
+     self_subrange type; I'm going to assume that this is used as an
+     idiom, and that all of them are special cases.  So . . .  */
+  if (self_subrange)
+    {
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+
+  index_type = stab_find_type (dhandle, info, rangenums);
+  if (index_type == DEBUG_TYPE_NULL)
+    {
+      /* Does this actually ever happen?  Is that why we are worrying
+         about dealing with it rather than just calling error_type?  */
+      warn_stab (orig, _("missing index type"));
+      index_type = debug_make_int_type (dhandle, 4, false);
+    }
+
+  return debug_make_range_type (dhandle, index_type, n2, n3);
+}
+
+/* Sun's ACC uses a somewhat saner method for specifying the builtin
+   typedefs in every file (for int, long, etc):
+
+       type = b <signed> <width>; <offset>; <nbits>
+       signed = u or s.  Possible c in addition to u or s (for char?).
+       offset = offset from high order bit to start bit of type.
+       width is # bytes in object of this type, nbits is # bits in type.
+
+   The width/offset stuff appears to be for small objects stored in
+   larger ones (e.g. `shorts' in `int' registers).  We ignore it for now,
+   FIXME.  */
+
+static debug_type
+parse_stab_sun_builtin_type (dhandle, pp)
+     PTR dhandle;
+     const char **pp;
+{
+  const char *orig;
+  boolean unsignedp;
+  bfd_vma bits;
+
+  orig = *pp;
+
+  switch (**pp)
+    {
+    case 's':
+      unsignedp = false;
+      break;
+    case 'u':
+      unsignedp = true;
+      break;
+    default:
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+  ++*pp;
+
+  /* For some odd reason, all forms of char put a c here.  This is strange
+     because no other type has this honor.  We can safely ignore this because
+     we actually determine 'char'acterness by the number of bits specified in
+     the descriptor.  */
+  if (**pp == 'c')
+    ++*pp;
+
+  /* The first number appears to be the number of bytes occupied
+     by this type, except that unsigned short is 4 instead of 2.
+     Since this information is redundant with the third number,
+     we will ignore it.  */
+  (void) parse_number (pp, (boolean *) NULL);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+  ++*pp;
+
+  /* The second number is always 0, so ignore it too. */
+  (void) parse_number (pp, (boolean *) NULL);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+  ++*pp;
+
+  /* The third number is the number of bits for this type. */
+  bits = parse_number (pp, (boolean *) NULL);
+
+  /* The type *should* end with a semicolon.  If it are embedded
+     in a larger type the semicolon may be the only way to know where
+     the type ends.  If this type is at the end of the stabstring we
+     can deal with the omitted semicolon (but we don't have to like
+     it).  Don't bother to complain(), Sun's compiler omits the semicolon
+     for "void".  */
+  if (**pp == ';')
+    ++*pp;
+
+  if (bits == 0)
+    return debug_make_void_type (dhandle);
+
+  return debug_make_int_type (dhandle, bits / 8, unsignedp);
+}
+
+/* Parse a builtin floating type generated by the Sun compiler.  */
+
+static debug_type
+parse_stab_sun_floating_type (dhandle, pp)
+     PTR dhandle;
+     const char **pp;
+{
+  const char *orig;
+  bfd_vma details;
+  bfd_vma bytes;
+
+  orig = *pp;
+
+  /* The first number has more details about the type, for example
+     FN_COMPLEX.  */
+  details = parse_number (pp, (boolean *) NULL);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+
+  /* The second number is the number of bytes occupied by this type */
+  bytes = parse_number (pp, (boolean *) NULL);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+
+  if (details == NF_COMPLEX
+      || details == NF_COMPLEX16
+      || details == NF_COMPLEX32)
+    return debug_make_complex_type (dhandle, bytes);
+
+  return debug_make_float_type (dhandle, bytes);      
+}
+
+/* Handle an enum type.  */
+
+static debug_type
+parse_stab_enum_type (dhandle, pp)
+     PTR dhandle;
+     const char **pp;
+{
+  const char *orig;
+  const char **names;
+  bfd_signed_vma *values;
+  unsigned int n;
+  unsigned int alloc;
+
+  orig = *pp;
+
+  /* FIXME: gdb checks os9k_stabs here.  */
+
+  /* The aix4 compiler emits an extra field before the enum members;
+     my guess is it's a type of some sort.  Just ignore it.  */
+  if (**pp == '-')
+    {
+      while (**pp != ':')
+       ++*pp;
+      ++*pp;
+    }
+
+  /* Read the value-names and their values.
+     The input syntax is NAME:VALUE,NAME:VALUE, and so on.
+     A semicolon or comma instead of a NAME means the end.  */
+  alloc = 10;
+  names = (const char **) xmalloc (alloc * sizeof *names);
+  values = (bfd_signed_vma *) xmalloc (alloc * sizeof *values);
+  n = 0;
+  while (**pp != '\0' && **pp != ';' && **pp != ',')
+    {
+      const char *p;
+      char *name;
+      bfd_signed_vma val;
+
+      p = *pp;
+      while (*p != ':')
+       ++p;
+
+      name = savestring (*pp, p - *pp);
+
+      *pp = p + 1;
+      val = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+      if (**pp != ',')
+       {
+         bad_stab (orig);
+         return DEBUG_TYPE_NULL;
+       }
+      ++*pp;
+
+      if (n + 1 >= alloc)
+       {
+         alloc += 10;
+         names = ((const char **)
+                  xrealloc ((PTR) names, alloc * sizeof *names));
+         values = ((bfd_signed_vma *)
+                   xrealloc ((PTR) values, alloc * sizeof *values));
+       }
+
+      names[n] = name;
+      values[n] = val;
+      ++n;
+    }
+
+  names[n] = NULL;
+  values[n] = 0;
+
+  if (**pp == ';')
+    ++*pp;
+
+  return debug_make_enum_type (dhandle, names, values);
+}
+
+/* Read the description of a structure (or union type) and return an object
+   describing the type.
+
+   PP points to a character pointer that points to the next unconsumed token
+   in the the stabs string.  For example, given stabs "A:T4=s4a:1,0,32;;",
+   *PP will point to "4a:1,0,32;;".  */
+
+static debug_type
+parse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char *tagname;
+     const char **pp;
+     boolean structp;
+     const int *typenums;
+{
+  const char *orig;
+  bfd_vma size;
+  debug_baseclass *baseclasses;
+  debug_field *fields;
+  boolean statics;
+  debug_method *methods;
+  debug_type vptrbase;
+  boolean ownvptr;
+
+  orig = *pp;
+
+  /* Get the size.  */
+  size = parse_number (pp, (boolean *) NULL);
+
+  /* Get the other information.  */
+  if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
+      || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
+      || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
+      || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
+                                  &ownvptr))
+    return DEBUG_TYPE_NULL;
+
+  if (! statics
+      && baseclasses == NULL
+      && methods == NULL
+      && vptrbase == DEBUG_TYPE_NULL
+      && ! ownvptr)
+    return debug_make_struct_type (dhandle, structp, size, fields);
+
+  return debug_make_object_type (dhandle, structp, size, fields, baseclasses,
+                                methods, vptrbase, ownvptr);
+}
+
+/* The stabs for C++ derived classes contain baseclass information which
+   is marked by a '!' character after the total size.  This function is
+   called when we encounter the baseclass marker, and slurps up all the
+   baseclass information.
+
+   Immediately following the '!' marker is the number of base classes that
+   the class is derived from, followed by information for each base class.
+   For each base class, there are two visibility specifiers, a bit offset
+   to the base class information within the derived class, a reference to
+   the type for the base class, and a terminating semicolon.
+
+   A typical example, with two base classes, would be "!2,020,19;0264,21;".
+                                                      ^^ ^ ^ ^  ^ ^  ^
+       Baseclass information marker __________________|| | | |  | |  |
+       Number of baseclasses __________________________| | | |  | |  |
+       Visibility specifiers (2) ________________________| | |  | |  |
+       Offset in bits from start of class _________________| |  | |  |
+       Type number for base class ___________________________|  | |  |
+       Visibility specifiers (2) _______________________________| |  |
+       Offset in bits from start of class ________________________|  |
+       Type number of base class ____________________________________|
+
+  Return true for success, false for failure.  */
+
+static boolean
+parse_stab_baseclasses (dhandle, info, pp, retp)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char **pp;
+     debug_baseclass **retp;
+{
+  const char *orig;
+  unsigned int c, i;
+  debug_baseclass *classes;
+
+  *retp = NULL;
+
+  orig = *pp;
+
+  if (**pp != '!')
+    {
+      /* No base classes.  */
+      return true;
+    }
+  ++*pp;
+
+  c = (unsigned int) parse_number (pp, (boolean *) NULL);
+
+  if (**pp != ',')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp));
+
+  for (i = 0; i < c; i++)
+    {
+      boolean virtual;
+      enum debug_visibility visibility;
+      bfd_vma bitpos;
+      debug_type type;
+
+      switch (**pp)
+       {
+       case '0':
+         virtual = false;
+         break;
+       case '1':
+         virtual = true;
+         break;
+       default:
+         warn_stab (orig, _("unknown virtual character for baseclass"));
+         virtual = false;
+         break;
+       }
+      ++*pp;
+
+      switch (**pp)
+       {
+       case '0':
+         visibility = DEBUG_VISIBILITY_PRIVATE;
+         break;
+       case '1':
+         visibility = DEBUG_VISIBILITY_PROTECTED;
+         break;
+       case '2':
+         visibility = DEBUG_VISIBILITY_PUBLIC;
+         break;
+       default:
+         warn_stab (orig, _("unknown visibility character for baseclass"));
+         visibility = DEBUG_VISIBILITY_PUBLIC;
+         break;
+       }
+      ++*pp;
+
+      /* The remaining value is the bit offset of the portion of the
+        object corresponding to this baseclass.  Always zero in the
+        absence of multiple inheritance.  */
+      bitpos = parse_number (pp, (boolean *) NULL);
+      if (**pp != ',')
+       {
+         bad_stab (orig);
+         return false;
+       }
+      ++*pp;
+
+      type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                             (debug_type **) NULL);
+      if (type == DEBUG_TYPE_NULL)
+       return false;
+
+      classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
+                                        visibility);
+      if (classes[i] == DEBUG_BASECLASS_NULL)
+       return false;
+
+      if (**pp != ';')
+       return false;
+      ++*pp;
+    }
+
+  classes[i] = DEBUG_BASECLASS_NULL;
+
+  *retp = classes;
+
+  return true;
+}
+
+/* Read struct or class data fields.  They have the form:
+
+       NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
+
+   At the end, we see a semicolon instead of a field.
+
+   In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
+   a static field.
+
+   The optional VISIBILITY is one of:
+
+       '/0'    (VISIBILITY_PRIVATE)
+       '/1'    (VISIBILITY_PROTECTED)
+       '/2'    (VISIBILITY_PUBLIC)
+       '/9'    (VISIBILITY_IGNORE)
+
+   or nothing, for C style fields with public visibility.
+
+   Returns 1 for success, 0 for failure.  */
+
+static boolean
+parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char **pp;
+     debug_field **retp;
+     boolean *staticsp;
+{
+  const char *orig;
+  const char *p;
+  debug_field *fields;
+  unsigned int c;
+  unsigned int alloc;
+
+  *retp = NULL;
+  *staticsp = false;
+
+  orig = *pp;
+
+  c = 0;
+  alloc = 10;
+  fields = (debug_field *) xmalloc (alloc * sizeof *fields);
+  while (**pp != ';')
+    {
+      /* FIXME: gdb checks os9k_stabs here.  */
+
+      p = *pp;
+
+      /* Add 1 to c to leave room for NULL pointer at end.  */
+      if (c + 1 >= alloc)
+       {
+         alloc += 10;
+         fields = ((debug_field *)
+                   xrealloc ((PTR) fields, alloc * sizeof *fields));
+       }
+
+      /* If it starts with CPLUS_MARKER it is a special abbreviation,
+        unless the CPLUS_MARKER is followed by an underscore, in
+        which case it is just the name of an anonymous type, which we
+        should handle like any other type name.  We accept either '$'
+        or '.', because a field name can never contain one of these
+        characters except as a CPLUS_MARKER.  */
+
+      if ((*p == '$' || *p == '.') && p[1] != '_')
+       {
+         ++*pp;
+         if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
+           return false;
+         ++c;
+         continue;
+       }
+
+      /* Look for the ':' that separates the field name from the field
+        values.  Data members are delimited by a single ':', while member
+        functions are delimited by a pair of ':'s.  When we hit the member
+        functions (if any), terminate scan loop and return. */
+
+      p = strchr (p, ':');
+      if (p == NULL)
+       {
+         bad_stab (orig);
+         return false;
+       }
+
+      if (p[1] == ':')
+       break;
+
+      if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
+                                        staticsp))
+       return false;
+
+      ++c;
+    }
+
+  fields[c] = DEBUG_FIELD_NULL;
+
+  *retp = fields;
+
+  return true;
+}
+
+/* Special GNU C++ name.  */
+
+static boolean
+parse_stab_cpp_abbrev (dhandle, info, pp, retp)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char **pp;
+     debug_field *retp;
+{
+  const char *orig;
+  int cpp_abbrev;
+  debug_type context;
+  const char *name;
+  const char *typename;
+  debug_type type;
+  bfd_vma bitpos;
+
+  *retp = DEBUG_FIELD_NULL;
+
+  orig = *pp;
+
+  if (**pp != 'v')
+    {
+      bad_stab (*pp);
+      return false;
+    }
+  ++*pp;
+
+  cpp_abbrev = **pp;
+  ++*pp;
+
+  /* At this point, *pp points to something like "22:23=*22...", where
+     the type number before the ':' is the "context" and everything
+     after is a regular type definition.  Lookup the type, find it's
+     name, and construct the field name.  */
+
+  context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                            (debug_type **) NULL);
+  if (context == DEBUG_TYPE_NULL)
+    return false;
+
+  switch (cpp_abbrev)
+    {
+    case 'f':
+      /* $vf -- a virtual function table pointer.  */
+      name = "_vptr$";
+      break;
+    case 'b':
+      /* $vb -- a virtual bsomethingorother */
+      typename = debug_get_type_name (dhandle, context);
+      if (typename == NULL)
+       {
+         warn_stab (orig, _("unnamed $vb type"));
+         typename = "FOO";
+       }
+      name = concat ("_vb$", typename, (const char *) NULL);
+      break;
+    default:
+      warn_stab (orig, _("unrecognized C++ abbreviation"));
+      name = "INVALID_CPLUSPLUS_ABBREV";
+      break;
+    }
+
+  if (**pp != ':')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                         (debug_type **) NULL);
+  if (**pp != ',')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  bitpos = parse_number (pp, (boolean *) NULL);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  *retp = debug_make_field (dhandle, name, type, bitpos, 0,
+                           DEBUG_VISIBILITY_PRIVATE);
+  if (*retp == DEBUG_FIELD_NULL)
+    return false;
+
+  return true;
+}
+
+/* Parse a single field in a struct or union.  */
+
+static boolean
+parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char **pp;
+     const char *p;
+     debug_field *retp;
+     boolean *staticsp;
+{
+  const char *orig;
+  char *name;
+  enum debug_visibility visibility;
+  debug_type type;
+  bfd_vma bitpos;
+  bfd_vma bitsize;
+
+  orig = *pp;
+
+  /* FIXME: gdb checks ARM_DEMANGLING here.  */
+
+  name = savestring (*pp, p - *pp);
+
+  *pp = p + 1;
+
+  if (**pp != '/')
+    visibility = DEBUG_VISIBILITY_PUBLIC;
+  else
+    {
+      ++*pp;
+      switch (**pp)
+       {
+       case '0':
+         visibility = DEBUG_VISIBILITY_PRIVATE;
+         break;
+       case '1':
+         visibility = DEBUG_VISIBILITY_PROTECTED;
+         break;
+       case '2':
+         visibility = DEBUG_VISIBILITY_PUBLIC;
+         break;
+       default:
+         warn_stab (orig, _("unknown visibility character for field"));
+         visibility = DEBUG_VISIBILITY_PUBLIC;
+         break;
+       }
+      ++*pp;
+    }
+
+  type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                         (debug_type **) NULL);
+  if (type == DEBUG_TYPE_NULL)
+    return false;
+
+  if (**pp == ':')
+    {
+      char *varname;
+
+      /* This is a static class member.  */
+      ++*pp;
+      p = strchr (*pp, ';');
+      if (p == NULL)
+       {
+         bad_stab (orig);
+         return false;
+       }
+
+      varname = savestring (*pp, p - *pp);
+
+      *pp = p + 1;
+
+      *retp = debug_make_static_member (dhandle, name, type, varname,
+                                       visibility);
+      *staticsp = true;
+
+      return true;
+    }
+
+  if (**pp != ',')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  bitpos = parse_number (pp, (boolean *) NULL);
+  if (**pp != ',')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  bitsize = parse_number (pp, (boolean *) NULL);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  if (bitpos == 0 && bitsize == 0)
+    {
+      /* This can happen in two cases: (1) at least for gcc 2.4.5 or
+        so, it is a field which has been optimized out.  The correct
+        stab for this case is to use VISIBILITY_IGNORE, but that is a
+        recent invention.  (2) It is a 0-size array.  For example
+        union { int num; char str[0]; } foo.  Printing "<no value>"
+        for str in "p foo" is OK, since foo.str (and thus foo.str[3])
+        will continue to work, and a 0-size array as a whole doesn't
+        have any contents to print.
+
+        I suspect this probably could also happen with gcc -gstabs
+        (not -gstabs+) for static fields, and perhaps other C++
+        extensions.  Hopefully few people use -gstabs with gdb, since
+        it is intended for dbx compatibility.  */
+      visibility = DEBUG_VISIBILITY_IGNORE;
+    }
+
+  /* FIXME: gdb does some stuff here to mark fields as unpacked.  */
+
+  *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility);
+
+  return true;
+}
+
+/* Read member function stabs info for C++ classes.  The form of each member
+   function data is:
+
+       NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ;
+
+   An example with two member functions is:
+
+       afunc1::20=##15;:i;2A.;afunc2::20:i;2A.;
+
+   For the case of overloaded operators, the format is op$::*.funcs, where
+   $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
+   name (such as `+=') and `.' marks the end of the operator name.  */
+
+static boolean
+parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char *tagname;
+     const char **pp;
+     const int *typenums;
+     debug_method **retp;
+{
+  const char *orig;
+  debug_method *methods;
+  unsigned int c;
+  unsigned int alloc;
+
+  *retp = NULL;
+
+  orig = *pp;
+
+  alloc = 0;
+  methods = NULL;
+  c = 0;
+
+  while (**pp != ';')
+    {
+      const char *p;
+      char *name;
+      debug_method_variant *variants;
+      unsigned int cvars;
+      unsigned int allocvars;
+      debug_type look_ahead_type;
+
+      p = strchr (*pp, ':');
+      if (p == NULL || p[1] != ':')
+       break;
+
+      /* FIXME: Some systems use something other than '$' here.  */
+      if ((*pp)[0] != 'o' || (*pp)[1] != 'p' || (*pp)[2] != '$')
+       {
+         name = savestring (*pp, p - *pp);
+         *pp = p + 2;
+       }
+      else
+       {
+         /* This is a completely wierd case.  In order to stuff in the
+            names that might contain colons (the usual name delimiter),
+            Mike Tiemann defined a different name format which is
+            signalled if the identifier is "op$".  In that case, the
+            format is "op$::XXXX." where XXXX is the name.  This is
+            used for names like "+" or "=".  YUUUUUUUK!  FIXME!  */
+         *pp = p + 2;
+         for (p = *pp; *p != '.' && *p != '\0'; p++)
+           ;
+         if (*p != '.')
+           {
+             bad_stab (orig);
+             return false;
+           }
+         name = savestring (*pp, p - *pp);
+         *pp = p + 1;
+       }
+
+      allocvars = 10;
+      variants = ((debug_method_variant *)
+                 xmalloc (allocvars * sizeof *variants));
+      cvars = 0;
+
+      look_ahead_type = DEBUG_TYPE_NULL;
+
+      do
+       {
+         debug_type type;
+         boolean stub;
+         char *argtypes;
+         enum debug_visibility visibility;
+         boolean constp, volatilep, staticp;
+         bfd_vma voffset;
+         debug_type context;
+         const char *physname;
+         boolean varargs;
+
+         if (look_ahead_type != DEBUG_TYPE_NULL)
+           {
+             /* g++ version 1 kludge */
+             type = look_ahead_type;
+             look_ahead_type = DEBUG_TYPE_NULL;
+           }
+         else
+           {
+             type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                     (debug_type **) NULL);
+             if (type == DEBUG_TYPE_NULL)
+               return false;
+             if (**pp != ':')
+               {
+                 bad_stab (orig);
+                 return false;
+               }
+           }
+
+         ++*pp;
+         p = strchr (*pp, ';');
+         if (p == NULL)
+           {
+             bad_stab (orig);
+             return false;
+           }
+
+         stub = false;
+         if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
+             && debug_get_parameter_types (dhandle, type, &varargs) == NULL)
+           stub = true;
+
+         argtypes = savestring (*pp, p - *pp);
+         *pp = p + 1;
+
+         switch (**pp)
+           {
+           case '0':
+             visibility = DEBUG_VISIBILITY_PRIVATE;
+             break;
+           case '1':
+             visibility = DEBUG_VISIBILITY_PROTECTED;
+             break;
+           default:
+             visibility = DEBUG_VISIBILITY_PUBLIC;
+             break;
+           }
+         ++*pp;
+
+         constp = false;
+         volatilep = false;
+         switch (**pp)
+           {
+           case 'A':
+             /* Normal function.  */
+             ++*pp;
+             break;
+           case 'B':
+             /* const member function.  */
+             constp = true;
+             ++*pp;
+             break;
+           case 'C':
+             /* volatile member function.  */
+             volatilep = true;
+             ++*pp;
+             break;
+           case 'D':
+             /* const volatile member function.  */
+             constp = true;
+             volatilep = true;
+             ++*pp;
+             break;
+           case '*':
+           case '?':
+           case '.':
+             /* File compiled with g++ version 1; no information.  */
+             break;
+           default:
+             warn_stab (orig, _("const/volatile indicator missing"));
+             break;
+           }
+
+         staticp = false;
+         switch (**pp)
+           {
+           case '*':
+             /* virtual member function, followed by index.  The sign
+                bit is supposedly set to distinguish
+                pointers-to-methods from virtual function indicies.  */
+             ++*pp;
+             voffset = parse_number (pp, (boolean *) NULL);
+             if (**pp != ';')
+               {
+                 bad_stab (orig);
+                 return false;
+               }
+             ++*pp;
+             voffset &= 0x7fffffff;
+
+             if (**pp == ';' || *pp == '\0')
+               {
+                 /* Must be g++ version 1.  */
+                 context = DEBUG_TYPE_NULL;
+               }
+             else
+               {
+                 /* Figure out from whence this virtual function
+                    came.  It may belong to virtual function table of
+                    one of its baseclasses.  */
+                   look_ahead_type = parse_stab_type (dhandle, info,
+                                                      (const char *) NULL,
+                                                      pp,
+                                                      (debug_type **) NULL);
+                   if (**pp == ':')
+                     {
+                       /* g++ version 1 overloaded methods.  */
+                       context = DEBUG_TYPE_NULL;
+                     }
+                   else
+                     {
+                       context = look_ahead_type;
+                       look_ahead_type = DEBUG_TYPE_NULL;
+                       if (**pp != ';')
+                         {
+                           bad_stab (orig);
+                           return false;
+                         }
+                       ++*pp;
+                     }
+                 }
+             break;
+
+           case '?':
+             /* static member function.  */
+             ++*pp;
+             staticp = true;
+             voffset = 0;
+             context = DEBUG_TYPE_NULL;
+             if (strncmp (argtypes, name, strlen (name)) != 0)
+               stub = true;
+             break;
+
+           default:
+             warn_stab (orig, "member function type missing");
+             voffset = 0;
+             context = DEBUG_TYPE_NULL;
+             break;
+
+           case '.':
+             ++*pp;
+             voffset = 0;
+             context = DEBUG_TYPE_NULL;
+             break;
+           }
+
+         /* If the type is not a stub, then the argtypes string is
+             the physical name of the function.  Otherwise the
+             argtypes string is the mangled form of the argument
+             types, and the full type and the physical name must be
+             extracted from them.  */
+         if (! stub)
+           physname = argtypes;
+         else
+           {
+             debug_type class_type, return_type;
+
+             class_type = stab_find_type (dhandle, info, typenums);
+             if (class_type == DEBUG_TYPE_NULL)
+               return false;
+             return_type = debug_get_return_type (dhandle, type);
+             if (return_type == DEBUG_TYPE_NULL)
+               {
+                 bad_stab (orig);
+                 return false;
+               }
+             type = parse_stab_argtypes (dhandle, info, class_type, name,
+                                         tagname, return_type, argtypes,
+                                         constp, volatilep, &physname);
+             if (type == DEBUG_TYPE_NULL)
+               return false;
+           }
+
+         if (cvars + 1 >= allocvars)
+           {
+             allocvars += 10;
+             variants = ((debug_method_variant *)
+                         xrealloc ((PTR) variants,
+                                   allocvars * sizeof *variants));
+           }
+
+         if (! staticp)
+           variants[cvars] = debug_make_method_variant (dhandle, physname,
+                                                        type, visibility,
+                                                        constp, volatilep,
+                                                        voffset, context);
+         else
+           variants[cvars] = debug_make_static_method_variant (dhandle,
+                                                               physname,
+                                                               type,
+                                                               visibility,
+                                                               constp,
+                                                               volatilep);
+         if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
+           return false;
+
+         ++cvars;
+       }
+      while (**pp != ';' && **pp != '\0');
+
+      variants[cvars] = DEBUG_METHOD_VARIANT_NULL;
+
+      if (**pp != '\0')
+       ++*pp;
+
+      if (c + 1 >= alloc)
+       {
+         alloc += 10;
+         methods = ((debug_method *)
+                    xrealloc ((PTR) methods, alloc * sizeof *methods));
+       }
+
+      methods[c] = debug_make_method (dhandle, name, variants);
+
+      ++c;
+    }
+
+  if (methods != NULL)
+    methods[c] = DEBUG_METHOD_NULL;
+
+  *retp = methods;
+
+  return true;
+}
+
+/* Parse a string representing argument types for a method.  Stabs
+   tries to save space by packing argument types into a mangled
+   string.  This string should give us enough information to extract
+   both argument types and the physical name of the function, given
+   the tag name.  */
+
+static debug_type
+parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname,
+                    return_type, argtypes, constp, volatilep, pphysname)
+     PTR dhandle;
+     struct stab_handle *info;
+     debug_type class_type;
+     const char *fieldname;
+     const char *tagname;
+     debug_type return_type;
+     const char *argtypes;
+     boolean constp;
+     boolean volatilep;
+     const char **pphysname;
+{
+  boolean is_full_physname_constructor;
+  boolean is_constructor;
+  boolean is_destructor;
+  debug_type *args;
+  boolean varargs;
+
+  /* Constructors are sometimes handled specially.  */
+  is_full_physname_constructor = ((argtypes[0] == '_'
+                                  && argtypes[1] == '_'
+                                  && (isdigit ((unsigned char) argtypes[2])
+                                      || argtypes[2] == 'Q'
+                                      || argtypes[2] == 't'))
+                                 || strncmp (argtypes, "__ct", 4) == 0);
+
+  is_constructor = (is_full_physname_constructor
+                   || (tagname != NULL
+                       && strcmp (fieldname, tagname) == 0));
+  is_destructor = ((argtypes[0] == '_'
+                   && (argtypes[1] == '$' || argtypes[1] == '.')
+                   && argtypes[2] == '_')
+                  || strncmp (argtypes, "__dt", 4) == 0);
+
+  if (is_destructor || is_full_physname_constructor)
+    *pphysname = argtypes;
+  else
+    {
+      unsigned int len;
+      const char *const_prefix;
+      const char *volatile_prefix;
+      char buf[20];
+      unsigned int mangled_name_len;
+      char *physname;
+
+      len = tagname == NULL ? 0 : strlen (tagname);
+      const_prefix = constp ? "C" : "";
+      volatile_prefix = volatilep ? "V" : "";
+
+      if (len == 0)
+       sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+      else if (tagname != NULL && strchr (tagname, '<') != NULL)
+       {
+         /* Template methods are fully mangled.  */
+         sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+         tagname = NULL;
+         len = 0;
+       }
+      else
+       sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+
+      mangled_name_len = ((is_constructor ? 0 : strlen (fieldname))
+                         + strlen (buf)
+                         + len
+                         + strlen (argtypes)
+                         + 1);
+
+      if (fieldname[0] == 'o'
+         && fieldname[1] == 'p'
+         && (fieldname[2] == '$' || fieldname[2] == '.'))
+       {
+         const char *opname;
+
+         opname = cplus_mangle_opname (fieldname + 3, 0);
+         if (opname == NULL)
+           {
+             fprintf (stderr, _("No mangling for \"%s\"\n"), fieldname);
+             return DEBUG_TYPE_NULL;
+           }
+         mangled_name_len += strlen (opname);
+         physname = (char *) xmalloc (mangled_name_len);
+         strncpy (physname, fieldname, 3);
+         strcpy (physname + 3, opname);
+       }
+      else
+       {
+         physname = (char *) xmalloc (mangled_name_len);
+         if (is_constructor)
+           physname[0] = '\0';
+         else
+           strcpy (physname, fieldname);
+       }
+
+      strcat (physname, buf);
+      if (tagname != NULL)
+       strcat (physname, tagname);
+      strcat (physname, argtypes);
+
+      *pphysname = physname;
+    }
+
+  if (*argtypes == '\0' || is_destructor)
+    {
+      args = (debug_type *) xmalloc (sizeof *args);
+      *args = NULL;
+      return debug_make_method_type (dhandle, return_type, class_type, args,
+                                    false);
+    }
+
+  args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs);
+  if (args == NULL)
+    return DEBUG_TYPE_NULL;
+
+  return debug_make_method_type (dhandle, return_type, class_type, args,
+                                varargs);
+}
+
+/* The tail end of stabs for C++ classes that contain a virtual function
+   pointer contains a tilde, a %, and a type number.
+   The type number refers to the base class (possibly this class itself) which
+   contains the vtable pointer for the current class.
+
+   This function is called when we have parsed all the method declarations,
+   so we can look for the vptr base class info.  */
+
+static boolean
+parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char **pp;
+     const int *typenums;
+     debug_type *retvptrbase;
+     boolean *retownvptr;
+{
+  const char *orig;
+  const char *hold;
+  int vtypenums[2];
+
+  *retvptrbase = DEBUG_TYPE_NULL;
+  *retownvptr = false;
+
+  orig = *pp;
+
+  /* If we are positioned at a ';', then skip it. */
+  if (**pp == ';')
+    ++*pp;
+
+  if (**pp != '~')
+    return true;
+
+  ++*pp;
+
+  if (**pp == '=' || **pp == '+' || **pp == '-')
+    {
+      /* Obsolete flags that used to indicate the presence of
+        constructors and/or destructors. */
+      ++*pp;
+    }
+
+  if (**pp != '%')
+    return true;
+
+  ++*pp;
+
+  hold = *pp;
+
+  /* The next number is the type number of the base class (possibly
+     our own class) which supplies the vtable for this class.  */
+  if (! parse_stab_type_number (pp, vtypenums))
+    return false;
+
+  if (vtypenums[0] == typenums[0]
+      && vtypenums[1] == typenums[1])
+    *retownvptr = true;
+  else
+    {
+      debug_type vtype;
+      const char *p;
+
+      *pp = hold;
+
+      vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                              (debug_type **) NULL);
+      for (p = *pp; *p != ';' && *p != '\0'; p++)
+       ;
+      if (*p != ';')
+       {
+         bad_stab (orig);
+         return false;
+       }
+
+      *retvptrbase = vtype;
+
+      *pp = p + 1;
+    }
+
+  return true;    
+}
+
+/* Read a definition of an array type.  */
+
+static debug_type
+parse_stab_array_type (dhandle, info, pp, stringp)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char **pp;
+     boolean stringp;
+{
+  const char *orig;
+  const char *p;
+  int typenums[2];
+  debug_type index_type;
+  boolean adjustable;
+  bfd_signed_vma lower, upper;
+  debug_type element_type;
+
+  /* Format of an array type:
+     "ar<index type>;lower;upper;<array_contents_type>".
+     OS9000: "arlower,upper;<array_contents_type>".
+
+     Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
+     for these, produce a type like float[][].  */
+
+  orig = *pp;
+
+  /* FIXME: gdb checks os9k_stabs here.  */
+
+  /* If the index type is type 0, we take it as int.  */
+  p = *pp;
+  if (! parse_stab_type_number (&p, typenums))
+    return false;
+  if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
+    {
+      index_type = debug_find_named_type (dhandle, "int");
+      if (index_type == DEBUG_TYPE_NULL)
+       {
+         index_type = debug_make_int_type (dhandle, 4, false);
+         if (index_type == DEBUG_TYPE_NULL)
+           return false;
+       }
+      *pp = p;
+    }
+  else
+    {
+      index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                   (debug_type **) NULL);
+    }
+
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return DEBUG_TYPE_NULL;
+    }
+  ++*pp;
+
+  adjustable = false;
+
+  if (! isdigit ((unsigned char) **pp) && **pp != '-')
+    {
+      ++*pp;
+      adjustable = true;
+    }
+
+  lower = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  if (! isdigit ((unsigned char) **pp) && **pp != '-')
+    {
+      ++*pp;
+      adjustable = true;
+    }
+
+  upper = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+  if (**pp != ';')
+    {
+      bad_stab (orig);
+      return false;
+    }
+  ++*pp;
+
+  element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                 (debug_type **) NULL);
+  if (element_type == DEBUG_TYPE_NULL)
+    return false;
+
+  if (adjustable)
+    {
+      lower = 0;
+      upper = -1;
+    }
+
+  return debug_make_array_type (dhandle, element_type, index_type, lower,
+                               upper, stringp);
+}
+
+/* This struct holds information about files we have seen using
+   N_BINCL.  */
+
+struct bincl_file
+{
+  /* The next N_BINCL file.  */
+  struct bincl_file *next;
+  /* The next N_BINCL on the stack.  */
+  struct bincl_file *next_stack;
+  /* The file name.  */
+  const char *name;
+  /* The hash value.  */
+  bfd_vma hash;
+  /* The file index.  */
+  unsigned int file;
+  /* The list of types defined in this file.  */
+  struct stab_types *file_types;
+};
+
+/* Start a new N_BINCL file, pushing it onto the stack.  */
+
+static void
+push_bincl (info, name, hash)
+     struct stab_handle *info;
+     const char *name;
+     bfd_vma hash;
+{
+  struct bincl_file *n;
+
+  n = (struct bincl_file *) xmalloc (sizeof *n);
+  n->next = info->bincl_list;
+  n->next_stack = info->bincl_stack;
+  n->name = name;
+  n->hash = hash;
+  n->file = info->files;
+  n->file_types = NULL;
+  info->bincl_list = n;
+  info->bincl_stack = n;
+
+  ++info->files;
+  info->file_types = ((struct stab_types **)
+                     xrealloc ((PTR) info->file_types,
+                               (info->files
+                                * sizeof *info->file_types)));
+  info->file_types[n->file] = NULL;
+}
+
+/* Finish an N_BINCL file, at an N_EINCL, popping the name off the
+   stack.  */
+
+static const char *
+pop_bincl (info)
+     struct stab_handle *info;
+{
+  struct bincl_file *o;
+
+  o = info->bincl_stack;
+  if (o == NULL)
+    return info->main_filename;
+  info->bincl_stack = o->next_stack;
+
+  o->file_types = info->file_types[o->file];
+
+  if (info->bincl_stack == NULL)
+    return info->main_filename;
+  return info->bincl_stack->name;
+}
+
+/* Handle an N_EXCL: get the types from the corresponding N_BINCL.  */
+
+static boolean
+find_excl (info, name, hash)
+     struct stab_handle *info;
+     const char *name;
+     bfd_vma hash;
+{
+  struct bincl_file *l;
+
+  ++info->files;
+  info->file_types = ((struct stab_types **)
+                     xrealloc ((PTR) info->file_types,
+                               (info->files
+                                * sizeof *info->file_types)));
+
+  for (l = info->bincl_list; l != NULL; l = l->next)
+    if (l->hash == hash && strcmp (l->name, name) == 0)
+      break;
+  if (l == NULL)
+    {
+      warn_stab (name, _("Undefined N_EXCL"));
+      info->file_types[info->files - 1] = NULL;
+      return true;
+    }
+
+  info->file_types[info->files - 1] = l->file_types;
+
+  return true;
+}
+
+/* Handle a variable definition.  gcc emits variable definitions for a
+   block before the N_LBRAC, so we must hold onto them until we see
+   it.  The SunPRO compiler emits variable definitions after the
+   N_LBRAC, so we can call debug_record_variable immediately.  */
+
+static boolean
+stab_record_variable (dhandle, info, name, type, kind, val)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char *name;
+     debug_type type;
+     enum debug_var_kind kind;
+     bfd_vma val;
+{
+  struct stab_pending_var *v;
+
+  if ((kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
+      || ! info->within_function
+      || (info->gcc_compiled == 0 && info->n_opt_found))
+    return debug_record_variable (dhandle, name, type, kind, val);
+
+  v = (struct stab_pending_var *) xmalloc (sizeof *v);
+  memset (v, 0, sizeof *v);
+
+  v->next = info->pending;
+  v->name = name;
+  v->type = type;
+  v->kind = kind;
+  v->val = val;
+  info->pending = v;
+
+  return true;
+}
+
+/* Emit pending variable definitions.  This is called after we see the
+   N_LBRAC that starts the block.  */
+
+static boolean
+stab_emit_pending_vars (dhandle, info)
+     PTR dhandle;
+     struct stab_handle *info;
+{
+  struct stab_pending_var *v;
+
+  v = info->pending;
+  while (v != NULL)
+    {
+      struct stab_pending_var *next;
+
+      if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val))
+       return false;
+
+      next = v->next;
+      free (v);
+      v = next;
+    }
+
+  info->pending = NULL;
+
+  return true;
+}
+
+/* Find the slot for a type in the database.  */
+
+static debug_type *
+stab_find_slot (info, typenums)
+     struct stab_handle *info;
+     const int *typenums;
+{
+  int filenum;
+  int index;
+  struct stab_types **ps;
+
+  filenum = typenums[0];
+  index = typenums[1];
+
+  if (filenum < 0 || (unsigned int) filenum >= info->files)
+    {
+      fprintf (stderr, _("Type file number %d out of range\n"), filenum);
+      return NULL;
+    }
+  if (index < 0)
+    {
+      fprintf (stderr, _("Type index number %d out of range\n"), index);
+      return NULL;
+    }
+
+  ps = info->file_types + filenum;
+
+  while (index >= STAB_TYPES_SLOTS)
+    {
+      if (*ps == NULL)
+       {
+         *ps = (struct stab_types *) xmalloc (sizeof **ps);
+         memset (*ps, 0, sizeof **ps);
+       }
+      ps = &(*ps)->next;
+      index -= STAB_TYPES_SLOTS;
+    }
+  if (*ps == NULL)
+    {
+      *ps = (struct stab_types *) xmalloc (sizeof **ps);
+      memset (*ps, 0, sizeof **ps);
+    }
+
+  return (*ps)->types + index;
+}
+
+/* Find a type given a type number.  If the type has not been
+   allocated yet, create an indirect type.  */
+
+static debug_type
+stab_find_type (dhandle, info, typenums)
+     PTR dhandle;
+     struct stab_handle *info;
+     const int *typenums;
+{
+  debug_type *slot;
+
+  if (typenums[0] == 0 && typenums[1] < 0)
+    {
+      /* A negative type number indicates an XCOFF builtin type.  */
+      return stab_xcoff_builtin_type (dhandle, info, typenums[1]);
+    }
+
+  slot = stab_find_slot (info, typenums);
+  if (slot == NULL)
+    return DEBUG_TYPE_NULL;
+
+  if (*slot == DEBUG_TYPE_NULL)
+    return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
+
+  return *slot;
+}
+
+/* Record that a given type number refers to a given type.  */
+
+static boolean
+stab_record_type (dhandle, info, typenums, type)
+     PTR dhandle;
+     struct stab_handle *info;
+     const int *typenums;
+     debug_type type;
+{
+  debug_type *slot;
+
+  slot = stab_find_slot (info, typenums);
+  if (slot == NULL)
+    return false;
+
+  /* gdb appears to ignore type redefinitions, so we do as well.  */
+
+  *slot = type;
+
+  return true;
+}
+
+/* Return an XCOFF builtin type.  */
+
+static debug_type
+stab_xcoff_builtin_type (dhandle, info, typenum)
+     PTR dhandle;
+     struct stab_handle *info;
+     int typenum;
+{
+  debug_type rettype;
+  const char *name;
+
+  if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT)
+    {
+      fprintf (stderr, _("Unrecognized XCOFF type %d\n"), typenum);
+      return DEBUG_TYPE_NULL;
+    }
+  if (info->xcoff_types[-typenum] != NULL)
+    return info->xcoff_types[-typenum];
+
+  switch (-typenum)
+    {
+    case 1:
+      /* The size of this and all the other types are fixed, defined
+        by the debugging format.  */
+      name = "int";
+      rettype = debug_make_int_type (dhandle, 4, false);
+      break;
+    case 2:
+      name = "char";
+      rettype = debug_make_int_type (dhandle, 1, false);
+      break;
+    case 3:
+      name = "short";
+      rettype = debug_make_int_type (dhandle, 2, false);
+      break;
+    case 4:
+      name = "long";
+      rettype = debug_make_int_type (dhandle, 4, false);
+      break;
+    case 5:
+      name = "unsigned char";
+      rettype = debug_make_int_type (dhandle, 1, true);
+      break;
+    case 6:
+      name = "signed char";
+      rettype = debug_make_int_type (dhandle, 1, false);
+      break;
+    case 7:
+      name = "unsigned short";
+      rettype = debug_make_int_type (dhandle, 2, true);
+      break;
+    case 8:
+      name = "unsigned int";
+      rettype = debug_make_int_type (dhandle, 4, true);
+      break;
+    case 9:
+      name = "unsigned";
+      rettype = debug_make_int_type (dhandle, 4, true);
+    case 10:
+      name = "unsigned long";
+      rettype = debug_make_int_type (dhandle, 4, true);
+      break;
+    case 11:
+      name = "void";
+      rettype = debug_make_void_type (dhandle);
+      break;
+    case 12:
+      /* IEEE single precision (32 bit).  */
+      name = "float";
+      rettype = debug_make_float_type (dhandle, 4);
+      break;
+    case 13:
+      /* IEEE double precision (64 bit).  */
+      name = "double";
+      rettype = debug_make_float_type (dhandle, 8);
+      break;
+    case 14:
+      /* This is an IEEE double on the RS/6000, and different machines
+        with different sizes for "long double" should use different
+        negative type numbers.  See stabs.texinfo.  */
+      name = "long double";
+      rettype = debug_make_float_type (dhandle, 8);
+      break;
+    case 15:
+      name = "integer";
+      rettype = debug_make_int_type (dhandle, 4, false);
+      break;
+    case 16:
+      name = "boolean";
+      rettype = debug_make_bool_type (dhandle, 4);
+      break;
+    case 17:
+      name = "short real";
+      rettype = debug_make_float_type (dhandle, 4);
+      break;
+    case 18:
+      name = "real";
+      rettype = debug_make_float_type (dhandle, 8);
+      break;
+    case 19:
+      /* FIXME */
+      name = "stringptr";
+      rettype = NULL;
+      break;
+    case 20:
+      /* FIXME */
+      name = "character";
+      rettype = debug_make_int_type (dhandle, 1, true);
+      break;
+    case 21:
+      name = "logical*1";
+      rettype = debug_make_bool_type (dhandle, 1);
+      break;
+    case 22:
+      name = "logical*2";
+      rettype = debug_make_bool_type (dhandle, 2);
+      break;
+    case 23:
+      name = "logical*4";
+      rettype = debug_make_bool_type (dhandle, 4);
+      break;
+    case 24:
+      name = "logical";
+      rettype = debug_make_bool_type (dhandle, 4);
+      break;
+    case 25:
+      /* Complex type consisting of two IEEE single precision values.  */
+      name = "complex";
+      rettype = debug_make_complex_type (dhandle, 8);
+      break;
+    case 26:
+      /* Complex type consisting of two IEEE double precision values.  */
+      name = "double complex";
+      rettype = debug_make_complex_type (dhandle, 16);
+      break;
+    case 27:
+      name = "integer*1";
+      rettype = debug_make_int_type (dhandle, 1, false);
+      break;
+    case 28:
+      name = "integer*2";
+      rettype = debug_make_int_type (dhandle, 2, false);
+      break;
+    case 29:
+      name = "integer*4";
+      rettype = debug_make_int_type (dhandle, 4, false);
+      break;
+    case 30:
+      /* FIXME */
+      name = "wchar";
+      rettype = debug_make_int_type (dhandle, 2, false);
+      break;
+    case 31:
+      name = "long long";
+      rettype = debug_make_int_type (dhandle, 8, false);
+      break;
+    case 32:
+      name = "unsigned long long";
+      rettype = debug_make_int_type (dhandle, 8, true);
+      break;
+    case 33:
+      name = "logical*8";
+      rettype = debug_make_bool_type (dhandle, 8);
+      break;
+    case 34:
+      name = "integer*8";
+      rettype = debug_make_int_type (dhandle, 8, false);
+      break;
+    default:
+      abort ();
+    }
+
+  rettype = debug_name_type (dhandle, name, rettype);
+
+  info->xcoff_types[-typenum] = rettype;
+
+  return rettype;
+}
+
+/* Find or create a tagged type.  */
+
+static debug_type
+stab_find_tagged_type (dhandle, info, p, len, kind)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char *p;
+     int len;
+     enum debug_type_kind kind;
+{
+  char *name;
+  debug_type dtype;
+  struct stab_tag *st;
+
+  name = savestring (p, len);
+
+  /* We pass DEBUG_KIND_ILLEGAL because we want all tags in the same
+     namespace.  This is right for C, and I don't know how to handle
+     other languages.  FIXME.  */
+  dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_ILLEGAL);
+  if (dtype != DEBUG_TYPE_NULL)
+    {
+      free (name);
+      return dtype;
+    }
+
+  /* We need to allocate an entry on the undefined tag list.  */
+  for (st = info->tags; st != NULL; st = st->next)
+    {
+      if (st->name[0] == name[0]
+         && strcmp (st->name, name) == 0)
+       {
+         if (st->kind == DEBUG_KIND_ILLEGAL)
+           st->kind = kind;
+         free (name);
+         break;
+       }
+    }
+  if (st == NULL)
+    {
+      st = (struct stab_tag *) xmalloc (sizeof *st);
+      memset (st, 0, sizeof *st);
+
+      st->next = info->tags;
+      st->name = name;
+      st->kind = kind;
+      st->slot = DEBUG_TYPE_NULL;
+      st->type = debug_make_indirect_type (dhandle, &st->slot, name);
+      info->tags = st;
+    }
+
+  return st->type;
+}
+\f
+/* In order to get the correct argument types for a stubbed method, we
+   need to extract the argument types from a C++ mangled string.
+   Since the argument types can refer back to the return type, this
+   means that we must demangle the entire physical name.  In gdb this
+   is done by calling cplus_demangle and running the results back
+   through the C++ expression parser.  Since we have no expression
+   parser, we must duplicate much of the work of cplus_demangle here.
+
+   We assume that GNU style demangling is used, since this is only
+   done for method stubs, and only g++ should output that form of
+   debugging information.  */
+
+/* This structure is used to hold a pointer to type information which
+   demangling a string.  */
+
+struct stab_demangle_typestring
+{
+  /* The start of the type.  This is not null terminated.  */
+  const char *typestring;
+  /* The length of the type.  */
+  unsigned int len;
+};
+
+/* This structure is used to hold information while demangling a
+   string.  */
+
+struct stab_demangle_info
+{
+  /* The debugging information handle.  */
+  PTR dhandle;
+  /* The stab information handle.  */
+  struct stab_handle *info;
+  /* The array of arguments we are building.  */
+  debug_type *args;
+  /* Whether the method takes a variable number of arguments.  */
+  boolean varargs;
+  /* The array of types we have remembered.  */
+  struct stab_demangle_typestring *typestrings;
+  /* The number of typestrings.  */
+  unsigned int typestring_count;
+  /* The number of typestring slots we have allocated.  */
+  unsigned int typestring_alloc;
+};
+
+static void stab_bad_demangle PARAMS ((const char *));
+static unsigned int stab_demangle_count PARAMS ((const char **));
+static boolean stab_demangle_get_count
+  PARAMS ((const char **, unsigned int *));
+static boolean stab_demangle_prefix
+  PARAMS ((struct stab_demangle_info *, const char **));
+static boolean stab_demangle_function_name
+  PARAMS ((struct stab_demangle_info *, const char **, const char *));
+static boolean stab_demangle_signature
+  PARAMS ((struct stab_demangle_info *, const char **));
+static boolean stab_demangle_qualified
+  PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_template
+  PARAMS ((struct stab_demangle_info *, const char **, char **));
+static boolean stab_demangle_class
+  PARAMS ((struct stab_demangle_info *, const char **, const char **));
+static boolean stab_demangle_args
+  PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
+          boolean *));
+static boolean stab_demangle_arg
+  PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
+          unsigned int *, unsigned int *));
+static boolean stab_demangle_type
+  PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_fund_type
+  PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
+static boolean stab_demangle_remember_type
+  PARAMS ((struct stab_demangle_info *, const char *, int));
+
+/* Warn about a bad demangling.  */
+
+static void
+stab_bad_demangle (s)
+     const char *s;
+{
+  fprintf (stderr, _("bad mangled name `%s'\n"), s);
+}
+
+/* Get a count from a stab string.  */
+
+static unsigned int
+stab_demangle_count (pp)
+     const char **pp;
+{
+  unsigned int count;
+
+  count = 0;
+  while (isdigit ((unsigned char) **pp))
+    {
+      count *= 10;
+      count += **pp - '0';
+      ++*pp;
+    }
+  return count;
+}
+
+/* Require a count in a string.  The count may be multiple digits, in
+   which case it must end in an underscore.  */
+
+static boolean
+stab_demangle_get_count (pp, pi)
+     const char **pp;
+     unsigned int *pi;
+{
+  if (! isdigit ((unsigned char) **pp))
+    return false;
+
+  *pi = **pp - '0';
+  ++*pp;
+  if (isdigit ((unsigned char) **pp))
+    {
+      unsigned int count;
+      const char *p;
+
+      count = *pi;
+      p = *pp;
+      do
+       {
+         count *= 10;
+         count += *p - '0';
+         ++p;
+       }
+      while (isdigit ((unsigned char) *p));
+      if (*p == '_')
+       {
+         *pp = p + 1;
+         *pi = count;
+       }
+    }
+
+  return true;
+}
+
+/* This function demangles a physical name, returning a NULL
+   terminated array of argument types.  */
+
+static debug_type *
+stab_demangle_argtypes (dhandle, info, physname, pvarargs)
+     PTR dhandle;
+     struct stab_handle *info;
+     const char *physname;
+     boolean *pvarargs;
+{
+  struct stab_demangle_info minfo;
+
+  minfo.dhandle = dhandle;
+  minfo.info = info;
+  minfo.args = NULL;
+  minfo.varargs = false;
+  minfo.typestring_alloc = 10;
+  minfo.typestrings = ((struct stab_demangle_typestring *)
+                      xmalloc (minfo.typestring_alloc
+                               * sizeof *minfo.typestrings));
+  minfo.typestring_count = 0;
+
+  /* cplus_demangle checks for special GNU mangled forms, but we can't
+     see any of them in mangled method argument types.  */
+
+  if (! stab_demangle_prefix (&minfo, &physname))
+    goto error_return;
+
+  if (*physname != '\0')
+    {
+      if (! stab_demangle_signature (&minfo, &physname))
+       goto error_return;
+    }
+
+  free (minfo.typestrings);
+  minfo.typestrings = NULL;
+
+  if (minfo.args == NULL)
+    fprintf (stderr, _("no argument types in mangled string\n"));
+
+  *pvarargs = minfo.varargs;
+  return minfo.args;
+
+ error_return:
+  if (minfo.typestrings != NULL)
+    free (minfo.typestrings);
+  return NULL;
+}
+
+/* Demangle the prefix of the mangled name.  */
+
+static boolean
+stab_demangle_prefix (minfo, pp)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+{
+  const char *scan;
+  unsigned int i;
+
+  /* cplus_demangle checks for global constructors and destructors,
+     but we can't see them in mangled argument types.  */
+
+  /* Look for `__'.  */
+  scan = *pp;
+  do
+    {
+      scan = strchr (scan, '_');
+    }
+  while (scan != NULL && *++scan != '_');
+
+  if (scan == NULL)
+    {
+      stab_bad_demangle (*pp);
+      return false;
+    }
+
+  --scan;
+
+  /* We found `__'; move ahead to the last contiguous `__' pair.  */
+  i = strspn (scan, "_");
+  if (i > 2)
+    scan += i - 2;
+
+  if (scan == *pp
+      && (isdigit ((unsigned char) scan[2])
+         || scan[2] == 'Q'
+         || scan[2] == 't'))
+    {
+      /* This is a GNU style constructor name.  */
+      *pp = scan + 2;
+      return true;
+    }
+  else if (scan == *pp
+          && ! isdigit ((unsigned char) scan[2])
+          && scan[2] != 't')
+    {
+      /* Look for the `__' that separates the prefix from the
+         signature.  */
+      while (*scan == '_')
+       ++scan;
+      scan = strstr (scan, "__");
+      if (scan == NULL || scan[2] == '\0')
+       {
+         stab_bad_demangle (*pp);
+         return false;
+       }
+
+      return stab_demangle_function_name (minfo, pp, scan);
+    }
+  else if (scan[2] != '\0')
+    {
+      /* The name doesn't start with `__', but it does contain `__'.  */
+      return stab_demangle_function_name (minfo, pp, scan);
+    }
+  else
+    {
+      stab_bad_demangle (*pp);
+      return false;
+    }
+  /*NOTREACHED*/
+}
+
+/* Demangle a function name prefix.  The scan argument points to the
+   double underscore which separates the function name from the
+   signature.  */
+
+static boolean
+stab_demangle_function_name (minfo, pp, scan)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+     const char *scan;
+{
+  const char *name;
+
+  /* The string from *pp to scan is the name of the function.  We
+     don't care about the name, since we just looking for argument
+     types.  However, for conversion operators, the name may include a
+     type which we must remember in order to handle backreferences.  */
+
+  name = *pp;
+  *pp = scan + 2;
+
+  if (*pp - name >= 5
+          && strncmp (name, "type", 4) == 0
+          && (name[4] == '$' || name[4] == '.'))
+    {
+      const char *tem;
+
+      /* This is a type conversion operator.  */
+      tem = name + 5;
+      if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
+       return false;
+    }
+  else if (name[0] == '_'
+          && name[1] == '_'
+          && name[2] == 'o'
+          && name[3] == 'p')
+    {
+      const char *tem;
+
+      /* This is a type conversion operator.  */
+      tem = name + 4;
+      if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
+       return false;
+    }
+
+  return true;
+}
+
+/* Demangle the signature.  This is where the argument types are
+   found.  */
+
+static boolean
+stab_demangle_signature (minfo, pp)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+{
+  const char *orig;
+  boolean expect_func, func_done;
+  const char *hold;
+
+  orig = *pp;
+
+  expect_func = false;
+  func_done = false;
+  hold = NULL;
+
+  while (**pp != '\0')
+    {
+      switch (**pp)
+       {
+       case 'Q':
+         hold = *pp;
+         if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL)
+             || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+           return false;
+         expect_func = true;
+         hold = NULL;
+         break;
+
+       case 'S':
+         /* Static member function.  FIXME: Can this happen?  */
+         if (hold == NULL)
+           hold = *pp;
+         ++*pp;
+         break;
+
+       case 'C':
+         /* Const member function.  */
+         if (hold == NULL)
+           hold = *pp;
+         ++*pp;
+         break;
+
+       case '0': case '1': case '2': case '3': case '4':
+       case '5': case '6': case '7': case '8': case '9':
+         if (hold == NULL)
+           hold = *pp;
+         if (! stab_demangle_class (minfo, pp, (const char **) NULL)
+             || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+           return false;
+         expect_func = true;
+         hold = NULL;
+         break;
+
+       case 'F':
+         /* Function.  I don't know if this actually happens with g++
+             output.  */
+         hold = NULL;
+         func_done = true;
+         ++*pp;
+         if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+           return false;
+         break;
+
+       case 't':
+         /* Template.  */
+         if (hold == NULL)
+           hold = *pp;
+         if (! stab_demangle_template (minfo, pp, (char **) NULL)
+             || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+           return false;
+         hold = NULL;
+         expect_func = true;
+         break;
+
+       case '_':
+         /* At the outermost level, we cannot have a return type
+            specified, so if we run into another '_' at this point we
+            are dealing with a mangled name that is either bogus, or
+            has been mangled by some algorithm we don't know how to
+            deal with.  So just reject the entire demangling.  */
+         stab_bad_demangle (orig);
+         return false;
+
+       default:
+         /* Assume we have stumbled onto the first outermost function
+            argument token, and start processing args.  */
+         func_done = true;
+         if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+           return false;
+         break;
+       }
+
+      if (expect_func)
+       {
+         func_done = true;
+         if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+           return false;
+       }
+    }
+
+  if (! func_done)
+    {
+      /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+        bar__3fooi is 'foo::bar(int)'.  We get here when we find the
+        first case, and need to ensure that the '(void)' gets added
+        to the current declp.  */
+      if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+       return false;
+    }
+
+  return true;
+}
+
+/* Demangle a qualified name, such as "Q25Outer5Inner" which is the
+   mangled form of "Outer::Inner".  */
+
+static boolean
+stab_demangle_qualified (minfo, pp, ptype)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+     debug_type *ptype;
+{
+  const char *orig;
+  const char *p;
+  unsigned int qualifiers;
+  debug_type context;
+
+  orig = *pp;
+
+  switch ((*pp)[1])
+    {
+    case '_':
+      /* GNU mangled name with more than 9 classes.  The count is
+        preceded by an underscore (to distinguish it from the <= 9
+        case) and followed by an underscore.  */
+      p = *pp + 2;
+      if (! isdigit ((unsigned char) *p) || *p == '0')
+       {
+         stab_bad_demangle (orig);
+         return false;
+       }
+      qualifiers = atoi (p);
+      while (isdigit ((unsigned char) *p))
+       ++p;
+      if (*p != '_')
+       {
+         stab_bad_demangle (orig);
+         return false;
+       }
+      *pp = p + 1;
+      break;
+
+    case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+      qualifiers = (*pp)[1] - '0';
+      /* Skip an optional underscore after the count.  */
+      if ((*pp)[2] == '_')
+       ++*pp;
+      *pp += 2;
+      break;
+
+    case '0':
+    default:
+      stab_bad_demangle (orig);
+      return false;
+    }
+
+  context = DEBUG_TYPE_NULL;
+
+  /* Pick off the names.  */
+  while (qualifiers-- > 0)
+    {
+      if (**pp == '_')
+       ++*pp;
+      if (**pp == 't')
+       {
+         char *name;
+
+         if (! stab_demangle_template (minfo, pp,
+                                       ptype != NULL ? &name : NULL))
+           return false;
+
+         if (ptype != NULL)
+           {
+             context = stab_find_tagged_type (minfo->dhandle, minfo->info,
+                                              name, strlen (name),
+                                              DEBUG_KIND_CLASS);
+             free (name);
+             if (context == DEBUG_TYPE_NULL)
+               return false;
+           }
+       }
+      else
+       {
+         unsigned int len;
+
+         len = stab_demangle_count (pp);
+         if (strlen (*pp) < len)
+           {
+             stab_bad_demangle (orig);
+             return false;
+           }
+
+         if (ptype != NULL)
+           {
+             const debug_field *fields;
+
+             fields = NULL;
+             if (context != DEBUG_TYPE_NULL)
+               fields = debug_get_fields (minfo->dhandle, context);
+
+             context = DEBUG_TYPE_NULL;
+
+             if (fields != NULL)
+               {
+                 char *name;
+
+                 /* Try to find the type by looking through the
+                     fields of context until we find a field with the
+                     same type.  This ought to work for a class
+                     defined within a class, but it won't work for,
+                     e.g., an enum defined within a class.  stabs does
+                     not give us enough information to figure out the
+                     latter case.  */
+
+                 name = savestring (*pp, len);
+
+                 for (; *fields != DEBUG_FIELD_NULL; fields++)
+                   {
+                     debug_type ft;
+                     const char *dn;
+
+                     ft = debug_get_field_type (minfo->dhandle, *fields);
+                     if (ft == NULL)
+                       return false;
+                     dn = debug_get_type_name (minfo->dhandle, ft);
+                     if (dn != NULL && strcmp (dn, name) == 0)
+                       {
+                         context = ft;
+                         break;
+                       }
+                   }
+
+                 free (name);
+               }
+
+             if (context == DEBUG_TYPE_NULL)
+               {
+                 /* We have to fall back on finding the type by name.
+                     If there are more types to come, then this must
+                     be a class.  Otherwise, it could be anything.  */
+
+                 if (qualifiers == 0)
+                   {
+                     char *name;
+
+                     name = savestring (*pp, len);
+                     context = debug_find_named_type (minfo->dhandle,
+                                                      name);
+                     free (name);
+                   }
+
+                 if (context == DEBUG_TYPE_NULL)
+                   {
+                     context = stab_find_tagged_type (minfo->dhandle,
+                                                      minfo->info,
+                                                      *pp, len,
+                                                      (qualifiers == 0
+                                                       ? DEBUG_KIND_ILLEGAL
+                                                       : DEBUG_KIND_CLASS));
+                     if (context == DEBUG_TYPE_NULL)
+                       return false;
+                   }
+               }
+           }
+
+         *pp += len;
+       }
+    }
+
+  if (ptype != NULL)
+    *ptype = context;
+
+  return true;
+}
+
+/* Demangle a template.  If PNAME is not NULL, this sets *PNAME to a
+   string representation of the template.  */
+
+static boolean
+stab_demangle_template (minfo, pp, pname)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+     char **pname;
+{
+  const char *orig;
+  unsigned int r, i;
+
+  orig = *pp;
+
+  ++*pp;
+
+  /* Skip the template name.  */
+  r = stab_demangle_count (pp);
+  if (r == 0 || strlen (*pp) < r)
+    {
+      stab_bad_demangle (orig);
+      return false;
+    }
+  *pp += r;
+
+  /* Get the size of the parameter list.  */
+  if (stab_demangle_get_count (pp, &r) == 0)
+    {
+      stab_bad_demangle (orig);
+      return false;
+    }
+
+  for (i = 0; i < r; i++)
+    {
+      if (**pp == 'Z')
+       {
+         /* This is a type parameter.  */
+         ++*pp;
+         if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
+           return false;
+       }
+      else
+       {
+         const char *old_p;
+         boolean pointerp, realp, integralp, charp, boolp;
+         boolean done;
+
+         old_p = *pp;
+         pointerp = false;
+         realp = false;
+         integralp = false;
+         charp = false;
+         boolp = false;
+         done = false;
+
+         /* This is a value parameter.  */
+
+         if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
+           return false;
+
+         while (*old_p != '\0' && ! done)
+           {
+             switch (*old_p)
+               {
+               case 'P':
+               case 'p':
+               case 'R':
+                 pointerp = true;
+                 done = true;
+                 break;
+               case 'C':       /* Const.  */
+               case 'S':       /* Signed.  */
+               case 'U':       /* Unsigned.  */
+               case 'V':       /* Volatile.  */
+               case 'F':       /* Function.  */
+               case 'M':       /* Member function.  */
+               case 'O':       /* ??? */
+                 ++old_p;
+                 break;
+               case 'Q':       /* Qualified name.  */
+                 integralp = true;
+                 done = true;
+                 break;
+               case 'T':       /* Remembered type.  */
+                 abort ();
+               case 'v':       /* Void.  */
+                 abort ();
+               case 'x':       /* Long long.  */
+               case 'l':       /* Long.  */
+               case 'i':       /* Int.  */
+               case 's':       /* Short.  */
+               case 'w':       /* Wchar_t.  */
+                 integralp = true;
+                 done = true;
+                 break;
+               case 'b':       /* Bool.  */
+                 boolp = true;
+                 done = true;
+                 break;
+               case 'c':       /* Char.  */
+                 charp = true;
+                 done = true;
+                 break;
+               case 'r':       /* Long double.  */
+               case 'd':       /* Double.  */
+               case 'f':       /* Float.  */
+                 realp = true;
+                 done = true;
+                 break;
+               default:
+                 /* Assume it's a user defined integral type.  */
+                 integralp = true;
+                 done = true;
+                 break;
+               }
+           }
+
+         if (integralp)
+           {
+             if (**pp == 'm')
+               ++*pp;
+             while (isdigit ((unsigned char) **pp))
+               ++*pp;
+           }
+         else if (charp)
+           {
+             unsigned int val;
+
+             if (**pp == 'm')
+               ++*pp;
+             val = stab_demangle_count (pp);
+             if (val == 0)
+               {
+                 stab_bad_demangle (orig);
+                 return false;
+               }
+           }
+         else if (boolp)
+           {
+             unsigned int val;
+
+             val = stab_demangle_count (pp);
+             if (val != 0 && val != 1)
+               {
+                 stab_bad_demangle (orig);
+                 return false;
+               }
+           }
+         else if (realp)
+           {
+             if (**pp == 'm')
+               ++*pp;
+             while (isdigit ((unsigned char) **pp))
+               ++*pp;
+             if (**pp == '.')
+               {
+                 ++*pp;
+                 while (isdigit ((unsigned char) **pp))
+                   ++*pp;
+               }
+             if (**pp == 'e')
+               {
+                 ++*pp;
+                 while (isdigit ((unsigned char) **pp))
+                   ++*pp;
+               }
+           }
+         else if (pointerp)
+           {
+             unsigned int len;
+
+             if (! stab_demangle_get_count (pp, &len))
+               {
+                 stab_bad_demangle (orig);
+                 return false;
+               }
+             *pp += len;
+           }
+       }
+    }
+
+  /* We can translate this to a string fairly easily by invoking the
+     regular demangling routine.  */
+  if (pname != NULL)
+    {
+      char *s1, *s2, *s3, *s4;
+      char *from, *to;
+
+      s1 = savestring (orig, *pp - orig);
+
+      s2 = concat ("NoSuchStrinG__", s1, (const char *) NULL);
+
+      free (s1);
+
+      s3 = cplus_demangle (s2, DMGL_ANSI);
+
+      free (s2);
+
+      if (s3 != NULL)
+       s4 = strstr (s3, "::NoSuchStrinG");
+      if (s3 == NULL || s4 == NULL)
+       {
+         stab_bad_demangle (orig);
+         if (s3 != NULL)
+           free (s3);
+         return false;
+       }
+
+      /* Eliminating all spaces, except those between > characters,
+         makes it more likely that the demangled name will match the
+         name which g++ used as the structure name.  */
+      for (from = to = s3; from != s4; ++from)
+       if (*from != ' '
+           || (from[1] == '>' && from > s3 && from[-1] == '>'))
+         *to++ = *from;
+
+      *pname = savestring (s3, to - s3);
+
+      free (s3);
+    }
+
+  return true;
+}
+
+/* Demangle a class name.  */
+
+static boolean
+stab_demangle_class (minfo, pp, pstart)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+     const char **pstart;
+{
+  const char *orig;
+  unsigned int n;
+
+  orig = *pp;
+
+  n = stab_demangle_count (pp);
+  if (strlen (*pp) < n)
+    {
+      stab_bad_demangle (orig);
+      return false;
+    }
+
+  if (pstart != NULL)
+    *pstart = *pp;
+
+  *pp += n;
+
+  return true;
+}
+
+/* Demangle function arguments.  If the pargs argument is not NULL, it
+   is set to a NULL terminated array holding the arguments.  */
+
+static boolean
+stab_demangle_args (minfo, pp, pargs, pvarargs)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+     debug_type **pargs;
+     boolean *pvarargs;
+{
+  const char *orig;
+  unsigned int alloc, count;
+
+  orig = *pp;
+
+  alloc = 10;
+  if (pargs != NULL)
+    {
+      *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
+      *pvarargs = false;
+    }
+  count = 0;
+
+  while (**pp != '_' && **pp != '\0' && **pp != 'e')
+    {
+      if (**pp == 'N' || **pp == 'T')
+       {
+         char temptype;
+         unsigned int r, t;
+
+         temptype = **pp;
+         ++*pp;
+
+         if (temptype == 'T')
+           r = 1;
+         else
+           {
+             if (! stab_demangle_get_count (pp, &r))
+               {
+                 stab_bad_demangle (orig);
+                 return false;
+               }
+           }
+
+         if (! stab_demangle_get_count (pp, &t))
+           {
+             stab_bad_demangle (orig);
+             return false;
+           }
+
+         if (t >= minfo->typestring_count)
+           {
+             stab_bad_demangle (orig);
+             return false;
+           }
+         while (r-- > 0)
+           {
+             const char *tem;
+
+             tem = minfo->typestrings[t].typestring;
+             if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc))
+               return false;
+           }
+       }
+      else
+       {
+         if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc))
+           return false;
+       }
+    }
+
+  if (pargs != NULL)
+    (*pargs)[count] = DEBUG_TYPE_NULL;
+
+  if (**pp == 'e')
+    {
+      if (pargs != NULL)
+       *pvarargs = true;
+      ++*pp;
+    }
+
+  return true;
+}
+
+/* Demangle a single argument.  */
+
+static boolean
+stab_demangle_arg (minfo, pp, pargs, pcount, palloc)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+     debug_type **pargs;
+     unsigned int *pcount;
+     unsigned int *palloc;
+{
+  const char *start;
+  debug_type type;
+
+  start = *pp;
+  if (! stab_demangle_type (minfo, pp,
+                           pargs == NULL ? (debug_type *) NULL : &type)
+      || ! stab_demangle_remember_type (minfo, start, *pp - start))
+    return false;
+
+  if (pargs != NULL)
+    {
+      if (type == DEBUG_TYPE_NULL)
+       return false;
+
+      if (*pcount + 1 >= *palloc)
+       {
+         *palloc += 10;
+         *pargs = ((debug_type *)
+                   xrealloc (*pargs, *palloc * sizeof **pargs));
+       }
+      (*pargs)[*pcount] = type;
+      ++*pcount;
+    }
+
+  return true;
+}
+
+/* Demangle a type.  If the ptype argument is not NULL, *ptype is set
+   to the newly allocated type.  */
+
+static boolean
+stab_demangle_type (minfo, pp, ptype)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+     debug_type *ptype;
+{
+  const char *orig;
+
+  orig = *pp;
+
+  switch (**pp)
+    {
+    case 'P':
+    case 'p':
+      /* A pointer type.  */
+      ++*pp;
+      if (! stab_demangle_type (minfo, pp, ptype))
+       return false;
+      if (ptype != NULL)
+       *ptype = debug_make_pointer_type (minfo->dhandle, *ptype);
+      break;
+
+    case 'R':
+      /* A reference type.  */
+      ++*pp;
+      if (! stab_demangle_type (minfo, pp, ptype))
+       return false;
+      if (ptype != NULL)
+       *ptype = debug_make_reference_type (minfo->dhandle, *ptype);
+      break;
+
+    case 'A':
+      /* An array.  */
+      {
+       unsigned long high;
+
+       ++*pp;
+       high = 0;
+       while (**pp != '\0' && **pp != '_')
+         {
+           if (! isdigit ((unsigned char) **pp))
+             {
+               stab_bad_demangle (orig);
+               return false;
+             }
+           high *= 10;
+           high += **pp - '0';
+           ++*pp;
+         }
+       if (**pp != '_')
+         {
+           stab_bad_demangle (orig);
+           return false;
+         }
+       ++*pp;
+
+       if (! stab_demangle_type (minfo, pp, ptype))
+         return false;
+       if (ptype != NULL)
+         {
+           debug_type int_type;
+
+           int_type = debug_find_named_type (minfo->dhandle, "int");
+           if (int_type == NULL)
+             int_type = debug_make_int_type (minfo->dhandle, 4, false);
+           *ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type,
+                                           0, high, false);
+         }
+      }
+      break;
+
+    case 'T':
+      /* A back reference to a remembered type.  */
+      {
+       unsigned int i;
+       const char *p;
+
+       ++*pp;
+       if (! stab_demangle_get_count (pp, &i))
+         {
+           stab_bad_demangle (orig);
+           return false;
+         }
+       if (i >= minfo->typestring_count)
+         {
+           stab_bad_demangle (orig);
+           return false;
+         }
+       p = minfo->typestrings[i].typestring;
+       if (! stab_demangle_type (minfo, &p, ptype))
+         return false;
+      }
+      break;
+
+    case 'F':
+      /* A function.  */
+      {
+       debug_type *args;
+       boolean varargs;
+
+       ++*pp;
+       if (! stab_demangle_args (minfo, pp,
+                                 (ptype == NULL
+                                  ? (debug_type **) NULL
+                                  : &args),
+                                 (ptype == NULL
+                                  ? (boolean *) NULL
+                                  : &varargs)))
+         return false;
+       if (**pp != '_')
+         {
+           /* cplus_demangle will accept a function without a return
+              type, but I don't know when that will happen, or what
+              to do if it does.  */
+           stab_bad_demangle (orig);
+           return false;
+         }
+       ++*pp;
+       if (! stab_demangle_type (minfo, pp, ptype))
+         return false;
+       if (ptype != NULL)
+         *ptype = debug_make_function_type (minfo->dhandle, *ptype, args,
+                                            varargs);
+
+      }
+      break;
+
+    case 'M':
+    case 'O':
+      {
+       boolean memberp, constp, volatilep;
+       debug_type *args;
+       boolean varargs;
+       unsigned int n;
+       const char *name;
+
+       memberp = **pp == 'M';
+       constp = false;
+       volatilep = false;
+       args = NULL;
+       varargs = false;
+
+       ++*pp;
+       if (! isdigit ((unsigned char) **pp))
+         {
+           stab_bad_demangle (orig);
+           return false;
+         }
+       n = stab_demangle_count (pp);
+       if (strlen (*pp) < n)
+         {
+           stab_bad_demangle (orig);
+           return false;
+         }
+       name = *pp;
+       *pp += n;
+
+       if (memberp)
+         {
+           if (**pp == 'C')
+             {
+               constp = true;
+               ++*pp;
+             }
+           else if (**pp == 'V')
+             {
+               volatilep = true;
+               ++*pp;
+             }
+           if (**pp != 'F')
+             {
+               stab_bad_demangle (orig);
+               return false;
+             }
+           ++*pp;
+           if (! stab_demangle_args (minfo, pp,
+                                     (ptype == NULL
+                                      ? (debug_type **) NULL
+                                      : &args),
+                                     (ptype == NULL
+                                      ? (boolean *) NULL
+                                      : &varargs)))
+             return false;
+         }
+
+       if (**pp != '_')
+         {
+           stab_bad_demangle (orig);
+           return false;
+         }
+       ++*pp;
+
+       if (! stab_demangle_type (minfo, pp, ptype))
+         return false;
+
+       if (ptype != NULL)
+         {
+           debug_type class_type;
+
+           class_type = stab_find_tagged_type (minfo->dhandle, minfo->info,
+                                               name, (int) n,
+                                               DEBUG_KIND_CLASS);
+           if (class_type == DEBUG_TYPE_NULL)
+             return false;
+
+           if (! memberp)
+             *ptype = debug_make_offset_type (minfo->dhandle, class_type,
+                                              *ptype);
+           else
+             {
+               /* FIXME: We have no way to record constp or
+                   volatilep.  */
+               *ptype = debug_make_method_type (minfo->dhandle, *ptype,
+                                                class_type, args, varargs);
+             }
+         }
+      }
+      break;
+
+    case 'G':
+      ++*pp;
+      if (! stab_demangle_type (minfo, pp, ptype))
+       return false;
+      break;
+
+    case 'C':
+      ++*pp;
+      if (! stab_demangle_type (minfo, pp, ptype))
+       return false;
+      if (ptype != NULL)
+       *ptype = debug_make_const_type (minfo->dhandle, *ptype);
+      break;
+
+    case 'Q':
+      {
+       const char *hold;
+
+       hold = *pp;
+       if (! stab_demangle_qualified (minfo, pp, ptype))
+         return false;
+      }
+      break;
+
+    default:
+      if (! stab_demangle_fund_type (minfo, pp, ptype))
+       return false;
+      break;
+    }
+
+  return true;
+}
+
+/* Demangle a fundamental type.  If the ptype argument is not NULL,
+   *ptype is set to the newly allocated type.  */
+
+static boolean
+stab_demangle_fund_type (minfo, pp, ptype)
+     struct stab_demangle_info *minfo;
+     const char **pp;
+     debug_type *ptype;
+{
+  const char *orig;
+  boolean constp, volatilep, unsignedp, signedp;
+  boolean done;
+
+  orig = *pp;
+
+  constp = false;
+  volatilep = false;
+  unsignedp = false;
+  signedp = false;
+
+  done = false;
+  while (! done)
+    {
+      switch (**pp)
+       {
+       case 'C':
+         constp = true;
+         ++*pp;
+         break;
+
+       case 'U':
+         unsignedp = true;
+         ++*pp;
+         break;
+
+       case 'S':
+         signedp = true;
+         ++*pp;
+         break;
+
+       case 'V':
+         volatilep = true;
+         ++*pp;
+         break;
+
+       default:
+         done = true;
+         break;
+       }
+    }
+
+  switch (**pp)
+    {
+    case '\0':
+    case '_':
+      /* cplus_demangle permits this, but I don't know what it means.  */
+      stab_bad_demangle (orig);
+      break;
+
+    case 'v': /* void */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "void");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_void_type (minfo->dhandle);
+       }
+      ++*pp;
+      break;
+
+    case 'x': /* long long */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "long long unsigned int"
+                                          : "long long int"));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 8, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 'l': /* long */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "long unsigned int"
+                                          : "long int"));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 'i': /* int */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "unsigned int"
+                                          : "int"));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 's': /* short */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "short unsigned int"
+                                          : "short int"));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 2, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 'b': /* bool */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "bool");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_bool_type (minfo->dhandle, 4);
+       }
+      ++*pp;
+      break;
+
+    case 'c': /* char */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "unsigned char"
+                                          : (signedp
+                                             ? "signed char"
+                                             : "char")));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 1, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 'w': /* wchar_t */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "__wchar_t");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 2, true);
+       }
+      ++*pp;
+      break;
+
+    case 'r': /* long double */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "long double");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_float_type (minfo->dhandle, 8);
+       }
+      ++*pp;
+      break;
+
+    case 'd': /* double */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "double");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_float_type (minfo->dhandle, 8);
+       }
+      ++*pp;
+      break;
+
+    case 'f': /* float */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "float");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_float_type (minfo->dhandle, 4);
+       }
+      ++*pp;
+      break;
+
+    case 'G':
+      ++*pp;
+      if (! isdigit ((unsigned char) **pp))
+       {
+         stab_bad_demangle (orig);
+         return false;
+       }
+      /* Fall through.  */
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      {
+       const char *hold;
+
+       if (! stab_demangle_class (minfo, pp, &hold))
+         return false;
+       if (ptype != NULL)
+         {
+           char *name;
+
+           name = savestring (hold, *pp - hold);
+           *ptype = debug_find_named_type (minfo->dhandle, name);
+           free (name);
+           if (*ptype == DEBUG_TYPE_NULL)
+             {
+               /* FIXME: It is probably incorrect to assume that
+                   undefined types are tagged types.  */
+               *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
+                                               hold, *pp - hold,
+                                               DEBUG_KIND_ILLEGAL);
+               if (*ptype == DEBUG_TYPE_NULL)
+                 return false;
+             }
+         }
+      }
+      break;
+
+    case 't':
+      {
+       char *name;
+
+       if (! stab_demangle_template (minfo, pp,
+                                     ptype != NULL ? &name : NULL))
+         return false;
+       if (ptype != NULL)
+         {
+           *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
+                                           name, strlen (name),
+                                           DEBUG_KIND_CLASS);
+           free (name);
+           if (*ptype == DEBUG_TYPE_NULL)
+             return false;
+         }
+      }
+      break;
+
+    default:
+      stab_bad_demangle (orig);
+      return false;
+    }
+
+  if (ptype != NULL)
+    {
+      if (constp)
+       *ptype = debug_make_const_type (minfo->dhandle, *ptype);
+      if (volatilep)
+       *ptype = debug_make_volatile_type (minfo->dhandle, *ptype);
+    }
+
+  return true;
+}
+
+/* Remember a type string in a demangled string.  */
+
+static boolean
+stab_demangle_remember_type (minfo, p, len)
+     struct stab_demangle_info *minfo;
+     const char *p;
+     int len;
+{
+  if (minfo->typestring_count >= minfo->typestring_alloc)
+    {
+      minfo->typestring_alloc += 10;
+      minfo->typestrings = ((struct stab_demangle_typestring *)
+                           xrealloc (minfo->typestrings,
+                                     (minfo->typestring_alloc
+                                      * sizeof *minfo->typestrings)));
+    }
+
+  minfo->typestrings[minfo->typestring_count].typestring = p;
+  minfo->typestrings[minfo->typestring_count].len = (unsigned int) len;
+  ++minfo->typestring_count;
+
+  return true;
+}
diff --git a/binutils/stamp-h.in b/binutils/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/binutils/strings.1 b/binutils/strings.1
new file mode 100644 (file)
index 0000000..408de29
--- /dev/null
@@ -0,0 +1,151 @@
+.\" Copyright (c) 1993 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH strings 1 "25 June 1993" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+strings \- print the strings of printable characters in files
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B strings
+.RB "[\|" \-a | \-\c
+.RB | \-\-all "\|]" 
+.RB "[\|" \-f | \-\-print\-file\-name "\|]"
+.RB "[\|" \-o "\|]" 
+.RB "[\|" \-\-help "\|]" 
+.RB "[\|" \-v | \-\-version "\|]"  
+.RB "[\|" \-n
+.I min\-len\c
+.RI | \-min\-len\c
+.RB | "\-\-bytes="\c
+.I min\-len\c
+\&\|]
+.RB "[\|" \-t
+.I {o,x,d}\c
+.RB "[\|" "\-\-target=\fIbfdname" "\|]"
+.RB | "\-\-radix="\c
+.I {o,x,d}\c
+\&\|]
+.I file\c
+.ad b
+.hy 1
+.SH DESCRIPTION
+For each
+.I file
+given, GNU \c
+.B strings
+prints the printable character sequences that are at least 4
+characters long (or the number given with the options below) and are
+followed by an unprintable character.  By default, it only prints the
+strings from the initialized and loaded sections of object files; for
+other types of files, it prints the strings from the whole file.
+
+.PP
+.B strings
+is mainly useful for determining the contents of non-text files.
+
+.SH OPTIONS
+The long and short forms of options, shown here as alternatives, are
+equivalent.
+
+.TP
+.B \-a
+.TP
+.B \-\-all
+.TP
+.B \-
+Do not scan only the initialized and loaded sections of object files;
+scan the whole files.
+
+.TP
+.B \-f
+.TP
+.B \-\-print\-file\-name
+Print the name of the file before each string.
+
+.TP
+.B \-\-help
+Print a summary of the options to
+.B strings
+on the standard output and exit.
+
+.TP
+.B \-v
+.TP
+.B \-\-version
+Print the version number
+of
+.B strings
+on the standard output and exit.
+
+.TP
+.B "\-n \fImin\-len\fP"
+.TP
+.B "\-\fImin\-len\fP"
+.TP
+.B "\-bytes=\fImin\-len\fP"
+Print sequences of characters that are at least
+.I min\-len
+characters long, instead of the default 4.
+
+.TP
+.BR "\-t " {o,x,d}
+.TP
+.BR "\-\-radix=" {o,x,d}
+Print the offset within the file before each string.  The single
+character argument specifies the radix of the offset\(emoctal,
+hexadecimal, or decimal.
+
+.TP
+.BI "\-\-target=" "bfdname"
+Specify an object code format other than your system's default format.
+See 
+.BR objdump ( 1 ),
+for information on listing available formats.
+
+.TP
+.B \-o
+Like
+.BR "\-t o" .
+
+.PP
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'"
+entry in 
+.B
+info\c
+\&; 
+.I
+The GNU Binary Utilities\c
+\&, Roland H. Pesch (October 1991);
+.BR ar ( 1 ),
+.BR nm ( 1 ),
+.BR objdump ( 1 ),
+.BR ranlib ( 1 ).
+
+
+.SH COPYING
+Copyright (c) 1993 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/strings.c b/binutils/strings.c
new file mode 100644 (file)
index 0000000..8ffe6a1
--- /dev/null
@@ -0,0 +1,514 @@
+/* strings -- print the strings of printable characters in files
+   Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+
+   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 2, 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+\f
+/* Usage: strings [options] file...
+
+   Options:
+   --all
+   -a
+   -           Do not scan only the initialized data section of object files.
+
+   --print-file-name
+   -f          Print the name of the file before each string.
+
+   --bytes=min-len
+   -n min-len
+   -min-len    Print graphic char sequences, MIN-LEN or more bytes long,
+               that are followed by a NUL or a newline.  Default is 4.
+
+   --radix={o,x,d}
+   -t {o,x,d}  Print the offset within the file before each string,
+               in octal/hex/decimal.
+
+   -o          Like -to.  (Some other implementations have -o like -to,
+               others like -td.  We chose one arbitrarily.)
+
+   --target=BFDNAME
+               Specify a non-default object file format.
+
+   --help
+   -h          Print the usage message on the standard output.
+
+   --version
+   -v          Print the program version number.
+
+   Written by Richard Stallman <rms@gnu.ai.mit.edu>
+   and David MacKenzie <djm@gnu.ai.mit.edu>.  */
+
+#include "bfd.h"
+#include <stdio.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <errno.h>
+#include "bucomm.h"
+#include "libiberty.h"
+
+#ifdef isascii
+#define isgraphic(c) (isascii (c) && isprint (c))
+#else
+#define isgraphic(c) (isprint (c))
+#endif
+
+#ifndef errno
+extern int errno;
+#endif
+
+/* The BFD section flags that identify an initialized data section.  */
+#define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
+
+/* Radix for printing addresses (must be 8, 10 or 16).  */
+static int address_radix;
+
+/* Minimum length of sequence of graphic chars to trigger output.  */
+static int string_min;
+
+/* true means print address within file for each string.  */
+static boolean print_addresses;
+
+/* true means print filename for each string.  */
+static boolean print_filenames;
+
+/* true means for object files scan only the data section.  */
+static boolean datasection_only;
+
+/* true if we found an initialized data section in the current file.  */
+static boolean got_a_section;
+
+/* The BFD object file format.  */
+static char *target;
+
+static struct option long_options[] =
+{
+  {"all", no_argument, NULL, 'a'},
+  {"print-file-name", no_argument, NULL, 'f'},
+  {"bytes", required_argument, NULL, 'n'},
+  {"radix", required_argument, NULL, 't'},
+  {"target", required_argument, NULL, 'T'},
+  {"help", no_argument, NULL, 'h'},
+  {"version", no_argument, NULL, 'v'},
+  {NULL, 0, NULL, 0}
+};
+
+static void strings_a_section PARAMS ((bfd *, asection *, PTR));
+static boolean strings_object_file PARAMS ((const char *));
+static boolean strings_file PARAMS ((char *file));
+static int integer_arg PARAMS ((char *s));
+static void print_strings PARAMS ((const char *filename, FILE *stream,
+                                 file_ptr address, int stop_point,
+                                 int magiccount, char *magic));
+static void usage PARAMS ((FILE *stream, int status));
+\f
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int optc;
+  int exit_status = 0;
+  boolean files_given = false;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = argv[0];
+  xmalloc_set_program_name (program_name);
+  string_min = -1;
+  print_addresses = false;
+  print_filenames = false;
+  datasection_only = true;
+  target = NULL;
+
+  while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789",
+                             long_options, (int *) 0)) != EOF)
+    {
+      switch (optc)
+       {
+       case 'a':
+         datasection_only = false;
+         break;
+
+       case 'f':
+         print_filenames = true;
+         break;
+
+       case 'h':
+         usage (stdout, 0);
+
+       case 'n':
+         string_min = integer_arg (optarg);
+         if (string_min < 1)
+           {
+             fprintf (stderr, _("%s: invalid number %s\n"),
+                      program_name, optarg);
+             exit (1);
+           }
+         break;
+
+       case 'o':
+         print_addresses = true;
+         address_radix = 8;
+         break;
+
+       case 't':
+         print_addresses = true;
+         if (optarg[1] != '\0')
+           usage (stderr, 1);
+         switch (optarg[0])
+           {
+           case 'o':
+             address_radix = 8;
+             break;
+
+           case 'd':
+             address_radix = 10;
+             break;
+
+           case 'x':
+             address_radix = 16;
+             break;
+
+           default:
+             usage (stderr, 1);
+           }
+         break;
+
+       case 'T':
+         target = optarg;
+         break;
+
+       case 'v':
+         print_version ("strings");
+         break;
+
+       case '?':
+         usage (stderr, 1);
+
+       default:
+         if (string_min < 0)
+           string_min = optc;
+         else
+           string_min = string_min * 10 + optc - '0';
+         break;
+       }
+    }
+
+  if (string_min < 0)
+    string_min = 4;
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  if (optind >= argc)
+    {
+      datasection_only = false;
+      print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
+      files_given = true;
+    }
+  else
+    {
+      for (; optind < argc; ++optind)
+       {
+         if (strcmp (argv[optind], "-") == 0)
+           datasection_only = false;
+         else
+           {
+             files_given = true;
+             exit_status |= (strings_file (argv[optind]) == false);
+           }
+       }
+    }
+
+  if (files_given == false)
+    usage (stderr, 1);
+
+  return (exit_status);
+}
+\f
+/* Scan section SECT of the file ABFD, whose printable name is FILE.
+   If it contains initialized data,
+   set `got_a_section' and print the strings in it.  */
+
+static void
+strings_a_section (abfd, sect, filearg)
+     bfd *abfd;
+     asection *sect;
+     PTR filearg;
+{
+  const char *file = (const char *) filearg;
+
+  if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
+    {
+      bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
+      PTR mem = xmalloc (sz);
+      if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
+       {
+         got_a_section = true;
+         print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
+       }
+      free (mem);
+    }
+}
+
+/* Scan all of the sections in FILE, and print the strings
+   in the initialized data section(s).
+
+   Return true if successful,
+   false if not (such as if FILE is not an object file).  */
+
+static boolean
+strings_object_file (file)
+     const char *file;
+{
+  bfd *abfd = bfd_openr (file, target);
+
+  if (abfd == NULL)
+    {
+      /* Treat the file as a non-object file.  */
+      return false;
+    }
+
+  /* This call is mainly for its side effect of reading in the sections.
+     We follow the traditional behavior of `strings' in that we don't
+     complain if we don't recognize a file to be an object file.  */
+  if (bfd_check_format (abfd, bfd_object) == false)
+    {
+      bfd_close (abfd);
+      return false;
+    }
+
+  got_a_section = false;
+  bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
+
+  if (!bfd_close (abfd))
+    {
+      bfd_nonfatal (file);
+      return false;
+    }
+
+  return got_a_section;
+}
+
+/* Print the strings in FILE.  Return true if ok, false if an error occurs.  */
+
+static boolean
+strings_file (file)
+     char *file;
+{
+  /* If we weren't told to scan the whole file,
+     try to open it as an object file and only look at
+     initialized data sections.  If that fails, fall back to the
+     whole file.  */
+  if (!datasection_only || !strings_object_file (file))
+    {
+      FILE *stream;
+
+      stream = fopen (file, "rb");
+      /* Not all systems permit "rb", so try "r" if it failed.  */
+      if (stream == NULL)
+       stream = fopen (file, "r");
+      if (stream == NULL)
+       {
+         fprintf (stderr, "%s: ", program_name);
+         perror (file);
+         return false;
+       }
+
+      print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
+
+      if (fclose (stream) == EOF)
+       {
+         fprintf (stderr, "%s: ", program_name);
+         perror (file);
+         return false;
+       }
+    }
+
+  return true;
+}
+\f
+/* Find the strings in file FILENAME, read from STREAM.
+   Assume that STREAM is positioned so that the next byte read
+   is at address ADDRESS in the file.
+   Stop reading at address STOP_POINT in the file, if nonzero.
+
+   If STREAM is NULL, do not read from it.
+   The caller can supply a buffer of characters
+   to be processed before the data in STREAM.
+   MAGIC is the address of the buffer and
+   MAGICCOUNT is how many characters are in it.
+   Those characters come at address ADDRESS and the data in STREAM follow.  */
+
+static void
+print_strings (filename, stream, address, stop_point, magiccount, magic)
+     const char *filename;
+     FILE *stream;
+     file_ptr address;
+     int stop_point;
+     int magiccount;
+     char *magic;
+{
+  char *buf = (char *) xmalloc (string_min + 1);
+
+  while (1)
+    {
+      file_ptr start;
+      int i;
+      int c;
+
+      /* See if the next `string_min' chars are all graphic chars.  */
+    tryline:
+      if (stop_point && address >= stop_point)
+       break;
+      start = address;
+      for (i = 0; i < string_min; i++)
+       {
+         if (magiccount)
+           {
+             magiccount--;
+             c = *magic++;
+           }
+         else
+           {
+             if (stream == NULL)
+               return;
+             c = getc (stream);
+             if (c == EOF)
+               return;
+           }
+         address++;
+         if (!isgraphic (c))
+           /* Found a non-graphic.  Try again starting with next char.  */
+           goto tryline;
+         buf[i] = c;
+       }
+
+      /* We found a run of `string_min' graphic characters.  Print up
+         to the next non-graphic character.  */
+
+      if (print_filenames)
+       printf ("%s: ", filename);
+      if (print_addresses)
+       switch (address_radix)
+         {
+         case 8:
+           printf ("%7lo ", (unsigned long) start);
+           break;
+
+         case 10:
+           printf ("%7ld ", (long) start);
+           break;
+
+         case 16:
+           printf ("%7lx ", (unsigned long) start);
+           break;
+         }
+
+      buf[i] = '\0';
+      fputs (buf, stdout);
+
+      while (1)
+       {
+         if (magiccount)
+           {
+             magiccount--;
+             c = *magic++;
+           }
+         else
+           {
+             if (stream == NULL)
+               break;
+             c = getc (stream);
+             if (c == EOF)
+               break;
+           }
+         address++;
+         if (! isgraphic (c))
+           break;
+         putchar (c);
+       }
+
+      putchar ('\n');
+    }
+}
+\f
+/* Parse string S as an integer, using decimal radix by default,
+   but allowing octal and hex numbers as in C.  */
+
+static int
+integer_arg (s)
+     char *s;
+{
+  int value;
+  int radix = 10;
+  char *p = s;
+  int c;
+
+  if (*p != '0')
+    radix = 10;
+  else if (*++p == 'x')
+    {
+      radix = 16;
+      p++;
+    }
+  else
+    radix = 8;
+
+  value = 0;
+  while (((c = *p++) >= '0' && c <= '9')
+        || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
+    {
+      value *= radix;
+      if (c >= '0' && c <= '9')
+       value += c - '0';
+      else
+       value += (c & ~40) - 'A';
+    }
+
+  if (c == 'b')
+    value *= 512;
+  else if (c == 'B')
+    value *= 1024;
+  else
+    p--;
+
+  if (*p)
+    {
+      fprintf (stderr, _("%s: invalid integer argument %s\n"), program_name, s);
+      exit (1);
+    }
+  return value;
+}
+
+static void
+usage (stream, status)
+     FILE *stream;
+     int status;
+{
+  fprintf (stream, _("\
+Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\
+       [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
+       [--target=bfdname] [--help] [--version] file...\n"),
+          program_name);
+  list_supported_targets (program_name, stream);
+  if (status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (status);
+}
diff --git a/binutils/strip.1 b/binutils/strip.1
new file mode 100644 (file)
index 0000000..708817d
--- /dev/null
@@ -0,0 +1,185 @@
+.\" Copyright (c) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH strip 1 "5 November 1991" "cygnus support" "GNU Development Tools"
+.de BP
+.sp
+.ti \-.2i
+\(**
+..
+
+.SH NAME
+strip \- Discard symbols from object files.
+
+.SH SYNOPSIS
+.hy 0
+.na
+.TP
+.B strip
+.RB "[\|" \-F\ \fIbfdname\fR\ |\ \fB\-\-target=\fIbfdname\fP "\|]"
+.RB "[\|" \-I\ \fIbfdname\fR\ |\ \fB\-\-input\-target=\fIbfdname\fP "\|]"
+.RB "[\|" \-O\ \fIbfdname\fR\ |\ \fB\-\-output\-target=\fIbfdname\fP "\|]"
+.RB "[\|" \-R\ \fIsectionname\fR\ |\ \fB\-\-remove\-section=\fIsectionname\fP "\|]"
+.RB "[\|" \-s\fR\ |\ \fB\-\-strip\-all "\|]"
+.RB "[\|" \-S\fR\ |\ \fB\-g\fR\ |\ \fB\-\-strip\-debug "\|]"
+.RB "[\|" \-\-strip\-unneeded\fR "\|]"
+.RB "[\|" \-x\fR\ |\ \fB\-\-discard\-all "\|]"
+.RB "[\|" \-X\fR\ |\ \fB\-\-discard\-locals "\|]"
+.RB "[\|" \-K\ \fIsymbolname\fR\ |\ \fB\-\-keep\-symbol=\fIsymbolname\fR "\|]" 
+.RB "[\|" \-N\ \fIsymbolname\fR\ |\ \fB\-\-strip\-symbol=\fIsymbolname\fR "\|]"
+.RB "[\|" \-o\ \fIfile\f\R "\|]"
+.RB "[\|" \-p\fR\ |\ \fB\-\-preserve\-dates "\|]"
+.RB "[\|" \-v\fR\ |\ \fB\-\-verbose "\|]"
+.RB "[\|" \-V\fR\ |\ \fB\-\-version "\|]"
+.RB "[\|" \-V\fR\ |\ \fB\-\-help "\|]"
+.I objfile\c
+\&.\|.\|.
+
+.SH DESCRIPTION
+GNU
+.B strip
+discards all symbols from the object files
+.IR objfile .
+The list of object files may include archives.
+At least one object file must be given.
+
+.P
+.B strip
+modifies the files named in its argument,
+rather than writing modified copies under different names.
+
+.SH OPTIONS
+.TP
+.B "\-F \fIbfdname"
+.TP
+.B "\-\-target=\fIbfdname"
+Treat the original \fIobjfile\fP as a file with the object
+code format \fIbfdname\fP, and rewrite it in the same format.
+
+.TP
+.B \-\-help
+Show a summary of the options to
+.B strip
+and exit.
+
+.TP
+.B "\-I \fIbfdname
+.TP
+.B "\-\-input\-target=\fIbfdname"
+Treat the original \fIobjfile\fP as a file with the object
+code format \fIbfdname\fP.
+
+.TP
+.B "\-O \fIbfdname\fP"
+.TP
+.B "\-\-output\-target=\fIbfdname"
+Replace \fIobjfile\fP with a file in the output format \fIbfdname\fP.
+
+.TP
+.B "\-R \fIsectionname\fP"
+.TP
+.B "\-\-remove\-section=\fIsectionname"
+Remove the named section from the file.  This option may be given more
+than once.  Note that using this option inappropriately may make the
+object file unusable.
+
+.TP
+.B \-s
+.TP
+.B \-\-strip\-all
+Remove all symbols.
+
+.TP
+.B \-S
+.TP
+.B \-g
+.TP
+.B \-\-strip\-debug
+Remove debugging symbols only.
+
+.TP
+.B \-\-strip\-unneeded
+Strip all symbols that are not needed for relocation processing.
+
+.TP
+.B \-N \fIsymbolname\fR
+.TP
+.B \-\-strip\-symbol=\fIsymbolname
+Remove symbol \fIsymbolname\fP from the source file. This option
+may be given more than once, and may be combined with other strip
+options.
+
+.TP
+.B \-o \fIfile\fR
+Put the stripped output in \fIfile\fR, rather than replacing the
+existing file.  When this argument is used, only one \fIobjfile\fR
+argument may be specified.
+
+.TP
+.B \-p
+.TP
+.B \-\-preserve-dates
+Preserve the access and modification dates of the file.
+
+.TP
+.B \-x
+.TP
+.B \-\-discard\-all
+Remove non-global symbols.
+
+.TP
+.B \-X
+.TP
+.B \-\-discard\-locals
+Remove compiler-generated local symbols.
+(These usually start with ``L'' or ``.''.)
+
+.TP
+.B \-K \fIsymbolname\fR, \fB\-\-keep\-symbol=\fIsymbolname
+Copy only symbol \fIsymbolname\fP from the source file. This option
+may be given more than once.
+
+.TP
+.B \-N \fIsymbolname\fR, \fB\-\-strip\-symbol=\fIsymbolname
+Do not copy symbol \fIsymbolname\fP from the source file. This option
+may be given more than once, and may be combined with strip options
+other than \fB\-K\fR.
+
+.TP
+.B \-v
+.TP
+.B \-\-verbose
+Verbose output: list all object files modified.  In the case of
+archives,
+.B "strip \-v"
+lists all members of the archive.
+
+.TP
+.B \-V
+.TP
+.B \-\-version
+Show the version number for \fBstrip\fP and exit.
+
+.SH "SEE ALSO"
+.RB "`\|" binutils "\|'" 
+entry in 
+.BR info ;
+.IR "The GNU Binary Utilities" ,
+Roland H. Pesch (October 1991).
+
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/binutils/sysdump.c b/binutils/sysdump.c
new file mode 100644 (file)
index 0000000..c821e8c
--- /dev/null
@@ -0,0 +1,790 @@
+/* Sysroff object format dumper.
+   Copyright (C) 1994, 95, 98, 1999 Free Software Foundation, Inc.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+
+/* Written by Steve Chamberlain <sac@cygnus.com>.
+
+ This program reads a SYSROFF object file and prints it in an
+ almost human readable form to stdout. */
+
+#include "bfd.h"
+#include "bucomm.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <libiberty.h>
+#include <getopt.h>
+#include "sysroff.h"
+
+#define PROGRAM_VERSION "1.0"
+
+static int dump = 1;
+static int segmented_p;
+static int code;
+static int addrsize = 4;
+static FILE *file;
+
+char *
+getCHARS (ptr, idx, size, max)
+     unsigned char *ptr;
+     int *idx;
+     int size;
+     int max;
+{
+  int oc = *idx / 8;
+  char *r;
+  int b = size;
+  if (b >= max)
+    {
+      return "*undefined*";
+    }
+
+  if (b == 0)
+    {
+      /* Got to work out the length of the string from self */
+      b = ptr[oc++];
+      (*idx) += 8;
+    }
+
+  *idx += b * 8;
+  r = xcalloc (b + 1, 1);
+  memcpy (r, ptr + oc, b);
+  r[b] = 0;
+  return r;
+}
+
+static void
+dh (ptr, size)
+     unsigned char *ptr;
+     int size;
+{
+  int i;
+  int j;
+  int span = 16;
+
+  printf ("\n************************************************************\n");
+
+  for (i = 0; i < size; i += span)
+    {
+      for (j = 0; j < span; j++)
+       {
+         if (j + i < size) 
+           printf ("%02x ", ptr[i + j]);
+          else
+            printf ("   ");
+       }
+
+      for (j = 0; j < span && j + i < size; j++)
+       {
+         int c = ptr[i + j];
+         if (c < 32 || c > 127)
+           c = '.';
+         printf ("%c", c);
+       }
+      printf ("\n");
+    }
+}
+
+int
+fillup (ptr)
+     char *ptr;
+{
+  int size;
+  int sum;
+  int i;
+  size = getc (file) - 2;
+  fread (ptr, 1, size, file);
+  sum = code + size + 2;
+  for (i = 0; i < size; i++)
+    {
+      sum += ptr[i];
+    }
+
+  if ((sum & 0xff) != 0xff)
+    {
+      printf ("SUM IS %x\n", sum);
+    }
+  if (dump)
+    dh (ptr, size);
+
+  return size - 1;
+}
+
+barray
+getBARRAY (ptr, idx, dsize, max)
+     unsigned char *ptr;
+     int *idx;
+     int dsize;
+     int max;
+{
+  barray res;
+  int i;
+  int byte = *idx / 8;
+  int size = ptr[byte++];
+  res.len = size;
+  res.data = (unsigned char *) xmalloc (size);
+  for (i = 0; i < size; i++)
+    {
+      res.data[i] = ptr[byte++];
+    }
+  return res;
+}
+
+int
+getINT (ptr, idx, size, max)
+     unsigned char *ptr;
+     int *idx;
+     int size;
+     int max;
+{
+  int n = 0;
+  int byte = *idx / 8;
+
+  if (byte >= max)
+    {
+      return 0;
+    }
+  if (size == -2)
+    size = addrsize;
+  if (size == -1)
+    size = 0;
+  switch (size)
+    {
+    case 0:
+      return 0;
+    case 1:
+      n = (ptr[byte]);
+      break;
+    case 2:
+      n = (ptr[byte + 0] << 8) + ptr[byte + 1];
+      break;
+    case 4:
+      n = (ptr[byte + 0] << 24) + (ptr[byte + 1] << 16) + (ptr[byte + 2] << 8) + (ptr[byte + 3]);
+      break;
+    default:
+      abort ();
+    }
+  *idx += size * 8;
+  return n;
+}
+
+int
+getBITS (ptr, idx, size, max)
+     char *ptr;
+     int *idx;
+     int size, max;
+{
+  int byte = *idx / 8;
+  int bit = *idx % 8;
+
+  if (byte >= max)
+    return 0;
+
+  *idx += size;
+
+  return (ptr[byte] >> (8 - bit - size)) & ((1 << size) - 1);
+}
+
+static void
+itheader (name, code)
+     char *name;
+     int code;
+{
+  printf ("\n%s 0x%02x\n", name, code);
+}
+
+static int indent;
+static void
+p ()
+{
+  int i;
+  for (i = 0; i < indent; i++)
+    {
+      printf ("| ");
+    }
+  printf ("> ");
+}
+
+static void
+tabout ()
+{
+  p ();
+}
+
+static void
+pbarray (y)
+     barray *y;
+{
+  int x;
+  printf ("%d (", y->len);
+  for (x = 0; x < y->len; x++)
+    {
+      printf ("(%02x %c)", y->data[x], isprint (y->data[x]) ? y->data[x] : '.');
+    }
+  printf (")\n");
+}
+
+#define SYSROFF_PRINT
+#define SYSROFF_SWAP_IN
+
+#include "sysroff.c"
+
+/* 
+ * FIXME: sysinfo, which generates sysroff.[ch] from sysroff.info, can't
+ * hack the special case of the tr block, which has no contents.  So we
+ * implement our own functions for reading in and printing out the tr
+ * block.
+ */
+
+#define IT_tr_CODE     0x7f
+void
+sysroff_swap_tr_in()
+{
+       char raw[255];
+
+       memset(raw, 0, 255);
+       fillup(raw);
+}
+
+void
+sysroff_print_tr_out()
+{
+       itheader("tr", IT_tr_CODE);
+}
+
+static int
+getone (type)
+     int type;
+{
+  int c = getc (file);
+  code = c;
+
+  if ((c & 0x7f) != type)
+    {
+      ungetc (c, file);
+      return 0;
+    }
+
+  switch (c & 0x7f)
+    {
+    case IT_cs_CODE:
+      {
+       struct IT_cs dummy;
+       sysroff_swap_cs_in (&dummy);
+       sysroff_print_cs_out (&dummy);
+      }
+      break;
+    case IT_dln_CODE:
+      {
+       struct IT_dln dummy;
+       sysroff_swap_dln_in (&dummy);
+       sysroff_print_dln_out (&dummy);
+      }
+      break;
+    case IT_hd_CODE:
+      {
+       struct IT_hd dummy;
+       sysroff_swap_hd_in (&dummy);
+       addrsize = dummy.afl;
+       sysroff_print_hd_out (&dummy);
+      }
+      break;
+    case IT_dar_CODE:
+      {
+       struct IT_dar dummy;
+       sysroff_swap_dar_in (&dummy);
+       sysroff_print_dar_out (&dummy);
+      }
+      break;
+    case IT_dsy_CODE:
+      {
+       struct IT_dsy dummy;
+       sysroff_swap_dsy_in (&dummy);
+       sysroff_print_dsy_out (&dummy);
+      }
+      break;
+    case IT_dfp_CODE:
+      {
+       struct IT_dfp dummy;
+       sysroff_swap_dfp_in (&dummy);
+       sysroff_print_dfp_out (&dummy);
+      }
+      break;
+    case IT_dso_CODE:
+      {
+       struct IT_dso dummy;
+       sysroff_swap_dso_in (&dummy);
+       sysroff_print_dso_out (&dummy);
+      }
+      break;
+    case IT_dpt_CODE:
+      {
+       struct IT_dpt dummy;
+       sysroff_swap_dpt_in (&dummy);
+       sysroff_print_dpt_out (&dummy);
+      }
+      break;
+    case IT_den_CODE:
+      {
+       struct IT_den dummy;
+       sysroff_swap_den_in (&dummy);
+       sysroff_print_den_out (&dummy);
+      }
+      break;
+    case IT_dbt_CODE:
+      {
+       struct IT_dbt dummy;
+       sysroff_swap_dbt_in (&dummy);
+       sysroff_print_dbt_out (&dummy);
+      }
+      break;
+    case IT_dty_CODE:
+      {
+       struct IT_dty dummy;
+       sysroff_swap_dty_in (&dummy);
+       sysroff_print_dty_out (&dummy);
+      }
+      break;
+    case IT_un_CODE:
+      {
+       struct IT_un dummy;
+       sysroff_swap_un_in (&dummy);
+       sysroff_print_un_out (&dummy);
+      }
+      break;
+    case IT_sc_CODE:
+      {
+       struct IT_sc dummy;
+       sysroff_swap_sc_in (&dummy);
+       sysroff_print_sc_out (&dummy);
+      }
+      break;
+    case IT_er_CODE:
+      {
+       struct IT_er dummy;
+       sysroff_swap_er_in (&dummy);
+       sysroff_print_er_out (&dummy);
+      }
+      break;
+    case IT_ed_CODE:
+      {
+       struct IT_ed dummy;
+       sysroff_swap_ed_in (&dummy);
+       sysroff_print_ed_out (&dummy);
+      }
+      break;
+    case IT_sh_CODE:
+      {
+       struct IT_sh dummy;
+       sysroff_swap_sh_in (&dummy);
+       sysroff_print_sh_out (&dummy);
+      }
+      break;
+    case IT_ob_CODE:
+      {
+       struct IT_ob dummy;
+       sysroff_swap_ob_in (&dummy);
+       sysroff_print_ob_out (&dummy);
+      }
+      break;
+    case IT_rl_CODE:
+      {
+       struct IT_rl dummy;
+       sysroff_swap_rl_in (&dummy);
+       sysroff_print_rl_out (&dummy);
+      }
+      break;
+    case IT_du_CODE:
+      {
+       struct IT_du dummy;
+       sysroff_swap_du_in (&dummy);
+
+       sysroff_print_du_out (&dummy);
+      }
+      break;
+    case IT_dus_CODE:
+      {
+       struct IT_dus dummy;
+       sysroff_swap_dus_in (&dummy);
+       sysroff_print_dus_out (&dummy);
+      }
+      break;
+    case IT_dul_CODE:
+      {
+       struct IT_dul dummy;
+       sysroff_swap_dul_in (&dummy);
+       sysroff_print_dul_out (&dummy);
+      }
+      break;
+    case IT_dss_CODE:
+      {
+       struct IT_dss dummy;
+       sysroff_swap_dss_in (&dummy);
+       sysroff_print_dss_out (&dummy);
+      }
+      break;
+    case IT_hs_CODE:
+      {
+       struct IT_hs dummy;
+       sysroff_swap_hs_in (&dummy);
+       sysroff_print_hs_out (&dummy);
+      }
+      break;
+    case IT_dps_CODE:
+      {
+       struct IT_dps dummy;
+       sysroff_swap_dps_in (&dummy);
+       sysroff_print_dps_out (&dummy);
+      }
+      break;
+    case IT_tr_CODE:
+      {
+       sysroff_swap_tr_in ();
+       sysroff_print_tr_out ();
+      }
+      break;
+    case IT_dds_CODE:
+      {
+       struct IT_dds dummy;
+       sysroff_swap_dds_in (&dummy);
+       sysroff_print_dds_out (&dummy);
+      }
+      break;
+    default:
+      printf ("GOT A %x\n", c);
+      return 0;
+      break;
+    }
+  return 1;
+}
+
+static int
+opt (x)
+     int x;
+{
+  return getone (x);
+}
+
+#if 0
+
+/* This is no longer used.  */
+
+static void
+unit_info_list ()
+{
+  while (opt (IT_un_CODE))
+    {
+      getone (IT_us_CODE);
+
+      while (getone (IT_sc_CODE))
+       getone (IT_ss_CODE);
+
+      while (getone (IT_er_CODE))
+       ;
+
+      while (getone (IT_ed_CODE))
+       ;
+    }
+}
+
+#endif
+
+#if 0
+
+/* This is no longer used.  */
+
+static void
+object_body_list ()
+{
+  while (getone (IT_sh_CODE))
+    {
+      while (getone (IT_ob_CODE))
+       ;
+      while (getone (IT_rl_CODE))
+       ;
+    }
+}
+
+#endif
+
+static void
+must (x)
+     int x;
+{
+  if (!getone (x))
+    {
+      printf ("WANTED %x!!\n", x);
+    }
+}
+
+static void
+tab (i, s)
+     int i;
+     char *s;
+{
+  indent += i;
+  if (s)
+    {
+      p ();
+      printf (s);
+      printf ("\n");
+    }
+}
+
+static void derived_type ();
+
+static void
+dump_symbol_info ()
+{
+  tab (1, "SYMBOL INFO");
+  while (opt (IT_dsy_CODE))
+    {
+      if (opt (IT_dty_CODE))
+       {
+         must (IT_dbt_CODE);
+         derived_type ();
+         must (IT_dty_CODE);
+       }
+    }
+  tab (-1, "");
+}
+
+static void
+derived_type ()
+{
+  tab (1, "DERIVED TYPE");
+  while (1)
+    {
+      if (opt (IT_dpp_CODE))
+       {
+         dump_symbol_info ();
+         must (IT_dpp_CODE);
+       }
+      else if (opt (IT_dfp_CODE))
+       {
+         dump_symbol_info ();
+         must (IT_dfp_CODE);
+       }
+      else if (opt (IT_den_CODE))
+       {
+         dump_symbol_info ();
+         must (IT_den_CODE);
+       }
+      else if (opt (IT_den_CODE))
+       {
+         dump_symbol_info ();
+         must (IT_den_CODE);
+       }
+      else if (opt (IT_dds_CODE))
+       {
+         dump_symbol_info ();
+         must (IT_dds_CODE);
+       }
+      else if (opt (IT_dar_CODE))
+       {
+       }
+      else if (opt (IT_dpt_CODE))
+       {
+       }
+      else if (opt (IT_dul_CODE))
+       {
+       }
+      else if (opt (IT_dse_CODE))
+       {
+       }
+      else if (opt (IT_dot_CODE))
+       {
+       }
+      else
+       break;
+    }
+
+  tab (-1, "");
+}
+
+#if 0
+
+/* This is no longer used.  */
+
+static void
+program_structure ()
+{
+  tab (1, "PROGRAM STRUCTURE");
+  while (opt (IT_dps_CODE))
+    {
+      must (IT_dso_CODE);
+      opt (IT_dss_CODE);
+      dump_symbol_info ();
+      must (IT_dps_CODE);
+    }
+  tab (-1, "");
+}
+
+#endif
+
+#if 0
+
+/* This is no longer used.  */
+
+static void
+debug_list ()
+{
+  tab (1, "DEBUG LIST");
+
+  must (IT_du_CODE);
+  opt (IT_dus_CODE);
+  program_structure ();
+  must (IT_dln_CODE);
+
+  tab (-1, "");
+}
+
+#endif
+
+static void
+module ()
+{
+  int c = 0;
+  int l = 0;
+
+  tab (1, "MODULE***\n");
+
+  do
+    {
+      c = getc (file);
+      ungetc (c, file);
+
+      c &= 0x7f;
+    }
+  while (getone (c) && c != IT_tr_CODE);
+
+#if 0
+  must (IT_cs_CODE);
+  must (IT_hd_CODE);
+  opt (IT_hs_CODE);
+
+  unit_info_list ();
+  object_body_list ();
+  debug_list ();
+
+  must (IT_tr_CODE);
+#endif
+  tab (-1, "");
+
+  c = getc (file);
+  while (c != EOF)
+    {
+      printf ("%02x ", c);
+      l++;
+      if (l == 32)
+       {
+         printf ("\n");
+         l = 0;
+       }
+      c = getc (file);
+    }
+}
+
+char *program_name;
+
+static void
+show_usage (file, status)
+     FILE *file;
+     int status;
+{
+  fprintf (file, _("Usage: %s [-hV] in-file\n"), program_name);
+  exit (status);
+}
+
+static void
+show_help ()
+{
+  printf (_("%s: Print a human readable interpretation of a SYSROFF object file\n"),
+         program_name);
+  show_usage (stdout, 0);
+}
+
+int
+main (ac, av)
+     int ac;
+     char **av;
+{
+  char *input_file = NULL;
+  int opt;
+  static struct option long_options[] =
+  {
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {NULL, no_argument, 0, 0}
+  };
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = av[0];
+  xmalloc_set_program_name (program_name);
+
+  while ((opt = getopt_long (ac, av, "hV", long_options, (int *) NULL)) != EOF)
+    {
+      switch (opt)
+       {
+       case 'h':
+         show_help ();
+         /*NOTREACHED*/
+       case 'V':
+         printf (_("GNU %s version %s\n"), program_name, PROGRAM_VERSION);
+         exit (0);
+         /*NOTREACHED*/
+       case 0:
+         break;
+       default:
+         show_usage (stderr, 1);
+         /*NOTREACHED*/
+       }
+    }
+
+  /* The input and output files may be named on the command line.  */
+
+  if (optind < ac)
+    {
+      input_file = av[optind];
+    }
+
+  if (!input_file)
+    {
+      fprintf (stderr, _("%s: no input file specified\n"),
+              program_name);
+      exit (1);
+    }
+
+  file = fopen (input_file, FOPEN_RB);
+  if (!file)
+    {
+      fprintf (stderr, _("%s: cannot open input file %s\n"),
+              program_name, input_file);
+      exit (1);
+    }
+
+  module ();
+  return 0;
+}
diff --git a/binutils/sysinfo.y b/binutils/sysinfo.y
new file mode 100644 (file)
index 0000000..0aa8737
--- /dev/null
@@ -0,0 +1,415 @@
+%{
+#include <stdio.h>
+#include <stdlib.h>
+
+extern char *word;
+extern char writecode;
+extern int number;
+extern int unit;
+char nice_name[1000];
+char *it;
+int sofar;
+int width;
+int code;
+char * repeat;
+char *oldrepeat;
+char *name;
+int rdepth;
+char *loop [] = {"","n","m","/*BAD*/"};
+char *names[] = {" ","[n]","[n][m]"};
+char *pnames[]= {"","*","**"};
+%}
+
+
+%union {
+ int i;
+ char *s;
+} 
+%token COND
+%token REPEAT
+%token '(' ')'
+%token <s> TYPE
+%token <s> NAME
+%token <i> NUMBER UNIT
+%type <i> attr_size 
+%type <s> attr_desc attr_id attr_type
+%%
+
+top:  {
+  switch (writecode)
+    {
+    case 'i':
+      printf("#ifdef SYSROFF_SWAP_IN\n");
+      break; 
+    case 'p':
+      printf("#ifdef SYSROFF_p\n");
+      break; 
+    case 'd':
+      break;
+    case 'g':
+      printf("#ifdef SYSROFF_SWAP_OUT\n");
+      break;
+    case 'c':
+      printf("#ifdef SYSROFF_PRINT\n");
+      printf("#include <stdio.h>\n");
+      printf("#include <stdlib.h>\n");
+      break;
+    }
+ } 
+it_list {
+  switch (writecode) {
+  case 'i':
+  case 'p':
+  case 'g':
+  case 'c':
+    printf("#endif\n");
+    break; 
+  case 'd':
+    break;
+  }
+}
+
+  ;
+
+
+it_list: it it_list
+  |
+  ;
+
+it:
+       '(' NAME NUMBER 
+      {
+       it = $2; code = $3;
+       switch (writecode) 
+         {
+         case 'd':
+           printf("\n\n\n#define IT_%s_CODE 0x%x\n", it,code);
+           printf("struct IT_%s { \n", it);
+           break;
+         case 'i':
+           printf("void sysroff_swap_%s_in(ptr)\n",$2);
+           printf("struct IT_%s *ptr;\n", it);
+           printf("{\n");
+           printf("char raw[255];\n");
+           printf("\tint idx = 0 ;\n");
+           printf("\tint size;\n");
+           printf("memset(raw,0,255);\n");     
+           printf("memset(ptr,0,sizeof(*ptr));\n");
+           printf("size = fillup(raw);\n");
+           break;
+         case 'g':
+           printf("void sysroff_swap_%s_out(file,ptr)\n",$2);
+           printf("FILE * file;\n");
+           printf("struct IT_%s *ptr;\n", it);
+           printf("{\n");
+           printf("\tchar raw[255];\n");
+           printf("\tint idx = 16 ;\n");
+           printf("\tmemset (raw, 0, 255);\n");
+           printf("\tcode = IT_%s_CODE;\n", it);
+           break;
+         case 'o':
+           printf("void sysroff_swap_%s_out(abfd,ptr)\n",$2);
+           printf("bfd * abfd;\n");
+           printf("struct IT_%s *ptr;\n",it);
+           printf("{\n");
+           printf("int idx = 0 ;\n");
+           break;
+         case 'c':
+           printf("void sysroff_print_%s_out(ptr)\n",$2);
+           printf("struct IT_%s *ptr;\n", it);
+           printf("{\n");
+           printf("itheader(\"%s\", IT_%s_CODE);\n",$2,$2);
+           break;
+
+         case 't':
+           break;
+         }
+
+      } 
+       it_field_list 
+')'
+{
+  switch (writecode) {
+  case 'd': 
+    printf("};\n");
+    break;
+  case 'g':
+    printf("\tchecksum(file,raw, idx, IT_%s_CODE);\n", it);
+    
+  case 'i':
+
+  case 'o':
+  case 'c':
+    printf("}\n");
+  }
+}
+;
+
+
+
+it_field_list:
+               it_field it_field_list
+       |       cond_it_field it_field_list     
+       |       repeat_it_field it_field_list
+       |
+       ;
+
+repeat_it_field: '(' REPEAT NAME
+       {
+         rdepth++;
+         switch (writecode) 
+           {
+           case 'c':
+             if (rdepth==1)
+             printf("\tprintf(\"repeat %%d\\n\", %s);\n",$3);
+             if (rdepth==2)
+             printf("\tprintf(\"repeat %%d\\n\", %s[n]);\n",$3);
+           case 'i':
+           case 'g':
+           case 'o':
+
+             if (rdepth==1) 
+               {
+             printf("\t{ int n; for (n = 0; n < %s; n++) {\n",    $3);
+           }
+             if (rdepth == 2) {
+             printf("\t{ int m; for (m = 0; m < %s[n]; m++) {\n",    $3);
+           }           
+
+             break;
+           }
+
+         oldrepeat = repeat;
+         repeat = $3;
+       }
+
+        it_field_list ')' 
+
+       {
+         repeat = oldrepeat;
+         oldrepeat =0;
+         rdepth--;
+         switch (writecode)
+           {
+           case 'i':
+           case 'g':
+           case 'o':
+           case 'c':
+         printf("\t}}\n");
+       }
+       }
+       ;
+
+
+cond_it_field: '(' COND NAME
+       {
+         switch (writecode) 
+           {
+           case 'i':
+           case 'g':
+           case 'o':
+           case 'c':
+             printf("\tif (%s) {\n", $3);
+             break;
+           }
+       }
+
+        it_field_list ')' 
+       {
+         switch (writecode)
+           {
+           case 'i':
+           case 'g':
+           case 'o':
+           case 'c':
+         printf("\t}\n");
+       }
+       }
+       ;
+
+it_field:
+       '(' attr_desc '(' attr_type attr_size ')' attr_id 
+       {name = $7; } 
+       enums ')'
+       {
+         char *desc = $2;
+         char *type = $4;
+         int size = $5;
+         char *id = $7;
+char *p = names[rdepth];
+char *ptr = pnames[rdepth];
+         switch (writecode) 
+           {
+           case 'g':
+             if (size % 8) 
+               {
+                 
+                 printf("\twriteBITS(ptr->%s%s,raw,&idx,%d);\n",
+                        id,
+                        names[rdepth], size);
+
+               }
+             else {
+               printf("\twrite%s(ptr->%s%s,raw,&idx,%d,file);\n",
+                      type,
+                      id,
+                      names[rdepth],size/8);
+               }
+             break;          
+           case 'i':
+             {
+
+               if (rdepth >= 1)
+
+                 {
+                   printf("if (!ptr->%s) ptr->%s = (%s*)xcalloc(%s, sizeof(ptr->%s[0]));\n", 
+                          id, 
+                          id,
+                          type,
+                          repeat,
+                          id);
+                 }
+
+               if (rdepth == 2)
+                 {
+                   printf("if (!ptr->%s[n]) ptr->%s[n] = (%s**)xcalloc(%s[n], sizeof(ptr->%s[n][0]));\n", 
+                          id, 
+                          id,
+                          type,
+                          repeat,
+                          id);
+                 }
+
+             }
+
+             if (size % 8) 
+               {
+                 printf("\tptr->%s%s = getBITS(raw,&idx, %d,size);\n",
+                        id,
+                        names[rdepth], 
+                        size);
+               }
+             else {
+               printf("\tptr->%s%s = get%s(raw,&idx, %d,size);\n",
+                      id,
+                      names[rdepth],
+                      type,
+                      size/8);
+               }
+             break;
+           case 'o':
+             printf("\tput%s(raw,%d,%d,&idx,ptr->%s%s);\n", type,size/8,size%8,id,names[rdepth]);
+             break;
+           case 'd':
+             if (repeat) 
+               printf("\t/* repeat %s */\n", repeat);
+
+                 if (type[0] == 'I') {
+                 printf("\tint %s%s; \t/* %s */\n",ptr,id, desc);
+               }
+                 else if (type[0] =='C') {
+                 printf("\tchar %s*%s;\t /* %s */\n",ptr,id, desc);
+               }
+             else {
+               printf("\tbarray %s%s;\t /* %s */\n",ptr,id, desc);
+             }
+                 break;
+               case 'c':
+             printf("tabout();\n");
+                 printf("\tprintf(\"/*%-30s*/ ptr->%s = \");\n", desc, id);
+
+                 if (type[0] == 'I')
+                 printf("\tprintf(\"%%d\\n\",ptr->%s%s);\n", id,p);
+                 else   if (type[0] == 'C')
+                 printf("\tprintf(\"%%s\\n\",ptr->%s%s);\n", id,p);
+
+                 else   if (type[0] == 'B') 
+                   {
+                 printf("\tpbarray(&ptr->%s%s);\n", id,p);
+               }
+             else abort();
+                 break;
+               }
+       }
+
+       ;
+
+
+attr_type:     
+        TYPE { $$ = $1; }
+       |  { $$ = "INT";}
+       ;
+
+attr_desc: 
+       '(' NAME ')'    
+       { $$ = $2; }
+       ;
+
+attr_size:
+        NUMBER UNIT 
+       { $$ = $1 * $2; }
+       ;
+
+
+attr_id:
+               '(' NAME ')'    { $$ = $2; }
+       |       { $$ = "dummy";}
+       ;       
+       
+enums: 
+       | '(' enum_list ')' ;
+
+enum_list:
+       |
+       enum_list '(' NAME NAME ')' { 
+         switch (writecode) 
+           {
+           case 'd':
+             printf("#define %s %s\n", $3,$4);
+             break;
+           case 'c':
+               printf("if (ptr->%s%s == %s) { tabout(); printf(\"%s\\n\");}\n", name, names[rdepth],$4,$3);
+           }
+       }
+
+       ;
+
+
+
+%%
+/* four modes
+
+   -d write structure defintions for sysroff in host format
+   -i write functions to swap into sysroff format in
+   -o write functions to swap into sysroff format out
+   -c write code to print info in human form */
+
+int yydebug;
+char writecode;
+
+int 
+main(ac,av)
+int ac;
+char **av;
+{
+  yydebug=0;
+  if (ac > 1)
+    writecode = av[1][1];
+if (writecode == 'd')
+  {
+    printf("typedef struct { unsigned char *data; int len; } barray; \n");
+    printf("typedef  int INT;\n");
+    printf("typedef  char * CHARS;\n");
+
+  }
+  yyparse();
+return 0;
+}
+
+int
+yyerror(s)
+     char *s;
+{
+  fprintf(stderr, "%s\n" , s);
+  return 0;
+}
diff --git a/binutils/syslex.l b/binutils/syslex.l
new file mode 100644 (file)
index 0000000..a394842
--- /dev/null
@@ -0,0 +1,51 @@
+%{
+#include "sysinfo.h"
+char *word;
+int number;
+int unit;
+
+#ifndef yywrap
+static int yywrap () { return 1; }
+#endif
+%}
+%%
+"(" { return '(';}
+")" { return ')';}
+"[" { return '[';}
+"]" { return ']';}
+" " { ; }
+";".* { ; } 
+"\t" { ; }
+"\n" { ; }
+"\""[^\"]*"\"" {
+yylval.s = malloc(strlen (yytext));
+strcpy(yylval.s, yytext+1);
+yylval.s[strlen(yylval.s)-1] = 0;
+        return NAME;
+       }
+
+0x[0-9a-f]+ {
+        yylval.i = strtol(yytext,0,16);
+       return  NUMBER;
+       }
+
+[0-9]+ {
+        yylval.i = atoi(yytext);
+       return  NUMBER;
+       }
+
+
+"bits" { yylval.i =1 ;return UNIT;}
+"bit" { yylval.i = 1; return UNIT;}
+"bytes" { yylval.i= 8; return UNIT;}
+"byte" { yylval.i = 8; return UNIT;}
+
+"int" { yylval.s = "INT"; return TYPE;}
+"barray" { yylval.s = "BARRAY"; return TYPE;}
+"chars" { yylval.s = "CHARS"; return TYPE;}
+"variable" { yylval.i = 0; return NUMBER;}
+"counted" { yylval.i = -4; return NUMBER;}
+"addrsize" { yylval.i = -2; return NUMBER; }
+"segsize" { yylval.i = -1; return NUMBER; }
+"cond" { return COND;}
+"repeat" { return REPEAT;}
diff --git a/binutils/sysroff.info b/binutils/sysroff.info
new file mode 100644 (file)
index 0000000..3af001a
--- /dev/null
@@ -0,0 +1,504 @@
+("cs" 0x0
+ (("size") (1 byte) ("size"))
+
+ (("hd") (1 byte) ("hd"))
+ (("hs") (1 byte) ("hs"))
+ (("un") (1 byte) ("un"))
+ (("us") (1 byte) ("us"))
+
+ (("sc") (1 byte) ("sc"))
+ (("ss") (1 byte) ("ss"))
+ (("er") (1 byte) ("er"))
+ (("ed") (1 byte) ("ed"))
+
+ (("sh") (1 byte) ("sh"))
+ (("ob") (1 byte) ("ob"))
+ (("rl") (1 byte) ("rl"))
+ (("du") (1 byte) ("du"))
+
+ (("dps") (1 byte) ("dps"))
+ (("dsy") (1 byte) ("dsy"))
+ (("dty") (1 byte) ("dty"))
+ (("dln") (1 byte) ("dln"))
+
+ (("dso") (1 byte) ("dso"))
+ (("dus") (1 byte) ("dus"))
+ (("dss") (1 byte) ("dss"))
+ (("dbt") (1 byte) ("dbt"))
+
+ (("dpp") (1 byte) ("dpp"))
+ (("dfp") (1 byte) ("dfp"))
+ (("den") (1 byte) ("den"))
+ (("dds") (1 byte) ("dds"))
+
+ (("dar") (1 byte) ("dar"))
+ (("dpt") (1 byte) ("dpt"))
+ (("dul") (1 byte) ("dul"))
+ (("dse") (1 byte) ("dse"))
+
+ (("dot") (1 byte) ("dot")))
+
+
+("hd" 0x04
+ (("module type") (4 bits) ("mt")
+  (("MTYPE_ABS_LM"     "0")
+   ("MTYPE_REL_LM"     "1")
+   ("MTYPE_OMS_OR_LMS"         "2")
+   ("MTYPE_UNSPEC"     "0xf")))
+ (("spare")(4 bits) ("spare1"))
+ (("creation date")( chars 12 bytes)( "cd"))
+ (("number of units") (2 bytes) ("nu"))
+ (("code") (1 byte) ("code"))
+ (("version") (chars 4 bytes) ("ver"))
+ (("address update") (1 byte) ("au"))
+ (("segment identifier") (1 bit) ("si"))
+ (("address field length") (4 bits) ("afl"))
+ (("spare")(3 bits) ("spare2"))
+ (("space size within segment") (1 byte) ("spcsz"))
+ (("segment size")     (1 byte) ("segsz"))
+ (("segment shift")    (1 byte) ("segsh"))
+ (("entry point")      (1 byte) ("ep"))
+ (cond "ptr->ep"
+       (cond "ptr->mt != MTYPE_ABS_LM" 
+            (("unit appearance number") (2 bytes) ("uan"))
+            (("section appearance number") (2 bytes) ("sa")))
+       (cond "segmented_p"
+            (("segment address") (segsize bytes) ("sad")))
+       (("address") (addrsize bytes) ("address")))
+ (("os name") (chars variable bytes) ("os"))
+ (("sys name") (chars variable bytes) ("sys"))
+ (("module name") (chars variable bytes) ("mn"))
+ (("cpu") (chars variable bytes) ("cpu")))
+
+
+("hs" 0x05
+ (("neg number") (2 bytes) ("neg")))
+
+
+("un" 0x06
+ (("format") (2 bits) ("format")
+  (("FORMAT_LM" "0")
+   ("FORMAT_OM" "1")
+   ("FORMAT_OMS_OR_LMS" "2")))
+ (("spare") (6 bits) ("spare1"))
+ (("number of sections") (2 bytes) ("nsections"))
+ (("number of external refs") (2 bytes) ("nextrefs"))
+ (("number of external defs") (2 bytes) ("nextdefs"))
+ (("unit name") (chars variable byte) ("name"))
+ (("tool name") (chars variable byte) ("tool"))
+ (("creation date") (chars 12 bytes) ("tcd"))
+ (("linker name") (chars variable byte) ("linker"))
+ (("creation date") (chars 12 bytes) ("lcd")))
+
+
+("us" 0x07
+ (("negotiation number") (2 bytes) ("neg")))
+
+
+("sc" 0x08
+ (("format") (2 bits) ("format"))      
+ (("spare") (6 bits) ("spare"))
+ (("segment address") (segsize bytes) ("segadd"))
+ (("address") (addrsize bytes) ("addr"))
+ (("length") (addrsize bytes) ("length"))
+ (("alignment") (addrsize bytes) ("align"))
+ (("contents") (4 bits) ("contents")
+  (("CONTENTS_CODE" "0")
+   ("CONTENTS_DATA" "1")
+   ("CONTENTS_STACK" "2")
+   ("CONTENTS_DUMMY" "3")
+   ("CONTENTS_SPECIAL" "4")
+   ("CONTENTS_NONSPEC" "0xf")))
+ (("concat") (4 bits) ("concat")
+  (("CONCAT_SIMPLE" "0")
+   ("CONCAT_SHAREDC" "1")
+   ("CONCAT_DUMMY" "2")
+   ("CONCAT_GROUP" "3")
+   ("CONCAT_SHARED" "4")
+   ("CONCAT_PRIVATE" "5")
+   ("CONCAT_UNSPEC" "0xf")))
+ (("read") (2 bits) ("read"))
+ (("write") (2 bits) ("write"))
+ (("exec") (2 bits) ("exec"))
+ (("initialized") (2 bits) ("init"))
+ (("mode") (2 bits) ("mode"))
+ (("spare") (6 bits) ("spare1"))
+ (("name") (chars variable byte) ("name")))
+
+
+("ss" 0x09
+ (("neg number") (2 bytes) ("neg")))
+
+       
+("er" 0x0c
+ (("symbol type") (2 bits) ("type")
+  (("ER_ENTRY" "0")
+   ("ER_DATA" "1")
+   ("ER_NOTDEF" "2")
+   ("ER_NOTSPEC" "3")))
+ (("spare") (6 bits) ("spare"))
+ (("symbol name") (chars variable byte) ("name")))
+       
+
+("ed" 0x14
+ (("section appearance number") (2 bytes) ("section"))
+ (("symbol type") (3 bits) ("type")
+  (("ED_TYPE_ENTRY" "0")
+   ("ED_TYPE_DATA" "1")
+   ("ED_TYPE_CONST" "2")
+   ("ED_TYPE_NOTSPEC" "7")))
+ (("spare") (5 bits) ("spare"))
+ (cond "ptr->type==ED_TYPE_ENTRY || ptr->type==ED_TYPE_DATA"
+       (("symbol address") (addrsize bytes) ("address")))
+ (cond "ptr->type==ED_TYPE_CONST"
+       (("constant value") (addrsize bytes) ("constant")))
+ (("symbol name") (chars variable byte) ("name")))
+
+
+("sh" 0x1a
+ (("unit appearance number") (2 bytes) ("unit"))
+ (("section appearance number") (2 bytes) ("section")))
+
+
+("ob" 0x1c
+ (("starting address flag") (1 bit) ("saf"))
+ (("compression flag") (1 bit) ("cpf"))
+ (("spare") (6 bits) ("spare"))
+ (cond "ptr->saf"
+       ( ("starting address") (addrsize bytes) ("address")))
+ (cond "ptr->cpf"
+       (("comp reps") (addrsize bytes) ("compreps")))
+ (("data") (barray counted byte) ("data")))
+       
+
+("rl" 0x20
+ (("boundary of relocateable area") (4 bits) ("boundary"))
+ (("address polarity") (1 bit) ("apol"))
+ (("segment number") (1 bit) ("segment"))
+ (("sign of relocation") (1 bit) ("sign"))
+ (("check range") (1 bit) ("check"))
+ (("reloc address") (addrsize bytes) ("addr"))
+
+ (("bit loc") (1 byte) ("bitloc"))
+ (("field length") (1 byte) ("flen"))
+ (("bcount") (1 byte) ("bcount"))
+ (("operator") (1 byte) ("op")
+  (("OP_RELOC_ADDR" "1")
+   ("OP_SEC_REF" "0")
+   ("OP_EXT_REF" "2")))
+ (cond "ptr->op == OP_EXT_REF"
+       (("symbol number") (2 bytes) ("symn"))  )
+       
+ (cond "ptr->op == OP_SEC_REF"
+       (("section number") (2 bytes) ("secn"))
+       (("const opcode") (1 byte) ("copcode_is_3"))
+       (("addend length") (1 byte) ("alength_is_4"))
+       (("addend") (4 byte) ("addend"))
+       (("plus opcode") (1 byte) ("aopcode_is_0x20")))
+
+ (cond "ptr->op == OP_RELOC_ADDR"
+       (("dunno") (2 bytes) ("dunno")))
+
+ (("end")  (1 byte) ("end")))
+       
+
+("du" 0x30
+ (("format") (2 bits) ("format"))
+ (("optimized") (1 bit) ("optimized"))
+ (("stackfrmt") (2 bits) ("stackfrmt"))
+ (("spare") (3 bits) ("spare"))
+ (("unit number") (2 bytes) ("unit"))
+ (("sections") (2 bytes) ("sections"))
+ (repeat "ptr->sections"
+        (("section appearance number") (2 bytes) ("san"))
+        (("address") (addrsize bytes) ("address"))
+        (("section length") (addrsize bytes) ("length")))
+ (("tool name") (chars variable byte) ("tool"))
+ (("creation date") (chars 12 bytes) ("date")))
+
+
+("dsy" 0x34
+ (("symbol type") (7 bits) ("type")
+  (("STYPE_VAR" "0")
+   ("STYPE_LAB" "1")
+   ("STYPE_PROC" "2")
+   ("STYPE_FUNC" "3")
+   ("STYPE_TYPE" "4")
+   ("STYPE_CONST" "5")
+   ("STYPE_ENTRY" "6")
+   ("STYPE_MEMBER" "7")
+   ("STYPE_ENUM" "8")
+   ("STYPE_TAG" "9")
+   ("STYPE_PACKAGE" "10")
+   ("STYPE_GENERIC" "11")
+   ("STYPE_TASK" "12")
+   ("STYPE_EXCEPTION" "13")
+   ("STYPE_PARAMETER" "14")
+   ("STYPE_EQUATE" "15")
+   ("STYPE_UNSPEC" "0x7f")))
+ (("assignment info") (1 bit) ("assign"))
+ (("symbol id") (2 bytes) ("snumber"))
+ (("symbol name") (chars variable bytes) ("sname"))
+ (("nesting level") (2 bytes) ("nesting"))
+ (cond "ptr->assign"
+       (("assignment type") (1 byte)  ("ainfo")
+       (("AINFO_REG" "1")
+        ("AINFO_STATIC_EXT_DEF" "2")
+        ("AINFO_STATIC_EXT_REF" "3")
+        ("AINFO_STATIC_INT" "4")
+        ("AINFO_STATIC_COM" "5")
+        ("AINFO_AUTO" "6")
+        ("AINFO_CONST" "7")
+        ("AINFO_UNSPEC" "0xff")))
+       (("data length") (addrsize bytes) ("dlength"))
+       (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF
+            || ptr->ainfo == AINFO_STATIC_INT
+            || ptr->ainfo == AINFO_STATIC_COM"
+            (("section number")  (2 bytes) ("section")))
+       (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF
+            || ptr->ainfo == AINFO_STATIC_INT
+            || ptr->ainfo == AINFO_STATIC_COM
+            || ptr->ainfo == AINFO_AUTO"
+            (("address") (addrsize bytes) ("address")))
+       (cond "ptr->ainfo == AINFO_REG"
+            (("register name") (chars variable bytes) ("reg")))
+       (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF
+           || ptr->ainfo == AINFO_STATIC_EXT_REF"
+            (("external name") (chars variable bytes) ("ename")))
+       (cond "ptr->ainfo == AINFO_CONST"
+            (("constant") (chars variable bytes) ("constant"))))
+ (cond "ptr->type == STYPE_MEMBER"
+       (("assignment unit") (1 bit) ("bitunit"))
+       (("spare") (7 bits) ("spare2"))
+       (("field length") (addrsize bytes) ("field_len"))
+       (("field offset") (addrsize bytes) ("field_off"))
+       (cond "ptr->bitunit"
+            (("bit offset") (addrsize bytes) ("field_bitoff"))))
+ (cond "ptr->type== STYPE_ENUM"
+       (("value length") (1 byte) ("evallen"))
+       (("value") (4 bytes) ("evalue")))
+ (cond "ptr->type == STYPE_CONST"
+       (("value") (chars variable bytes) ("cvalue")))
+ (cond "ptr->type == STYPE_EQUATE"
+       (("value length") (1 byte) ("qvallen"))
+       (("value") (4 bytes) ("qvalue"))
+       (("basic type") (1 byte) ("btype"))
+       (("size information") (addrsize bytes) ("sizeinfo"))
+       (("sign") (2 bits) ("sign"))
+       (("floating point type") (6 bits) ("flt_type")))
+ (("source file number") (2 bytes) ("sfn"))
+ (("source line number") (2 bytes) ("sln"))
+ (("negotiation number") (2 bytes) ("neg"))
+ (cond "ptr->type == STYPE_TAG"
+       (("magic") (1 byte) ("magic"))))
+
+
+("dul" 0x52
+ (("max declaration type flag") (1 bit) ("max_variable"))
+ (("max spare") (7 bits) ("maxspare"))
+ (cond "ptr->max_variable == 0"
+       (("maximum") (addrsize bytes) ("max"))
+       (("max mode") (chars variable bytes) ("maxmode")))
+
+ (("min declaration type flag") (1 bit) ("min_variable"))
+ (("min spare") (7 bits) ("minspare"))
+ (cond "ptr->min_variable == 0"
+       (("minimum") (addrsize bytes) ("min"))
+       (("min mode") (chars variable bytes) ("minmode"))))
+
+
+("dty" 0x36
+ (("end flag") (1 bit) ("end"))
+ (("spare") (7 bits) ("spare"))
+ (cond "!ptr->end"
+       (("negotiation") (2 bytes) ("neg"))))
+
+
+("dbt" 0x44
+ (("basic type") (1 byte) ("btype")
+  (("BTYPE_VOID" "0")
+   ("BTYPE_UNDEF" "1")
+   ("BTYPE_CHAR" "2")
+   ("BTYPE_INT" "3")
+   ("BTYPE_FLOAT" "4")
+   ("BTYPE_BIT" "5")
+   ("BTYPE_STRING" "6")
+   ("BTYPE_DECIMAL" "7")
+   ("BTYPE_ENUM" "8")
+   ("BTYPE_STRUCT" "9")
+   ("BTYPE_TYPE" "10")
+   ("BTYPE_TAG" "11")
+   ("BTYPE_UNSPEC" "0xff")))
+ (("size info") (addrsize bytes) ("bitsize"))
+ (("sign") (2 bits) ("sign")
+  (("SIGN_SIGNED" "0")
+   ("SIGN_UNSIGNED" "1")
+   ("SIGN_UNSPEC" "3")))
+ (("floating point type") (6 bits) ("fptype")
+  (("FPTYPE_SINGLE" "0")
+   ("FPTYPE_DOUBLE" "1")
+   ("FPTYPE_EXTENDED" "2")
+   ("FPTYPE_NOTSPEC" "0x3f")))
+ (cond "ptr->btype==BTYPE_TAG || ptr->btype == BTYPE_TYPE"
+       (("symbol id") (2 bytes) ("sid")))
+ (("negotiation") (2 bytes) ("neg")))
+
+("dar" 0x4e
+ (("element length" ) (addrsize bytes) ("length"))
+ (("dims") (1 byte) ("dims"))
+ (repeat "ptr->dims"
+        (("variable flag") (1 bit) ("variable")
+         (("VARIABLE_FIXED" "0")
+          ("VARIABLE_VARIABLE" "1")))
+
+        (("subscript type") (1 bit) ("subtype")
+         (("SUB_INTEGER" "0")
+          ("SUB_TYPE"    "1")))
+
+        (("spare") (6 bits) ("spare"))
+
+        (cond "ptr->subtype[n] == SUB_TYPE"
+              (("sub symbol id") (2 bytes) ("sid")))
+
+        (cond "ptr->subtype[n] == SUB_INTEGER"
+              (("max declaration type flag") (1 bit) ("max_variable"))
+              (("max spare") (7 bits) ("maxspare"))
+              ;; FIXME: next field should be conditional on max_variable,
+              (("maximum") (addrsize bytes) ("max"))
+
+              (("min declaration type flag") (1 bit) ("min_variable"))
+              (("min spare") (7 bits) ("minspare"))
+              ;; FIXME: next field should be conditional on min_variable
+              (("minimum") (addrsize bytes) ("min"))))
+ (("negotiation") (2 bytes) ("neg")))
+
+              
+("dso" 0x3a
+ (("function name") (2 bytes) ("sid"))
+ (("sp update count") (4 bytes) ("spupdates"))
+ (repeat "ptr->spupdates"
+        (("update address") (addrsize bytes) ("address"))
+        (("offset") (addrsize bytes) ("offset"))))
+
+("dln" 0x38
+ (("number of lines") (2 bytes) ("nln"))
+ (repeat "ptr->nln"
+        (("source file number") (2 bytes) ("sfn"))
+        (("source line number") (2 bytes) ("sln"))
+        (("section number") (2 bytes) ("section"))
+        (("from address") (addrsize bytes) ("from_address"))
+        (("to address") (addrsize bytes) ("to_address"))
+        (("call count") (2 bytes) ("cc"))
+        )
+ (("neg") (2 bytes) ("neg")))
+("dpp" 0x46
+ (("start/end") (1 bit) ("end"))
+ (("spare") (7 bits) ("spare"))
+ (cond "!ptr->end"
+       (("params") (1 byte) ("params"))
+       (("neg number") (2 bytes) ("neg"))))
+
+("den" 0x4a
+ (("start/end") (1 bit) ("end"))
+ (("spare") (7 bits) ("spare"))
+ (cond "!ptr->end"
+       (("neg number") (2 bytes) ("neg"))))
+
+("dfp" 0x48
+ (("start/end flag") (1 bit) ("end"))
+ (("spare") (7 bits) ("spare"))
+ (cond "!ptr->end"
+       (("number of parameters") (1 byte) ("nparams"))
+       (("neg number") (2 bytes) ("neg"))))
+
+("dds" 0x4c
+ (("start/end") (1 bit) ("end"))
+ (("spare") (7 bits) ("spare"))
+ (cond "!ptr->end"
+       (("neg number") (2 bytes) ("neg"))))
+
+("dpt" 0x50
+ (("neg number") (2 bytes) ("neg"))
+ (("dunno") (1 byte) ("dunno")))
+
+("dse" 0x54
+ (("neg number") (2 bytes) ("neg"))
+ (("dunno") (1 byte) ("dunno")))
+
+("dot" 0x56
+ (("unknown") (1 byte) ("unknown")))
+; FIXME: unknown field should be repeated symbol number?
+
+
+("dss" 0x42
+ (("type") (1 byte) ("type"))
+ (("external/internal") (1 bit) ("internal"))
+ (("spare") (7 bits) ("spare"))
+ (cond "!ptr->internal"
+       (  ("package name") (chars variable byte) ("package")))
+ (cond "ptr->internal"
+       (("symbol id") (2 bytes) ("id")))
+ (("record type") (2 bytes) ("record"))
+ (("rules") (chars variable byte) ("rules"))
+ (("number of symbols") (2 bytes) ("nsymbols"))
+ (("unknown" ) (2 bytes) ("fixme")))
+     
+("pss" 0x40
+ (("negotiation number") (2 bytes) ("efn"))
+ (("number of source files") (2 bytes) ("ns"))
+ (repeat "ptr->ns"
+        (("directory reference bit") (1 bit) ("drb"))
+        (("spare") (7 bits) ("spare"))
+        (("completed file name") (chars variable byte) ("fname"))
+        (cond "ptr->drb[n]" 
+              (("directory apperance number") (2 bytes) ("dan"))))
+ (("number of directories") (2 bytes) ("ndir"))
+ (repeat "ptr->ndir"
+        (("directory name") (chars variable bytes) ("dname"))))
+
+
+; FIXME: the tr block has no contents. sysinfo, etc. aren't prepared 
+; to deal with that.
+; ("tr" 0x7f)
+
+
+("dus" 0x40
+ (("negotiation number") (2 bytes) ("efn"))
+ (("number of source files") (2 bytes) ("ns"))
+ (repeat "ptr->ns"
+        (("directory reference bit") (1 bit) ("drb"))
+        (("spare") (7 bits) ("spare"))
+        (("completed file name") (chars variable byte) ("fname"))
+        (cond "ptr->drb[n]" 
+              (("directory apperance number") (2 bytes) ("dan"))))
+ (("number of directories") (2 bytes) ("ndir"))
+ (repeat "ptr->ndir"
+        (("directory name") (chars variable bytes) ("dname"))))
+
+
+("dps" 0x32
+ (("start/end flag") (1 bit) ("end"))
+ (("block type") (7 bits) ("type")
+  (("BLOCK_TYPE_COMPUNIT" "0")
+   ("BLOCK_TYPE_PROCEDURE" "2")
+   ("BLOCK_TYPE_FUNCTION" "3")
+   ("BLOCK_TYPE_BLOCK" "4")
+   ("BLOCK_TYPE_BASIC" "9")))
+ (cond "!ptr->end"
+       (("optimization") (1 byte) ("opt"))
+       (("section number") (2 bytes) ("san"))
+       (("address") (addrsize bytes) ("address"))
+       (("block size") (addrsize bytes) ("block_size"))
+       (("nesting") (1 byte) ("nesting"))
+       (cond "ptr->type == BLOCK_TYPE_PROCEDURE 
+           || ptr->type == BLOCK_TYPE_FUNCTION"
+            (("return address") (1 bit) ("retaddr"))
+            (("interrupt function flag") (1 bit) ("intrflag"))
+            (("stack update flag") (1 bit) ("stackflag"))
+            (("intra page JMP") (1 bit) ("intrpagejmp"))
+            (("spare") (4 bits) ("spare")))
+       (("neg number") (2 bytes) ("neg"))))
+
diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog
new file mode 100644 (file)
index 0000000..15a0577
--- /dev/null
@@ -0,0 +1,585 @@
+1999-03-12  Nick Clifton  <nickc@cygnus.com>
+
+       * binutils-all/readelf.wi: Remove FR30 specific componnts.
+       * binutils-all/readelf.s: Remove RELA specific components.
+
+1999-02-16  Nick Clifton  <nickc@cygnus.com>
+
+       * binutils-all/readelf.s: Do not assume section alignment is 4.
+       * binutils-all/readelf.r: Do not assume rela's are being used. 
+       * binutils-all/readelf.exp: disable tests for non ELF based
+       targets.
+
+1999-02-02  Nick Clifton  <nickc@cygnus.com>
+
+       * binutils-all/readelf.wi: Amend to match new readelf output.
+       * binutils-all/readelf.r: Do not assume that RELAs will be used.
+
+1999-01-29  Nick Clifton  <nickc@cygnus.com>
+
+       * config/default.exp: Add definitions of READELF and READELFFLAGS.
+
+       * binutils-all/readelf.exp: New file: Readelf tests
+       * binutils-all/readelf.h: New file: Expected results for 'readelf -h'
+       * binutils-all/readelf.s: New file: Expected results for 'readelf -S'
+       * binutils-all/readelf.ss: New file: Expected results for 'readelf -s'
+       * binutils-all/readelf.r: New file: Expected results for 'readelf -r'
+       * binutils-all/readelf.wi: New file: Expected results for 'readelf -wi'
+
+Wed Dec  9 19:11:39 1998  Jeffrey A Law  (law@cygnus.com)
+
+       * binutils-all/objcopy.exp (copy_executable): Expect comparison
+       failure for mips*-*-elf.
+
+Fri Oct 16 22:57:12 1998  Felix Lee  <flee@cygnus.com>
+
+       * binutils-all/objcopy.exp: fix "no symbols" message.
+
+Tue Jul 28 15:14:04 1998  Jeffrey A Law  (law@cygnus.com)
+
+       * binutils-all/objcopy.exp: Keep "main" and "_main" for strip with
+       saving symbol tests.  Look for either "main" or "_main" in the output
+       file.  Fix test for "no symbols" in the output file.
+
+1998-07-22  Vladimir N. Makarov  <vmakarov@cygnus.com>
+
+       * binutils-all/objcopy.exp: Polish output about fail for objcopy
+       (simple copy), strip with/without saving a symbol for object file
+       and executable.
+
+Wed Jul  1 16:27:40 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * binutils-all/objcopy.exp: ARM simple objcopy now passes.
+
+Wed Jun 24 09:20:21 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * binutils-all/objdump.exp: Look for '.data' rather than 'data'
+       when parsing output of objdump -h.
+       * binutils-all/size.exp: Look for '.data' rather than 'data' when
+       parsing output of size -A.
+
+1998-07-20  Vladimir N. Makarov  <vmakarov@cygnus.com>
+
+       * objcopy.exp: Two new tests - strip object file with saving a
+       symbol and strip executable file with saving a symbol.
+
+Fri May 29 14:50:24 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Don't xfail the simple objcopy test
+       when cross compiling.
+
+Thu Nov  6 14:32:37 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       * lib/utils-lib.exp: Temporary definition of target_assemble and
+       default_target_assemble so that testing can work with older
+       dejagnu versions.
+
+Wed Sep 24 12:09:15 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       * binutils-all/objcopy.exp(strip_executable): Make a new copy of
+       the executable being tested.
+
+Mon Sep 15 21:25:20 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       * binutils-all/objcopy.exp: Compile the executables to be tested
+       on the target with a status wrapper (as necessary).
+
+       * binutils-all/ar.exp: If testing on a remote host, don't bother
+       looking on the local host for the program being tested. Use the
+       correct filenames on the remote host.
+
+       * binutils-all/nm.exp: Ditto.
+
+       * binutils-all/size.exp: Ditto.
+
+       * binutils-all/objdump.exp: Ditto.
+       (cpus_expected): Add the target CPU to the regexp of CPUs to be
+       expected, if it's not already there.
+
+Thu Aug 28 09:57:27 1997  Doug Evans  <dje@canuck.cygnus.com>
+
+       * binutils-all/objdump.exp (cpus_expected): Add arc.
+
+Tue Aug  5 00:03:20 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * config/default.exp: Look for nm-new and strip-new.
+
+Tue Jun  3 17:12:54 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       * config/default.exp: Remove expect_before statement.
+
+       * binutils-all/objcopy.exp: Don't use global exec_output variable;
+       the output is returned from remote_load instead.
+
+Mon May 12 22:14:20 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       * binutils-all/objcopy.exp(strip_test): Tests that
+       fail to compile are untested, not unresolved.
+       (copy_setup): Ditto.
+
+       * lib/utils-lib.exp(default_binutils_assemble): Call
+       target_assemble instead of target_compile.
+
+Wed Apr 30 20:37:51 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       Changes to support multilib and remote hosted testing, along with
+       general cleanups and simplifications.
+
+       * lib/utils-lib.exp(binutil_version): Use remote_exec.
+       (default_binutils_run): Ditto.
+       (default_binutils_assemble): Remove first argument; call
+       target_compile to actually do the assembly.
+       (default_binutils_compile,default_binutils_remove,prune_warnings):
+       Delete.
+
+       * config/default.exp: Remove AS and ASFLAGS.
+       (binutils_compile,binutils_remove): Delete.
+       (binutils_assemble): Remove first argument.
+
+       * binutils-all/ar.exp: See if we're running the tests on
+       a remote host, and download/upload files as appropriate.
+       Replace calls to binutils_remove with remote_file. Replace
+       calls to binutils_compile with target_compile. Remove initial
+       argument to binutils_assemble. Use remote_load to execute
+       programs on the target.
+       * binutils-all/nm.exp: Ditto.
+       * binutils-all/objcopy.exp:  Ditto.
+       * binutils-all/objdump.exp:  Ditto.
+       * binutils-all/size.exp: Ditto.
+
+Mon Apr 14 12:36:41 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/ar.exp (long_filenames): Check for a file system
+       with a 14 character file name length limit.
+
+Tue Apr  1 09:52:15 1997  Jeffrey A Law  (law@cygnus.com)
+
+       * binutils-all/objdump.exp: Handle d10v.
+
+Fri Feb  7 16:45:34 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       * binutils-all/ar.exp: Use prune_warnings instead of
+       prune_system_crud.
+       * binutils-all/objcopy.exp: Ditto.
+
+Wed Jan 29 00:16:43 1997  Bob Manson  <manson@charmed.cygnus.com>
+
+       * binutils-all/nm.exp: Use / between $srcdir and $subdir.
+       * binutils-all/objcopy.exp: Ditto.
+       * binutils-all/objdump.exp: Ditto.
+       * binutils-all/size.exp: Ditto.
+       * binutils-all/hppa/objdump.exp: Ditto.
+       
+
+Wed Oct 16 22:57:59 1996  Jeffrey A Law  (law@cygnus.com)
+
+       * binutils-all/objdump.exp: Add mn10200 and mn10300 to expected
+       cpus list.
+
+Tue Oct  1 15:06:55 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * lib/utils-lib.exp (binutil_version): Fix for current version
+       printing.
+
+Sun Aug  4 22:25:40 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Fix end of line matching in srec tests
+       to work with TCL 7.5.
+
+Sat Jun 29 12:51:30 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Simple copy test works for i960 b.out
+       targets.
+
+Mon Jun 24 14:33:04 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: On OSF/1, the simple copy test will
+       succeed with gas, and fail with /bin/as, so mark it as an expected
+       failure only if it fails.
+
+Tue Mar 26 16:55:08 1996  Jeffrey A Law  (law@cygnus.com)
+
+       * binutils-all/objcopy.exp: No longer expect adjust-section-vma
+       test to fail for hppa*-*-proelf*.
+
+Mon Mar 11 08:25:14 1996  Jeffrey A Law  (law@cygnus.com)
+
+       * binutils-all/objdump.exp: Look for "$CODE$", not just "CODE".
+
+Wed Jan 31 11:55:13 1996  Jeffrey A Law  (law@cygnus.com)
+
+       * binutils-all/objcopy.exp: Expect adjust-section-vma tests to
+       fail for hppa*-*-proelf* targets.
+
+Thu Jan 25 13:53:04 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objdump.exp: Update for objdump -h format change.
+       * binutils-all/objcopy.exp: Likewise.
+
+Mon Jan 15 18:14:14 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Use the lma, not the vma, when testing
+       address adjustments.
+
+Fri Dec 15 16:31:55 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objdump.exp: Update objdump -i test for current
+       objdump output.
+
+Mon Nov 27 15:15:09 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Correct fail calls to always use the
+       same string as the pass call.
+
+Wed Nov 22 13:18:58 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * lib/utils-lib.exp (prune_system_crud): Discard -g -O warnings
+       from native compilers on OSF/1 and SunOS.
+
+Fri Nov 17 10:36:09 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * lib/utils-lib.exp (default_binutils_compiler: Change error
+       message to say compilation rather than assembly.
+
+Wed Nov 15 18:34:42 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       * binutils-all/objcopy.exp: Simple copy test does appear to work
+       on i*86-svr4.
+
+Wed Nov 15 12:19:28 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: If assembly fails, call unresolved.
+       Test running objcopy and strip on a final executable.
+       * binutils-all/testprog.c: New file.
+       * config/default.exp (STRIP, STRIPFLAGS): Define.
+       (binutils_compile): New procedure.
+       * lib/utils-lib.exp (default_binutils_compile): New procedure.
+
+Fri Nov  3 13:22:33 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * lib/utils-lib.exp (default_binutils_run): Don't use verbose
+       -log, reverting part of Oct 2 change.
+
+Wed Nov  1 15:09:57 1995  Manfred Hollstein KS/EF4A 60/1F/110 #40283  <manfred@lts.sel.alcatel.de>
+
+       * binutils-all/objcopy.exp: Add setup_xfails for
+       m68*-motorola-sysv* and m88*-motorola-sysv*.
+
+Wed Oct  4 14:38:31 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/nm.exp: Add setup_xfails for XCOFF.
+
+Mon Oct  2 12:41:48 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/ar.exp: New file.
+       * binutils-all/bintest.s: Make text_symbol and data_symbol global.
+       Add new static symbols static_text_symbol and static_data_symbol.
+       * binutils-all/nm.exp: Adjust accordingly.
+       * config/default.exp (AR): Set if not set.
+       (binutils_remove): New procedure.
+       * lib/utils-lib.exp (default_binutils_run): Call
+       prune_system_crud on program output.  Use verbose -log instead of
+       both verbose and send_log.
+       (default_binutils_remove): New procedure.
+
+       * lib/utils-lib.exp (default_binutils_assemble): Call
+       prune_system_crud on assembler output.
+
+Tue Sep 26 14:07:05 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Add setup_xfails for simple copy test
+       for i386 COFF targets.
+
+Wed Sep 13 13:20:21 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * lib/utils-lib.exp (prune_system_crud): Define if not defined.
+       * binutils-all/objcopy.exp: Call prune_system_crud on cmp output.
+
+Sat Aug 19 17:38:06 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Add xfail for i*86-*-aout* for simple
+       copy test.
+
+Wed Aug 16 16:52:53 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/nm.exp: Add setup_xfail for mips*-sony-bsd* for
+       tests which fail on ECOFF targets.
+
+       * binutils-all/objcopy.exp: Change i*86-*-linux xfail for simple
+       copy test to check for i*86-*-linuxaout* instead.
+
+Tue Aug  8 17:48:37 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Add setup_xfail for a29k-*-vxworks*
+       for simple copy test.
+
+Tue Jul 25 11:57:12 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Change setup_xfail for simple copy
+       test from i960-*-vxworks5.1 to i960-*-vxworks*.
+
+Mon Jul 10 12:25:46 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Add setup_xfail for z8*-*-coff for
+       simple copy test.
+       * binutils-all/objdump.exp (cpus_expected): Add z8001 and z8002.
+
+Sun May 21 20:32:53 1995  Jeff Law  (law@snake.cs.utah.edu)
+
+       * binutils-all/hppa/objdump.exp (addendbug): Handle PA ELF targets
+       too.
+       * binutils-all/objcopy.exp (simple copy): Don't expect PA ELF
+       targets to fail.
+
+Tue Apr  4 14:52:08 1995  Jeff Law  (law@snake.cs.utah.edu)
+
+       * binutils-all/hppa: Renamed from binutils-hppa.
+
+Wed Mar 29 12:02:43 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Add setup_xfail for simple copy test
+       for h8500-*-hms and h8500-*-coff.
+
+Tue Mar 28 11:18:28 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Add setup_xfail for simple copy test
+       for m68*-ericsson-ose and m88*-*-coff.
+
+Mon Mar 27 11:27:31 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objcopy.exp: Add setup_xfail for simple copy test
+       for m68*-*-vxworks*.
+
+Fri Mar 24 11:44:25 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-hppa/objdump.exp: Correct hppa*-*-* check.
+
+Tue Mar 21 10:48:45 1995  Jeff Law  (law@snake.cs.utah.edu)
+
+       * binutils-hppa/addendbug.s: New testcase.
+       * binutils-hppa/objdump.exp: Run it.
+
+Mon Mar 20 11:31:05 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * lib/utils-lib.exp (default_binutils_run): Quote any dollar signs
+       in progargs before passing it to exec.
+
+Fri Mar 17 16:39:31 1995  Jeff Law  (law@snake.cs.utah.edu)
+
+       * config/hppa.sed: Sed script to transform bintest.s into proper
+       PA assembly code.
+       * binutils-all/nm.exp: Enable these tests on the PA.
+       * binutils-all/objcopy.exp: Enable these tests on the PA.  Expect
+       simple copy to fail.
+       * binutils-all/objdump.exp: Enable these tests on the PA.  Handle
+       "CODE" as a section name.
+       * binutils-all/size.exp: Enable these tests on the PA.
+       * lib/utils-lib.exp (default_binutils_assemble): For "hppa*-*-*",
+       run the assembly through a sed script before passing it to the
+       assembler.
+
+Wed Mar 15 16:47:13 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/objdump.exp: Force section sizes to be interpreted
+       in hex.  Change objdump -h failure mode to always use the same
+       string.
+
+Thu Jan  5 13:01:43 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * binutils-all/nm.exp: Just check for irix4*, rather than
+       irix\[0-4\]*, to avoid DejaGnu bug.
+
+Thu Dec 15 19:35:31 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * binutils-all/objcopy.exp: Expect simple-objcopy test to fail
+       for various other targets for which gas doesn't use bfd: sh-hms,
+       m68k-hpux, m68k-sunos, m68k-coff, i386-linux, a29k-udi, a29k-coff,
+       i960-vxworks5.1, i960-coff, h8300-hms, h8300-coff.
+
+Wed Dec 14 15:54:46 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * binutils-all/size.exp: Skip tests requiring bintest.o on hppa,
+       since it (correctly) generates syntax errors on that platform.
+       * binutils-all/objdump.exp: Ditto.
+       * binutils-all/nm.exp: Ditto.
+       * binutils-all/objcopy.exp: Ditto.  Also, move setup_xfail for
+       sh-coff to branch where objcopy execution produced no error
+       messages.  Expect failure for hp300 also.
+
+Thu Dec  8 14:36:15 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * binutils-all/objdump.exp (cpus_expected): New variable, taken
+       from objdump -i test, added ns32k and powerpc, sorted.
+       (objdump -i, -f tests): Use $cpus_expected.
+
+       * binutils-all/objcopy.exp: For simple-copy test, expect failure
+       for sh-coff.
+
+Tue Oct 25 16:00:14 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * binutils-all/objcopy.exp: Adjust --adjust-section-vma tests for
+       new S-record section handling.
+
+Tue Oct 18 11:18:21 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * binutils-all/nm.exp: nm with no arguments and nm -P do not work
+       as expected on ECOFF targets; add calls to setup_xfail.
+
+       * binutils-all/objcopy.exp: New file.
+       * config/default.exp: Initialize OBJCOPY and OBJCOPYFLAGS.
+
+Fri Oct 14 14:46:22 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       Rewrite testsuite.
+       * configure.in, Makefile.in: Remove.
+       * binutils-all/configure.in, binutils-all/Makefile.in: Remove.
+       * binutils-all/bintest.c: Remove.
+       * binutils-all/bintest.s: New file.
+       * binutils-all/nm.exp, binutils-all/objdump.exp: Rewrite.
+       * binutils-all/size.exp: Rewrite.
+       * config/default.exp: Load utils-lib.exp.  Set AS and ASFLAGS.
+       Don't go up one directory from $base_dir.  Create tmpdir.
+       (binutils_run, binutils-assemble): New procedures.
+       * config/unix.exp: Remove.
+       * config/mt-a29k-udi, config/mt-i386-aout: Remove.
+       * config/mt-i960-nindy, config/mt-lynx, config/mt-m68k: Remove.
+       * config/mt-mips-ecoff, config/mt-slite: Remove.
+       * config/mt-sparc-aout, config/mt-vxworks: Remove.
+       * lib/utils-lib.exp (binutil_version): Don't redirect standard
+       input when getting version.  Don't unset errorInfo.
+       (default_binutils_run): New procedure.
+       (default_binutils_assemble): New procedure.
+
+Thu Sep 29 12:45:39 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * VMS does not permit `.' in directory names: renamed binutils.all
+       to binutils-all.
+       * configure.in (configdirs): Change binutils.all to binutils-all.
+
+Fri Sep 23 16:01:14 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * configure.in: Use mt-m68k for m68k*-*-aout* and m68k*-*-coff*,
+       not for m68k-*-*.
+
+Fri Sep 23 13:54:50 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * binutils.all/objdump.exp: Added ARM to list of CPU types.
+
+Thu Sep 22 11:04:50 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * binutils.all/objdump.exp: Update for new usage message.
+       * binutils.all/size.exp: Use a double backslash in the string to
+       get a single backslash to the regexp matcher.  Accept $TEXT$,
+       $DATA$ and $BSS$ as well as .text, .data and .bss, for HP/UX.
+
+Fri Sep  2 12:53:10 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * config/unix.exp: If nm.new does not exist, use [transform nm].
+       * config/default.exp: Likewise.
+
+Wed Aug 24 12:41:37 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * configure.in, binutils.all/configure.in: Change i386 to
+       i[345]86.
+
+Tue Jul 19 15:23:53 1994  Bill Cox  (bill@rtl.cygnus.com)
+
+       * config/mt-mips-ecoff: Add -Tidp.ld option.
+
+Thu Jun 30 12:41:55 1994  J.T. Conklin  (jtc@phishhead.cygnus.com)
+
+       * config/default.exp: Use nm.new, not nm, from newly built tree.
+
+Tue May 17 14:04:05 1994  Bill Cox  (bill@rtl.cygnus.com)
+
+       * config/default.exp, config/unix.exp: Replace error
+         proc calls with perror.
+
+Tue May 10 11:20:54 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * configure.in (sparclite): Match on sparclite*-*-*.
+
+Wed Apr 13 18:25:19 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * config/unix.exp: Use nm.new, not nm, from newly built tree.
+
+       * binutils.all/objdump.exp: Add more wildcards to list of
+       single-letter options in pattern for usage message.
+
+       * binutils.all/nm.exp: Deleted debug-symbols test, since it only
+       works for a.out/stabs systems.  Fixed regexps to make underscores
+       optional, since some C compilers don't prepend them.  Deleted
+       check for foo.o symbol, since again some systems don't generate
+       it.
+
+Mon Apr 11 10:31:00 1994  Bill Cox  (bill@rtl.cygnus.com)
+
+       * Makefile.in (check): Set TCL_LIBRARY for runtest.
+
+Mon Feb 14 19:34:03 1994  Rob Savoye  (rob@darkstar.cygnus.com)
+
+       * Makefile.in: Use new config features of DejaGnu in site.exp
+       file. "Make check" should now work for all crosses.
+
+Fri Jan 28 18:00:29 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * binutils.all/objdump.exp: In usage message, accept
+       "section-name" as well as "section_name".
+
+Mon Jan 17 16:57:02 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * binutils.all/objdump.exp: Trim list of format names expected,
+       and accept any known CPU type.
+
+Thu Dec  2 20:50:24 1993  Rob Savoye  (rob@darkstar.cygnus.com)
+
+       * Makefile.in: Remove some stuff from the site.exp file.
+       * config/unix.exp: Add global before seeing if the variables for
+       nm, objdump, and size exist.
+
+Wed Nov  3 11:12:32 1993  Rob Savoye  (rob@darkstar.cygnus.com)
+
+       * config/udi.exp,unix.exp: Transform tool name.
+       * binutils.all/*.exp: Clear errorInfo after exec.
+
+Fri Jul  2 12:41:20 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * binutils.all/*.exp: Use -- for long arguments rather than +.
+
+Fri Jun  4 10:52:29 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * configure.in: change srctrigger to Makefile.in 
+
+Wed May 26 17:27:46 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in (FLAGS_TO_PASS): Pass down CC and CFLAGS.
+
+Fri May  7 13:58:44 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * binutils.all/objdump.exp: Update for new usage message.
+
+Mon Apr 19 14:08:52 1993  Rob Savoye  (rob@darkstar.cygnus.com)
+
+       * binutils.all/*.exp: Use the new util_test proc.
+       * Makefile.in: Create a local site.exp file with config info.
+
+Thu Mar 25 05:38:47 1993  Ken Raeburn  (raeburn@kr-pc.cygnus.com)
+
+       * nm.all/configure.in (srcname): Delete extra quote.
+
+Mon Feb 22 07:54:03 1993  Mike Werner  (mtw@poseidon.cygnus.com)
+
+        * binutils/testsuite: made modifications to testcases, etc., to allow
+        them to work properly  given the reorganization of deja-gnu and the
+        relocation of the testcases from deja-gnu to a "tool" subdirectory.
+
+Sun Feb 21 10:55:55 1993  Mike Werner  (mtw@poseidon.cygnus.com)
+
+       * binutils/testsuite: Initial creation of binutils/testsuite.
+       Migrated dejagnu testcases and support files for testing nm to
+       binutils/testsuite from deja-gnu.  These files were moved "as is"
+       with no modifications.  This migration is part of a major overhaul
+       of dejagnu.  The modifications to these testcases, etc., which
+       will allow them to work with the new version of dejagnu will be
+       made in a future update.
+
diff --git a/binutils/testsuite/binutils-all/ar.exp b/binutils/testsuite/binutils-all/ar.exp
new file mode 100644 (file)
index 0000000..4b38c6b
--- /dev/null
@@ -0,0 +1,219 @@
+#   Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# Written by Ian Lance Taylor <ian@cygnus.com>
+
+if ![is_remote host] {
+    if {[which $AR] == 0} then {
+        perror "$AR does not exist"
+        return
+    }
+}
+
+# send_user "Version [binutil_version $AR]"
+
+# Test long file name support
+
+proc long_filenames { } {
+    global AR
+    global host_triplet
+
+    set testname "ar long file names"
+
+    set n1 "abcdefghijklmnopqrstuvwxyz1"
+    set n2 "abcdefghijklmnopqrstuvwxyz2"
+    set file1 tmpdir/$n1
+    set file2 tmpdir/$n2
+
+    remote_file build delete $file1
+
+    # Some file systems truncate file names at 14 characters, which
+    # makes it impossible to run this test.  Check for that now.
+    set status [catch "set f [open tmpdir/$n1 w]" errs]
+    if { $status != 0 } {
+       verbose -log "open tmpdir/$n1 returned $errs"
+       unsupported $testname
+       return
+    }
+    puts $f "first"
+    close $f
+
+
+    remote_file build delete $file2
+
+    set status [catch "set f [open tmpdir/$n2 w]" errs]
+    if { $status != 0 } {
+       verbose -log "open tmpdir/$n2 returned $errs"
+       unsupported $testname
+       return
+    }
+    puts $f "second"
+    close $f
+
+    if [is_remote host] {
+       set file1 [remote_download host $file1];
+       set file2 [remote_download host $file2];
+       set dest artest.a
+    } else {
+       set dest tmpdir/artest.a
+    }
+
+    remote_file host delete $dest;
+
+    set got [binutils_run $AR "rc $dest $file1 $file2"]
+    if [is_remote host] {
+       remote_upload host $file1 tmpdir/$n1
+    }
+
+    set f [open tmpdir/$n1 r]
+    gets $f string
+    close $f
+    if ![string match "first" $string] {
+       verbose -log "reading tmpdir/$n1 returned $string"
+       unsupported $testname
+       return
+    }
+
+    remote_file host delete $dest;
+    set got [binutils_run $AR "rc $dest $file1 $file2"]
+
+    if ![string match "" $got] {
+       fail $testname
+       return
+    }
+
+    remote_file build delete tmpdir/$n1
+    remote_file build delete tmpdir/$n2
+
+    set got [binutils_run $AR "t $dest"]
+    regsub "\[\r\n \t\]*$" "$got" "" got;
+    if ![string match "$n1*$n2" $got] {
+       fail $testname
+       return
+    }
+    
+    if [is_remote host] {
+       remote_file host delete $file1;
+       remote_file host delete $file2;
+    }
+
+    verbose -log "$AR x $dest"
+    set exec_output [binutils_run $AR "x $dest"]
+    set exec_output [prune_warnings $exec_output]
+    if ![string match "" $exec_output] {
+       verbose -log $exec_output
+       fail $testname
+       return
+    }
+
+    if [is_remote host] {
+       remote_upload host $n1 tmpdir/$n1;
+       remote_upload host $n2 tmpdir/$n2;
+       set file1 tmpdir/$n1
+       set file2 tmpdir/$n2
+    } else {
+       set file1 $n1
+       set file2 $n2
+    }
+
+    if ![file exists $file1] {
+       verbose -log "$file1 does not exist"
+       fail $testname
+       return
+    }
+    if ![file exists $file2] {
+       verbose -log "$file2 does not exist"
+       fail $testname
+       return
+    }
+
+    set f [open $file1 r]
+    if { [gets $f line] == -1 || $line != "first" } {
+       verbose -log "$file1 contents:"
+       verbose -log "$line"
+       close $f
+       fail $testname
+       return
+    }
+    close $f
+
+    set f [open $file2 r]
+    if { [gets $f line] == -1 || $line != "second" } {
+       verbose -log "$file2 contents:"
+       verbose -log "$line"
+       close $f
+       fail $testname
+       return
+    }
+    close $f
+
+    pass $testname
+}
+
+# Test building the symbol table.
+
+proc symbol_table { } {
+    global AR
+    global AS
+    global NM
+    global srcdir
+    global subdir
+
+    set testname "ar symbol table"
+
+    if ![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o] {
+       unresolved $testname
+       return
+    }
+
+    if [is_remote host] {
+       set archive artest.a
+       set objfile [remote_download host tmpdir/bintest.o]
+       remote_file host delete $archive
+    } else {
+       set archive tmpdir/artest.a
+       set objfile tmpdir/bintest.o
+    }
+
+    remote_file build delete tmpdir/artest.a
+
+    set got [binutils_run $AR "rc $archive ${objfile}"]
+    if ![string match "" $got] {
+       fail $testname
+       return
+    }
+
+    set got [binutils_run $NM "--print-armap $archive"]
+    if { ![string match "*text_symbol in bintest.o*" $got] \
+        || ![string match "*data_symbol in bintest.o*" $got] \
+        || ![string match "*common_symbol in bintest.o*" $got] \
+        || [string match "*static_text_symbol in bintest.o*" $got] \
+        || [string match "*static_data_symbol in bintest.o*" $got] \
+        || [string match "*external_symbol in bintest.o*" $got] } {
+       fail $testname
+       return
+    }
+
+    pass $testname
+}
+
+# Run the tests.
+
+long_filenames
+symbol_table
diff --git a/binutils/testsuite/binutils-all/bintest.s b/binutils/testsuite/binutils-all/bintest.s
new file mode 100644 (file)
index 0000000..9e00650
--- /dev/null
@@ -0,0 +1,12 @@
+       .globl text_symbol
+       .text
+text_symbol:   
+static_text_symbol:
+       .long   1
+       .long   external_symbol
+       .globl data_symbol
+       .data
+data_symbol:
+static_data_symbol:
+       .long   2
+       .comm common_symbol,4
diff --git a/binutils/testsuite/binutils-all/hppa/addendbug.s b/binutils/testsuite/binutils-all/hppa/addendbug.s
new file mode 100644 (file)
index 0000000..659306f
--- /dev/null
@@ -0,0 +1,23 @@
+       .SPACE $PRIVATE$
+       .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31
+       .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82
+       .SPACE $TEXT$
+       .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
+       .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+       .IMPORT $global$,DATA
+       .IMPORT $$dyncall,MILLICODE
+; gcc_compiled.:
+       .SPACE $TEXT$
+       .SUBSPA $CODE$
+
+       .align 4
+       .EXPORT initialize_char_syntax,CODE
+       .EXPORT initialize_char_syntax,ENTRY,PRIV_LEV=3,RTNVAL=GR
+initialize_char_syntax
+       .PROC
+       .CALLINFO FRAME=64,NO_CALLS,SAVE_SP,ENTRY_GR=3
+       .ENTRY
+       addil L'is_idchar-$global$-32,%r27
+       .EXIT
+       .PROCEND
+is_idchar      .comm 256
diff --git a/binutils/testsuite/binutils-all/hppa/objdump.exp b/binutils/testsuite/binutils-all/hppa/objdump.exp
new file mode 100644 (file)
index 0000000..a46b289
--- /dev/null
@@ -0,0 +1,59 @@
+#   Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# This file was written by Rob Savoye <rob@cygnus.com>
+# and rewritten by Ian Lance Taylor <ian@cygnus.com>
+
+if ![istarget hppa*-*-*] then {
+  return
+}
+
+if {[which $OBJDUMP] == 0} then {
+    perror "$OBJDUMP does not exist"
+    return
+}
+
+send_user "Version [binutil_version $OBJDUMP]"
+
+if {![binutils_assemble $srcdir/$subdir/addendbug.s tmpdir/addendbug.o]} then {
+    return
+}
+
+if [is_remote host] {
+    set objfile [remote_download host tmpdir/addendbug.o]
+} else {
+    set objfile tmpdir/addendbug.o
+}
+
+# Make sure the SOM BFD code sign extends constants in R_DATA_OVERRIDE fixups.
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r $objfile"]
+
+if [istarget hppa*-*-*elf*] then {
+  set want "00000000 R_PARISC_DPREL21L\[       \]+is_idchar\\+0xffffffe0.*"
+} else {
+  set want "00000000 R_DP_RELATIVE\[   \]+is_idchar\\+0xffffffe0.*"
+}
+
+
+if [regexp $want $got] then {
+    pass "addendbug test"
+} else {
+    fail "addendbug test"
+}
diff --git a/binutils/testsuite/binutils-all/nm.exp b/binutils/testsuite/binutils-all/nm.exp
new file mode 100644 (file)
index 0000000..76c7c5f
--- /dev/null
@@ -0,0 +1,123 @@
+#   Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# This file was written by Rob Savoye <rob@cygnus.com>
+# and rewritten by Ian Lance Taylor <ian@cygnus.com>
+
+if ![is_remote host] {
+    if {[which $NM] == 0} then {
+        perror "$NM does not exist"
+        return
+    }
+}
+
+send_user "Version [binutil_version $NM]"
+
+
+if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
+    return
+}
+
+if [is_remote host] {
+    set tempfile [remote_download host tmpdir/bintest.o]
+} else {
+    set tempfile tmpdir/bintest.o
+}
+
+# Test nm with no arguments.
+
+# This test does not work correctly on ECOFF targets, because ECOFF
+# stores most symbols twice, which messes up the nm output.
+setup_xfail "alpha*-*-osf*" "alpha*-*-netware*"
+setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*"
+setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" "mips*-sony-bsd*"
+
+# This test does not work correctly on XCOFF targets, because XCOFF
+# does not enter static symbols in the symbol table.
+setup_xfail "*-*-aix*"
+
+set got [binutils_run $NM "$NMFLAGS $tempfile"]
+
+if [info exists vars] then { unset vars }
+while {[regexp "(\[a-zA-Z\]) (\[a-z_\]*_symbol)(.*)" $got all type symbol rest]} {
+    set vars($symbol) $type
+    set got $rest
+}
+
+if {![info exists vars(text_symbol)] \
+     || $vars(text_symbol) != "T" \
+     || ![info exists vars(data_symbol)] \
+     || $vars(data_symbol) != "D" \
+     || ![info exists vars(common_symbol)] \
+     || $vars(common_symbol) != "C" \
+     || ![info exists vars(external_symbol)] \
+     || $vars(external_symbol) != "U" \
+     || ![info exists vars(static_text_symbol)] \
+     || $vars(static_text_symbol) != "t" \
+     || ![info exists vars(static_data_symbol)] \
+     || $vars(static_data_symbol) != "d"} {
+    fail "nm (no arguments)"
+} else {
+    pass "nm (no arguments)"
+}
+
+# Test nm -g
+
+set got [binutils_run $NM "$NMFLAGS -g $tempfile"]
+
+if [info exists vars] then { unset vars }
+while {[regexp "(\[a-z_\]*_symbol)(.*)" $got all symbol rest]} {
+    set vars($symbol) 1
+    set got $rest
+}
+
+if {![info exists vars(text_symbol)] \
+     || ![info exists vars(data_symbol)] \
+     || ![info exists vars(common_symbol)] \
+     || ![info exists vars(external_symbol)] \
+     || [info exists vars(static_text_symbol)] \
+     || [info exists vars(static_data_symbol)]} {
+    fail "nm -g"
+} else {
+    pass "nm -g"
+}
+
+# Test nm -P
+
+# This test does not work correctly on ECOFF targets, because ECOFF
+# stores most symbols twice, which messes up the nm output.
+setup_xfail "alpha*-*-osf*" "alpha*-*-netware*"
+setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*"
+setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" "mips*-sony-bsd*"
+
+# This test does not work correctly on XCOFF targets, because XCOFF
+# does not enter static symbols in the symbol table.
+setup_xfail "*-*-aix*"
+
+set got [binutils_run $NM "$NMFLAGS -P $tempfile"]
+
+set want "common_symbol C \[0\]*4.*data_symbol D \[0-9a-fA-F\]*.*external_symbol U.*static_data_symbol d \[0-9a-fA-F\]*.*static_text_symbol t \[0-9a-fA-F\]*.*text_symbol T \[0-9a-fA-F\]*"
+
+if [regexp $want $got] then {
+    pass "nm -P"
+} else {
+    fail "nm -P"
+}
+
+# There are certainly other tests that could be run.
diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp
new file mode 100644 (file)
index 0000000..78972f1
--- /dev/null
@@ -0,0 +1,591 @@
+#   Copyright (C) 1994, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# Written by Ian Lance Taylor <ian@cygnus.com>
+
+if ![is_remote host] {
+    if {[which $OBJCOPY] == 0} then {
+        perror "$OBJCOPY does not exist"
+        return
+    }
+}
+
+send_user "Version [binutil_version $OBJCOPY]"
+
+if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
+    perror "unresolved 1"
+    unresolved "objcopy (simple copy)"
+    return
+}
+
+if ![is_remote host] {
+    set tempfile tmpdir/bintest.o;
+    set copyfile tmpdir/copy;
+} else {
+    set tempfile [remote_download host tmpdir/bintest.o]
+    set copyfile copy
+}
+
+# Test that objcopy does not modify a file when copying it.
+
+set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS $tempfile ${copyfile}.o"]
+
+if ![string match "" $got] then {
+    fail "objcopy (simple copy)"
+} else {
+    send_log "cmp $tempfile ${copyfile}.o\n"
+    verbose "cmp $tempfile ${copyfile}.o"
+    if [is_remote host] {
+       set src1 tmpdir/bintest.o
+       set src2 tmpdir/copy.o
+       remote_upload host $tempfile $src1;
+       remote_upload host ${copyfile}.o $src2;
+    } else {
+       set src1 ${tempfile}
+       set src2 ${copyfile}.o
+    }
+    set status [remote_exec build cmp "${src1} ${src2}"];
+    set exec_output [lindex $status 1];
+    set exec_output [prune_warnings $exec_output]
+
+    # On some systems the result of objcopy will not be identical.
+    # Usually this is just because gas isn't using bfd to write the files
+    # in the first place, and may order things a little differently.
+    # Those systems should use setup_xfail here.
+
+    setup_xfail "sh-*-coff" "sh-*-hms" 
+    setup_xfail "m68*-*-hpux*" "m68*-*-sunos*" "m68*-*-coff" "m68*-*-vxworks*"
+    setup_xfail "m68*-ericsson-ose" "m68k*-motorola-sysv*"
+    setup_xfail "i*86-*-linuxaout*" "i*86-*-aout*"
+    setup_xfail "i*86-*-sysv3" "i*86-*-isc*" "i*86-*-sco*" "i*86-*-coff"
+    setup_xfail "i*86-*-aix*" "i*86-*-go32*"
+    setup_xfail "a29k-*-udi" "a29k-*-coff" "a29k-*-vxworks*"
+    setup_xfail "i960-*-coff"
+    setup_xfail "h8300-*-hms" "h8300-*-coff"
+    setup_xfail "h8500-*-hms" "h8500-*-coff"
+    setup_xfail "hppa*-*-*"
+    clear_xfail "hppa*-*-*elf*"
+    setup_xfail "m88*-*-coff" "m88*-motorola-sysv*"
+    setup_xfail "z8*-*-coff"
+
+    if [string match "" $exec_output] then {
+       pass "objcopy (simple copy)"
+    } else {
+       send_log "$exec_output\n"
+       verbose "$exec_output" 1
+
+       # On OSF/1, this succeeds with gas and fails with /bin/as.
+       setup_xfail "alpha*-*-osf*"
+
+       # This fails for COFF i960-vxworks targets.
+       setup_xfail "i960-*-vxworks*"
+
+       fail "objcopy (simple copy)"
+    }
+}
+
+# Test generating S records.
+
+# We make the srec filename 8.3 compatible. Note that the header string
+# matched against depends on the name of the file. Ugh.
+
+if [is_remote host] {
+    set srecfile copy.sre
+    set header_string S00B0000636F70792E737265C1
+} else {
+    set srecfile ${copyfile}.srec
+    set header_string S0130000746D706469722F636F70792E7372656397
+}
+
+set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${srecfile}"]
+
+if ![string match "" $got] then {
+    fail "objcopy -O srec"
+} else {
+    if [is_remote host] {
+       remote_upload host ${srecfile} tmpdir/copy.srec;
+       set srecfile tmpdir/copy.srec;
+    }
+    set file [open ${srecfile} r]
+
+    # The first S record is fixed by the file name we are using.
+    gets $file line
+    send_log "$line\n"
+    verbose $line
+    if ![regexp "$header_string.*" $line] {
+       send_log "bad header\n"
+       fail "objcopy -O srec"
+    } else {
+       while {[gets $file line] != -1 \
+              && [regexp "^S\[123\]\[0-9a-fA-F\]+\[\r\n\]*$" $line]} {
+           send_log "$line\n"
+           verbose $line
+           set line "**EOF**"
+       }
+       send_log "$line\n"
+       verbose $line
+       if ![regexp "^S\[789\]\[0-9a-fA-F\]+\[\r\n\]*$" $line] then {
+           send_log "bad trailer\n"
+           fail "objcopy -O srec"
+       } else {
+           if {[gets $file line] != -1} then {
+               send_log "garbage at end\n"
+               send_log "$line\n"
+               verbose $line
+               fail "objcopy -O srec"
+           } else {
+               set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"]
+               if ![regexp "file format srec" $got] then {
+                   send_log "objdump failed\n"
+                   fail "objcopy -O srec"
+               } else {
+                   pass "objcopy -O srec"
+               }
+           }
+       }
+    }
+
+    close $file
+}
+
+# Test setting and adjusting the start address.  We only test this
+# while generating S records, because we may not be able to set the
+# start address for other object file formats, and the S record case
+# is the only useful one anyhow.
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $tempfile"]
+if ![regexp "start address (\[0-9a-fA-FxX\]+)" $got all origstart] then {
+    perror "objdump can not recognize bintest.o"
+    set origstart ""
+} else {
+    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec --set-start 0x7654"]
+    if ![string match "" $got] then {
+       fail "objcopy --set-start"
+    } else {
+       set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"]
+       if ![regexp "file format srec.*start address (\[0-9a-fA-FxX\]+)" $got all srecstart] then {
+           fail "objcopy --set-start"
+       } else {
+           if {$srecstart != 0x7654} then {
+               send_log "$srecstart != 0x7654\n"
+               fail "objcopy --set-start"
+           } else {
+               pass "objcopy --set-start"
+           }
+       }
+    }
+
+    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec --adjust-start 0x123"]
+    if ![string match "" $got] then {
+       fail "objcopy --adjust-start"
+    } else {
+       set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"]
+       if ![regexp "file format srec.*start address (\[0-9a-fA-FxX\]+)" $got all srecstart] then {
+           fail "objcopy --adjust-start"
+       } else {
+           if {$srecstart != $origstart + 0x123} then {
+               send_log "$srecstart != $origstart + 0x123\n"
+               fail "objcopy --adjust-start"
+           } else {
+               pass "objcopy --adjust-start"
+           }
+       }
+    }
+}
+
+# Test adjusting the overall VMA, and adjusting the VMA of a
+# particular section.  We again only test this when generating S
+# records.
+
+set low ""
+set lowname ""
+
+set headers [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h $tempfile"]
+
+set headers_regexp "\[         0-9\]+(\[^      \]+)\[  \]*(\[0-9a-fA-F\]+)\[   \]+\[0-9a-fA-F\]+\[     \]+(\[0-9a-fA-F\]+)\[   \]+\[0-9a-fA-F\]+\[     \]+2\[*\]\[*\]\[0-9\]+(.*)"
+
+set got $headers
+while {[regexp $headers_regexp $got all name size vma rest]} {
+    set vma 0x$vma
+    set size 0x$size
+    if {$size != 0} {
+       if {$low == "" || $vma < $low} {
+            set low $vma
+           set lowname $name
+       }
+    }
+    set got $rest
+}
+
+if {$low == "" || $origstart == ""} then {
+    perror "objdump can not recognize bintest.o"
+} else {
+    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec --adjust-vma 0x123"]
+    if ![string match "" $got] then {
+        fail "objcopy --adjust-vma"
+    } else {
+       set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -fh ${copyfile}.srec"]
+       set want "file format srec.*start address\[     \]*(\[0-9a-fA-FxX\]+).*sec1\[   \]+\[0-9a-fA-F\]+\[     \]+(\[0-9a-fA-F\]+)"
+       if ![regexp $want $got all start vma] then {
+           fail "objcopy --adjust-vma"
+       } else {
+           set vma 0x$vma
+           if {$vma != $low + 0x123} then {
+               send_log "$vma != $low + 0x123\n"
+               fail "objcopy --adjust-vma"
+           } else {
+               if {$start != $origstart + 0x123} then {
+                   send_log "$start != $origstart + 0x123\n"
+                   fail "objcopy --adjust-vma"
+               } else {
+                   pass "objcopy --adjust-vma"
+               }
+           }
+       }
+    }
+
+    set arg ""
+    set got $headers
+    while {[regexp $headers_regexp $got all name size vma rest]} {
+       set vma 0x$vma
+       if {$vma == $low} then {
+           set arg "$arg --adjust-section-vma $name+4"
+       }
+       set got $rest
+    }
+
+    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec $arg"]
+    if ![string match "" $got] then {
+       fail "objcopy --adjust-section-vma +"
+    } else {
+       set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h ${copyfile}.srec"]
+       set want "file format srec.*sec1\[      \]+\[0-9a-fA-F\]+\[     \]+(\[0-9a-fA-F\]+)"
+       if ![regexp $want $got all vma] then {
+           fail "objcopy --adjust-section-vma +"
+       } else {
+           set vma 0x$vma
+           if {$vma != $low + 4} then {
+               send_log "$vma != $low + 4\n"
+               fail "objcopy --adjust-section-vma +"
+           } else {
+               pass "objcopy --adjust-section-vma +"
+           }
+       }
+    }
+
+    regsub -all "\\+4" $arg "=[expr $low + 4]" argeq
+    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec $argeq"]
+    if ![string match "" $got] then {
+       fail "objcopy --adjust-section-vma ="
+    } else {
+       set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h ${copyfile}.srec"]
+       set want "file format srec.*sec1\[      \]+\[0-9a-fA-F\]+\[     \]+(\[0-9a-fA-F\]+)"
+       if ![regexp $want $got all vma] then {
+           fail "objcopy --adjust-section-vma ="
+       } else {
+           set vma 0x$vma
+           if {$vma != $low + 4} then {
+               send_log "$vma != $low + 4\n"
+               fail "objcopy --adjust-section-vma ="
+           } else {
+               pass "objcopy --adjust-section-vma ="
+           }
+       }
+    }
+}
+
+# Test stripping an object.
+
+proc strip_test { } {
+    global CC
+    global STRIP
+    global STRIPFLAGS
+    global NM
+    global NMFLAGS
+    global srcdir
+    global subdir
+
+    set test "strip"
+
+    if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } {
+       untested $test
+       return
+    }
+
+    if [is_remote host] {
+       set objfile [remote_download host tmpdir/testprog.o];
+    } else {
+       set objfile tmpdir/testprog.o
+    }
+
+    set exec_output [binutils_run $STRIP "$STRIPFLAGS $objfile"]
+    if ![string match "" $exec_output] {
+       fail $test
+       return
+    }
+
+    set exec_output [binutils_run $NM "-a $NMFLAGS $objfile"]
+    if ![string match "*: no symbols*" $exec_output] {
+       fail $test
+       return
+    }
+
+    pass $test
+}
+
+strip_test
+
+# Test stripping an object file with saving a symbol
+
+proc strip_test_with_saving_a_symbol { } {
+    global CC
+    global STRIP
+    global STRIPFLAGS
+    global NM
+    global NMFLAGS
+    global srcdir
+    global subdir
+
+    set test "strip with saving a symbol"
+
+    if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } {
+       untested $test
+       return
+    }
+
+    if [is_remote host] {
+       set objfile [remote_download host tmpdir/testprog.o];
+    } else {
+       set objfile tmpdir/testprog.o
+    }
+
+    set exec_output [binutils_run $STRIP "$STRIPFLAGS -K main -K _main $objfile"]
+    if ![string match "" $exec_output] {
+       fail $test
+       return
+    }
+
+    set exec_output [binutils_run $NM "$NMFLAGS $objfile"]
+    if {![regexp {^([0-9a-fA-F]+)?[ ]+T main} $exec_output] \
+         && ![regexp {^([0-9a-fA-F]+)?[ ]+T _main} $exec_output]} {
+       fail $test
+       return
+    }
+
+    pass $test
+}
+
+strip_test_with_saving_a_symbol
+
+# Build a final executable.
+
+proc copy_setup { } {
+    global srcdir
+    global subdir
+    
+    set res [build_wrapper testglue.o];
+    set flags { debug };
+    
+    if { $res != "" } {
+       lappend flags "additional_flags=[lindex $res 1]";
+       set add_libs "testglue.o";
+    } else {
+       set add_libs "";
+    }
+
+    if { [target_compile "$srcdir/$subdir/testprog.c $add_libs" tmpdir/testprog executable $flags]  != "" } {
+       return 2
+    }
+
+    set result [remote_load target tmpdir/testprog];
+    set status [lindex $result 0];
+
+    if { $status != "pass"  } {
+       perror "unresolved setup, status = $status"
+       return 3
+    }
+
+    return 0
+}
+
+# Test copying an executable.
+
+proc copy_executable { prog flags test1 test2 } {
+
+    if [is_remote host] {
+       set testfile [remote_download host tmpdir/testprog];
+       set testcopy copyprog
+    } else {
+       set testfile tmpdir/testprog
+       set testcopy tmpdir/copyprog
+    }
+    remote_file host delete $testcopy;
+
+    set exec_output [binutils_run $prog "$flags $testfile $testcopy"]
+
+    if ![string match "" $exec_output] {
+       fail $test1
+       fail $test2
+       return
+    }
+
+    if [is_remote host] {
+       remote_upload host $testcopy tmpdir/copyprog
+    }
+
+    set status [remote_exec build "cmp" "tmpdir/testprog tmpdir/copyprog"]
+    set exec_output [lindex $status 1];
+
+    if [string match "" $exec_output] then {
+       pass $test1
+    } else {
+       send_log "$exec_output\n"
+       verbose "$exec_output"
+
+       # This will fail for many reasons.  For example, it will most
+       # likely fail if a non-GNU linker is used.  Therefore, we do
+       # not insist that it pass.  If you are using an assembler and
+       # linker based on the same BFD as objcopy, it is worth
+       # investigating to see why this failure occurs.  If we are
+       # cross compiling, we assume that a GNU linker is being used,
+       # and expect it to succeed.
+       if {[isnative]} then {
+           setup_xfail "*-*-*"
+       }
+
+       # This also fails for mips*-*-elf targets.  See elf32-mips.c
+       # mips_elf_sym_is_global.
+       setup_xfail "mips*-*-elf"
+
+       fail $test1
+    }
+
+    set output [remote_load target tmpdir/copyprog]
+    set status [lindex $output 0];
+    if { $status != "pass" } {
+       fail $test2
+    } else {
+       pass $test2
+    }
+}
+
+# Test stripping an executable
+
+proc strip_executable { prog flags test } {
+    global NM
+    global NMFLAGS
+
+    remote_download build tmpdir/copyprog tmpdir/striprog
+    if [is_remote host] {
+       set copyfile [remote_download host tmpdir/striprog];
+    } else {
+       set copyfile tmpdir/striprog
+    }
+
+    set exec_output [binutils_run $prog "$flags ${copyfile}"]
+    if ![string match "" $exec_output] {
+       fail $test
+       return
+    }
+
+    if [is_remote host] {
+       remote_upload host ${copyfile} tmpdir/striprog;
+    }
+
+    set result [remote_load target tmpdir/striprog]
+    set status [lindex $result 0];
+    if { $status != "pass" } {
+       fail $test
+        return
+    }
+
+    set exec_output [binutils_run $NM "$NMFLAGS ${copyfile}"]
+    if ![string match "*: no symbols*" $exec_output] {
+       fail $test
+       return
+    }
+    pass $test
+}
+
+# Test stripping an executable with saving a symbol
+
+proc strip_executable_with_saving_a_symbol { prog flags test } {
+    global NM
+    global NMFLAGS
+
+    remote_download build tmpdir/copyprog tmpdir/striprog
+    if [is_remote host] {
+       set copyfile [remote_download host tmpdir/striprog];
+    } else {
+       set copyfile tmpdir/striprog
+    }
+
+    set exec_output [binutils_run $prog "$flags ${copyfile}"]
+    if ![string match "" $exec_output] {
+       fail $test
+       return
+    }
+
+    if [is_remote host] {
+       remote_upload host ${copyfile} tmpdir/striprog;
+    }
+
+    set result [remote_load target tmpdir/striprog]
+    set status [lindex $result 0];
+    if { $status != "pass" } {
+       fail $test
+        return
+    }
+
+    set exec_output [binutils_run $NM "$NMFLAGS ${copyfile}"]
+    if {![regexp {^[0-9a-fA-F]+ T main} $exec_output] \
+         && ![regexp {^[0-9a-fA-F]+ T _main} $exec_output]} {
+       fail $test
+       return
+    }
+    pass $test
+}
+
+set test1 "simple objcopy of executable"
+set test2 "run objcopy of executable"
+set test3 "run stripped executable"
+set test4 "run stripped executable with saving a symbol"
+
+switch [copy_setup] {
+    "1" {
+       # do nothing
+    }
+    "2" {
+       untested $test1
+       untested $test2
+       untested $test3
+       untested $test4
+    }
+    "3" {
+       unresolved $test1
+       unresolved $test2
+       unresolved $test3
+       unresolved $test4
+    }
+    "0" {
+       copy_executable "$OBJCOPY" "$OBJCOPYFLAGS" "$test1" "$test2"
+       strip_executable "$STRIP" "$STRIPFLAGS" "$test3"
+       strip_executable_with_saving_a_symbol "$STRIP" "-K main -K _main $STRIPFLAGS" "$test4"
+    }
+}
diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp
new file mode 100644 (file)
index 0000000..7c50f02
--- /dev/null
@@ -0,0 +1,140 @@
+#   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# This file was written by Rob Savoye <rob@cygnus.com>
+# and rewritten by Ian Lance Taylor <ian@cygnus.com>
+
+if ![is_remote host] {
+    if {[which $OBJDUMP] == 0} then {
+       perror "$OBJDUMP does not exist"
+       return
+    }
+}
+
+send_user "Version [binutil_version $OBJDUMP]"
+
+# Simple test of objdump -i
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"]
+
+set cpus_expected "(a29k|alliant|alpha|arc|arm|convex|d10v|d30v|h8|hppa|i386|i860|i960|m32r|m68k|m88k|mips|mn10200|mn10300|ns32k|powerpc|pyramid|romp|rs6000|sh|sparc|tahoe|v850|vax|we32k|z8k|z8001|z8002)"
+
+# Make sure the target CPU shows up in the list.
+if ![regexp $cpus_expected $target_cpu] {
+    regsub "^\[(\]" "$cpus_expected" "(${target_cpu}|" cpus_expected;
+}
+
+set want "BFD header file version.*srec.*header .* endian.*, data .* endian.*$cpus_expected"
+
+if [regexp $want $got] then {
+    pass "objdump -i"
+} else {
+    fail "objdump -i"
+}
+
+# The remaining tests require a test file.
+
+
+if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
+    return
+}
+if [is_remote host] {
+    set testfile [remote_download host tmpdir/bintest.o]
+} else {
+    set testfile tmpdir/bintest.o
+}
+
+# Test objdump -f
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $testfile"]
+
+set want "$testfile:\[         \]*file format.*architecture:\[         \]*${cpus_expected}.*HAS_RELOC.*HAS_SYMS"
+
+if ![regexp $want $got] then {
+    fail "objdump -f"
+} else {
+    pass "objdump -f"
+}
+
+# Test objdump -h
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h $testfile"]
+
+set want "$testfile:\[         \]*file format.*Sections.*\[0-9\]+\[    \]+\[^  \]*(text|TEXT|\\\$CODE\\\$)\[^  \]*\[   \]*(\[0-9a-fA-F\]+).*\[0-9\]+\[         \]+\[^  \]*(\\.data|DATA)\[^    \]*\[   \]*(\[0-9a-fA-F\]+)"
+
+if ![regexp $want $got all text_name text_size data_name data_size] then {
+    fail "objdump -h"
+} else {
+    verbose "text name is $text_name size is $text_size"
+    verbose "data name is $data_name size is $data_size"
+    if {[expr "0x$text_size"] < 8 || [expr "0x$data_size"] < 4} then {
+       send_log "sizes too small\n"
+       fail "objdump -h"
+    } else {
+       pass "objdump -h"
+    }
+}
+
+# Test objdump -t
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -t $testfile"]
+
+if [info exists vars] then { unset vars }
+while {[regexp "(\[a-z\]*_symbol)(.*)" $got all symbol rest]} {
+    set vars($symbol) 1
+    set got $rest
+}
+
+if {![info exists vars(text_symbol)] \
+     || ![info exists vars(data_symbol)] \
+     || ![info exists vars(common_symbol)] \
+     || ![info exists vars(external_symbol)]} then {
+    fail "objdump -t"
+} else {
+    pass "objdump -t"
+}
+
+# Test objdump -r
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r $testfile"]
+
+set want "$testfile:\[         \]*file format.*RELOCATION RECORDS FOR \\\[\[^\]\]*(text|TEXT|\\\$CODE\\\$)\[^\]\]*\\\].*external_symbol"
+
+if [regexp $want $got] then {
+    pass "objdump -r"
+} else {
+    fail "objdump -r"
+}
+
+# Test objdump -s
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -s $testfile"]
+
+set want "$testfile:\[         \]*file format.*Contents.*(text|TEXT|\\\$CODE\\\$)\[^0-9\]*\[   \]*\[0-9a-fA-F\]*\[     \]*(00000001|01000000).*Contents.*(data|DATA)\[^0-9\]*\[        \]*\[0-9a-fA-F\]*\[     \]*(00000002|02000000)"
+
+if [regexp $want $got] then {
+    pass "objdump -s"
+} else {
+    fail "objdump -s"
+}
+
+# Options which are not tested: -a -d -D -R -T -x -l --stabs
+# I don't see any generic way to test any of these other than -a.
+# Tests could be written for specific targets, and that should be done
+# if specific problems are found.
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
new file mode 100644 (file)
index 0000000..b2f744c
--- /dev/null
@@ -0,0 +1,217 @@
+#   Copyright (C) 1999 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# Written by Nick Clifto  <nickc@cygnus.com>
+# Based on scripts written by Ian Lance Taylor <ian@cygnus.com>
+# and Ken Raeburn <raeburn@cygnus.com>.
+
+# First some helpful procedures, then the tests themselves
+
+# Return the contents of the filename given
+proc file_contents { filename } {
+    set file [open $filename r]
+    set contents [read $file]
+    close $file
+    return $contents
+}
+
+# regexp_diff, based on simple_diff taken from ld test suite
+#      compares two files line-by-line
+#      file1 contains strings, file2 contains regexps and #-comments
+#      blank lines are ignored in either file
+#      returns non-zero if differences exist
+#
+proc regexp_diff { file_1 file_2 } {
+
+    set eof -1
+    set end_1 0
+    set end_2 0
+    set differences 0
+    set diff_pass 0
+
+    if [file exists $file_1] then {
+       set file_a [open $file_1 r]
+    } else {
+       warning "$file_1 doesn't exist"
+       return 1
+    }
+
+    if [file exists $file_2] then {
+       set file_b [open $file_2 r]
+    } else {
+       fail "$file_2 doesn't exist"
+       close $file_a
+       return 1
+    }
+
+    verbose " Regexp-diff'ing: $file_1 $file_2" 2
+
+    while { 1 } {
+       set line_a ""
+       set line_b ""
+       while { [string length $line_a] == 0 } {
+           if { [gets $file_a line_a] == $eof } {
+               set end_1 1
+               break
+           }
+       }
+       while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
+           if [ string match "#pass" $line_b ] {
+               set end_2 1
+               set diff_pass 1
+               break
+           }
+           if { [gets $file_b line_b] == $eof } {
+               set end_2 1
+               break
+           }
+       }
+
+        if { $diff_pass } { 
+            break 
+        } elseif { $end_1 && $end_2 } { 
+            break
+        } elseif { $end_1 } {
+            send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
+            verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
+            set differences 1
+            break
+        } elseif { $end_2 } {
+            send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
+            verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
+            set differences 1
+            break
+        } else {
+            verbose "regexp \"^$line_b$\"\nline   \"$line_a\"" 3
+            if ![regexp "^$line_b$" "$line_a"] {
+               send_log "regexp_diff match failure\n"
+               send_log "regexp \"^$line_b$\"\nline   \"$line_a\"\n"
+               set differences 1
+                break
+            }
+        }
+    }
+
+    if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
+       send_log "$file_1 and $file_2 are different lengths\n"
+       verbose "$file_1 and $file_2 are different lengths" 3
+       set differences 1
+    }
+
+    close $file_a
+    close $file_b
+
+    return $differences
+}
+
+# Run an individual readelf test.
+# Basically readelf is run on the binary_file with the given options.
+# Readelf's output is captured and then compared against the contents
+# of the regexp_file.
+
+proc readelf_test { options binary_file regexp_file xfails } {
+
+    global READELF
+    global READELFFLAGS
+    global srcdir
+    global subdir
+    
+    send_log "exec $READELF $READELFFLAGS $options $binary_file > readelf.out"
+    catch "exec $READELF $READELFFLAGS $options $binary_file > readelf.out" got
+
+    if { [llength $xfails] != 0 } then {
+       setup_xfail $xfails
+    }
+    
+    if ![string match "" $got] then {
+       send_log $got
+       fail "readelf $options"
+       return
+    }
+
+    if { [regexp_diff readelf.out $srcdir/$subdir/$regexp_file] } then {
+       fail "readelf $options"
+       verbose "output is \n[file_contents readelf.out]" 2
+       return
+    }
+
+    pass "readelf $options"
+}
+
+
+
+# Only ELF based toolchains need readelf.
+# For now be paranoid and assume that if ELF is not mentioned
+# in the target string, then the target is not an ELF based port.
+
+if ![istarget "*-*elf"] then {
+    verbose "$READELF is only intenteded for ELF targets" 2
+    return
+}
+
+if ![is_remote host] {
+    if {[which $READELF] == 0} then {
+        perror "$READELF does not exist"
+        return
+    }
+}
+
+send_user "Version [binutil_version $READELF]"
+
+# Assemle the test file.
+if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
+    perror "unresolved 1"
+    unresolved "readelf - failed to assemble"
+    return
+}
+
+if ![is_remote host] {
+    set tempfile tmpdir/bintest.o;
+} else {
+    set tempfile [remote_download host tmpdir/bintest.o]
+}
+
+# Run the tests
+readelf_test -h $tempfile readelf.h  {}
+
+# The v850 fails the next two tests because it creates two special
+# sections of its own: .call_table_data and .call_table_text
+# The regexp scripts are not expecting these sections...
+
+readelf_test -S $tempfile readelf.s  {v850*-*-*}
+readelf_test -s $tempfile readelf.ss {v850*-*-*}
+readelf_test -r $tempfile readelf.r  {}
+
+
+# Compile the second test file.
+if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } {
+    untested "readelf -w"
+    return
+}
+
+if [is_remote host] {
+    set tempfile [remote_download host tmpdir/testprog.o];
+} else {
+    set tempfile tmpdir/testprog.o
+}
+
+# The xfail targets here do not default to DWARF2 format debug information
+# The symptom is that the output of 'readelf -wi' is empty.
+
+readelf_test -wi $tempfile readelf.wi {v850*-*-*}
diff --git a/binutils/testsuite/binutils-all/readelf.h b/binutils/testsuite/binutils-all/readelf.h
new file mode 100644 (file)
index 0000000..555afe9
--- /dev/null
@@ -0,0 +1,16 @@
+ELF Header:
+  Magic:   7f 45 4c 46 0[12] 0[12] 01 00 00 00 00 00 00 00 00 00 
+  Type:                              REL \(Relocatable file\)
+  Machine:                           .*
+  Version:                           0x1
+  Data:                              ELFDATA.* endian\)
+  Entry point address:               0x0
+  Start of program headers:          0 \(bytes into file\)
+  Start of section headers:          .* \(bytes into file\)
+  Flags:                             .*
+  Size of this header:               .* \(bytes\)
+  Size of program headers:           0 \(bytes\)
+  Number of program headers:         0
+  Size of section headers:           .* \(bytes\)
+  Number of section headers:         .*
+  Section header string table index: .*
diff --git a/binutils/testsuite/binutils-all/readelf.r b/binutils/testsuite/binutils-all/readelf.r
new file mode 100644 (file)
index 0000000..4bea721
--- /dev/null
@@ -0,0 +1,4 @@
+
+Relocation section '.rel.*text' at offset 0x.* contains 1 entries:
+  Offset    Info  Type            Symbol's Value  Symbol's Name.*
+  00000004  00.* R_.*           00000000  external_symbol.*
diff --git a/binutils/testsuite/binutils-all/readelf.s b/binutils/testsuite/binutils-all/readelf.s
new file mode 100644 (file)
index 0000000..58b1245
--- /dev/null
@@ -0,0 +1,13 @@
+There are .* section headers, starting at offset .*:
+
+Section Headers:
+  \[Nr\] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
+  \[ 0\]                   NULL            00000000 000000 000000 00      0   0 0
+  \[ 1\] .text             PROGBITS        00000000 000034 000008 00  AX  0   0 .
+  \[ 2\] .rel.+text +REL. +0+ 0+.* 00000. 0.      .   1 4
+  \[ 3\] .data             PROGBITS        00000000 00003c 000004 00 WA   0   0 .
+  \[ 4\] .bss              NOBITS          00000000 000040 000000 00 WA   0   0 .
+  \[ 5\] .shstrtab         STRTAB          00000000 000040 0000.* 00      0   0 .
+  \[ 6\] .symtab           SYMTAB          00000000 0+.* 0+.* 10      7   6 4
+  \[ 7\] .strtab           STRTAB          00000000 0+.* 0+.* 00      0   0 1
+
diff --git a/binutils/testsuite/binutils-all/readelf.ss b/binutils/testsuite/binutils-all/readelf.ss
new file mode 100644 (file)
index 0000000..3760b38
--- /dev/null
@@ -0,0 +1,13 @@
+
+Symbol table '.symtab' contains .* entries:
+  Num:    Value  Size Type    Bind   Ot  Ndx Name
+    0:        0     0 NOTYPE  LOCAL   0  UND 
+    1:        0     0 SECTION LOCAL   0    1 
+    2:        0     0 SECTION LOCAL   0    3 
+    3:        0     0 SECTION LOCAL   0    4 
+    4:        0     0 NOTYPE  LOCAL   0    1 static_text_symbol
+    5:        0     0 NOTYPE  LOCAL   0    3 static_data_symbol
+    .:        0     0 NOTYPE  GLOBAL  0    1 text_symbol
+    .:        0     0 NOTYPE  GLOBAL  0  UND external_symbol
+   .*:        0     0 NOTYPE  GLOBAL  0    3 data_symbol
+   .*:        4     4 OBJECT  GLOBAL  0  COM common_symbol
diff --git a/binutils/testsuite/binutils-all/readelf.wi b/binutils/testsuite/binutils-all/readelf.wi
new file mode 100644 (file)
index 0000000..3cb2ecc
--- /dev/null
@@ -0,0 +1,78 @@
+The section .debug_info contains:
+
+  Compilation Unit:
+   Length:        .*
+   Version:       2
+   Abbrev Offset: 0
+   Pointer Size:  4
+    Abbrev Number: 1 \(DW_TAG_compile_unit\)
+     DW_AT_name        : .*/testprog.c 
+     DW_AT_comp_dir    : .*/binutils   
+     DW_AT_producer    : GNU C .*      
+     DW_AT_language    : 1     \(ANSI C\)
+     DW_AT_low_pc      : 0     
+     DW_AT_high_pc     : .*    
+     DW_AT_stmt_list   : 0     
+    Abbrev Number: 2 \(DW_TAG_subprogram\)
+     DW_AT_external    : 1     
+     DW_AT_name        : fn    
+     DW_AT_decl_file   : 1     
+     DW_AT_decl_line   : a     
+     DW_AT_type        : .*    
+     DW_AT_low_pc      : 0     
+     DW_AT_high_pc     : .*    
+     DW_AT_frame_base  : 1 byte block: .*
+    Abbrev Number: 3 \(DW_TAG_base_type\)
+     DW_AT_name        : int   
+     DW_AT_byte_size   : 4     
+     DW_AT_encoding    : 5     \(signed\)
+    Abbrev Number: 4 \(DW_TAG_subprogram\)
+     DW_AT_sibling     : .*    
+     DW_AT_external    : 1     
+     DW_AT_name        : main  
+     DW_AT_decl_file   : 1     
+     DW_AT_decl_line   : 10    
+     DW_AT_type        : .*    
+     DW_AT_low_pc      : .*    
+     DW_AT_high_pc     : .*    
+     DW_AT_frame_base  : 1 byte block: .*
+    Abbrev Number: 5 \(DW_TAG_lexical_block\)
+     DW_AT_low_pc      : .*    
+     DW_AT_high_pc     : .*    
+
+   Extra data at end of comp unit:
+ .*: Abbrev Number: 6 \(DW_TAG_variable\)
+     DW_AT_name        : common        
+     DW_AT_decl_file   : 1     
+     DW_AT_decl_line   : 3     
+     DW_AT_type        : .*
+     DW_AT_external    : 1     
+     DW_AT_location    : 5 byte block: 3 . 0 0 0       \(DW_OP_addr: 0\)
+ .*: Abbrev Number: 6 \(DW_TAG_variable\)
+     DW_AT_name        : global        
+     DW_AT_decl_file   : 1     
+     DW_AT_decl_line   : 4     
+     DW_AT_type        : .*    
+     DW_AT_external    : 1     
+     DW_AT_location    : 5 byte block: 3 . 0 0 0       \(DW_OP_addr: 0\)
+ .*: Abbrev Number: 7 \(DW_TAG_variable\)
+     DW_AT_name        : local 
+     DW_AT_decl_file   : 1     
+     DW_AT_decl_line   : 5     
+     DW_AT_type        : .*    
+     DW_AT_location    : 5 byte block: 3 . 0 0 .       \(DW_OP_addr: .\)
+ .*: Abbrev Number: 8 \(DW_TAG_array_type\)
+     DW_AT_sibling     : .*    
+     DW_AT_type        : .*    
+ .*: Abbrev Number: 9 \(DW_TAG_subrange_type\)
+     DW_AT_upper_bound : 6     
+ .*: Abbrev Number: 3 \(DW_TAG_base_type\)
+     DW_AT_name        : char  
+     DW_AT_byte_size   : 1     
+     DW_AT_encoding    : .     \(.* char\)
+ .*: Abbrev Number: 7 \(DW_TAG_variable\)
+     DW_AT_name        : string        
+     DW_AT_decl_file   : 1     
+     DW_AT_decl_line   : 6     
+     DW_AT_type        : .*    
+     DW_AT_location    : 5 byte block: 3 . 0 0 .       \(DW_OP_addr: .\)
diff --git a/binutils/testsuite/binutils-all/size.exp b/binutils/testsuite/binutils-all/size.exp
new file mode 100644 (file)
index 0000000..b908c91
--- /dev/null
@@ -0,0 +1,78 @@
+#   Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# This file was written by Rob Savoye <rob@cygnus.com>
+# and rewritten by Ian Lance Taylor <ian@cygnus.com>
+
+if ![is_remote host] {
+    if {[which $SIZE] == 0} then {
+       perror "$SIZE does not exist"
+       return
+    }
+}
+
+send_user "Version [binutil_version $SIZE]"
+
+
+if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then {
+    return
+}
+
+if [is_remote host] {
+    set testfile [remote_download host tmpdir/bintest.o]
+} else {
+    set testfile tmpdir/bintest.o
+}
+
+set dec "\[0-9\]+"
+set hex "\[0-9a-fA-F\]+"
+
+# Test size with no arguments
+
+set got [binutils_run $SIZE "$SIZEFLAGS $testfile"]
+
+set want "($dec)\[     \]+($dec)\[     \]+($dec)\[     \]+($dec)\[     \]+($hex)\[     \]+${testfile}"
+
+if ![regexp $want $got all text data bss dtot hextot] then {
+    fail "size (no arguments)"
+} else {
+    if {$text < 8 || $data < 4} then {
+       fail "size (no arguments)"
+    } else {
+       pass "size (no arguments)"
+    }
+}
+
+# Test size -A
+
+set got [binutils_run $SIZE "$SIZEFLAGS -A ${testfile}"]
+
+set want "${testfile}.*(text|TEXT)\[^\n\r\]*\[         \]($dec)\[      \]+$dec.*(\\.data|DATA)\[^\n\r\]*\[     \]($dec)\[      \]+$dec"
+
+if ![regexp $want $got all textname textsize dataname datasize] then {
+    fail "size -A"
+} else {
+    verbose "text size: $textsize"
+    verbose "data size: $datasize"
+    if {$textsize < 8 || $datasize < 4} then {
+       fail "size -A"
+    } else {
+       pass "size -A"
+    }
+}
diff --git a/binutils/testsuite/binutils-all/testprog.c b/binutils/testsuite/binutils-all/testprog.c
new file mode 100644 (file)
index 0000000..210656b
--- /dev/null
@@ -0,0 +1,28 @@
+/* This program is used to test objcopy and strip.  */
+
+int common;
+int global = 1;
+static int local = 2;
+static char string[] = "string";
+
+int
+fn ()
+{
+  return 3;
+}
+
+int
+main ()
+{
+  if (common != 0
+      || global != 1
+      || local != 2
+      || strcmp (string, "string") != 0)
+    {
+      printf ("failed\n");
+      exit (1);
+    }
+
+  printf ("ok\n");
+  exit (0);
+}
diff --git a/binutils/testsuite/config/default.exp b/binutils/testsuite/config/default.exp
new file mode 100644 (file)
index 0000000..2a2802e
--- /dev/null
@@ -0,0 +1,88 @@
+#   Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+load_lib util-defs.exp
+load_lib utils-lib.exp
+
+if ![info exists NM] then {
+    set NM [findfile $base_dir/nm-new $base_dir/nm-new [transform nm]]
+}
+if ![info exists NMFLAGS] then {
+    set NMFLAGS ""
+}
+
+if ![info exists SIZE] then {
+    set SIZE [findfile $base_dir/size]
+}
+if ![info exists SIZEFLAGS] then {
+    set SIZEFLAGS ""
+}
+
+if ![info exists OBJDUMP] then {
+    set OBJDUMP [findfile $base_dir/objdump]
+}
+if ![info exists OBJDUMPFLAGS] then {
+    set OBJDUMPFLAGS ""
+}
+
+if ![info exists OBJCOPY] then {
+    set OBJCOPY [findfile $base_dir/objcopy]
+}
+if ![info exists OBJCOPYFLAGS] then {
+    set OBJCOPYFLAGS ""
+}
+
+if ![info exists AR] then {
+    set AR [findfile $base_dir/ar]
+}
+
+if ![info exists STRIP] then {
+    set STRIP [findfile $base_dir/strip-new $base_dir/strip-new [transform strip]]
+}
+if ![info exists STRIPFLAGS] then {
+    set STRIPFLAGS ""
+}
+
+if ![info exists READELF] then {
+    set READELF [findfile $base_dir/readelf]
+}
+if ![info exists READELFFLAGS] then {
+    set READELFFLAGS ""
+}
+
+if ![file isdirectory tmpdir] {catch "exec mkdir tmpdir" status}
+
+#
+# binutils_run
+#      run a program, returning the output
+#      sets binutils_run_failed if the program does not exist
+#
+proc binutils_run { prog progargs } {
+    default_binutils_run $prog $progargs
+}
+
+#
+# binutils_assemble
+#      assemble a file
+#
+proc binutils_assemble { source object } {
+    default_binutils_assemble $source $object
+}
diff --git a/binutils/testsuite/config/hppa.sed b/binutils/testsuite/config/hppa.sed
new file mode 100644 (file)
index 0000000..d8607d8
--- /dev/null
@@ -0,0 +1,4 @@
+s/# Old OSF sed blows up if you have a sed command starting with "#"//
+s/# Avoid it by putting the comments within real sed commands.//
+s/# Fix the definition of common_symbol to be correct for the PA assebmlers.//
+s/     \.comm common_symbol,4/common_symbol    .comm 4/
diff --git a/binutils/testsuite/lib/utils-lib.exp b/binutils/testsuite/lib/utils-lib.exp
new file mode 100644 (file)
index 0000000..e27f217
--- /dev/null
@@ -0,0 +1,161 @@
+#   Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc.
+
+# 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# This file was written by Rob Savoye <rob@cygnus.com>
+# and extended by Ian Lance Taylor <ian@cygnus.com>
+
+proc binutil_version { prog } {
+    if ![is_remote host] {
+       set path [which $prog];
+       if {$path == 0} then {
+           perror "$prog can't be run, file not found."
+           return ""
+       }
+    } else {
+       set path $prog
+    }
+    set state [remote_exec host $prog --version];
+    set tmp "[lindex $state 1]\n";
+    # Should find a way to discard constant parts, keep whatever's
+    # left, so the version string could be almost anything at all...
+    regexp "\[^\n\]* (cygnus-|)(\[-0-9.a-zA-Z-\]+)\[\r\n\].*" "$tmp" version cyg number
+    if ![info exists number] then {
+        return "$path (no version number)\n"
+    }
+    return "$path $number\n"
+}
+
+#
+# default_binutils_run
+#      run a program, returning the output
+#      sets binutils_run_failed if the program does not exist
+#
+proc default_binutils_run { prog progargs } {
+    global binutils_run_failed
+    global host_triplet
+
+    set binutils_run_failed 0
+
+    if ![is_remote host] {
+       if {[which $prog] == 0} then {
+           perror "$prog does not exist"
+           set binutils_run_failed 1
+           return ""
+       }
+    }
+
+    send_log "$prog $progargs\n"
+    verbose "$prog $progargs"
+
+    # Gotta quote dollar-signs because they get mangled by the
+    # shell otherwise.
+    regsub -all "\\$" "$progargs" "\\$" progargs
+
+    set state [remote_exec host $prog $progargs]
+    set exec_output [prune_warnings [lindex $state 1]];
+    if {![string match "" $exec_output]} then {
+       send_log "$exec_output\n"
+       verbose "$exec_output"
+    }
+    return $exec_output
+}
+
+#
+# default_binutils_assemble
+#      assemble a file
+#
+proc default_binutils_assemble { source object } {
+    global srcdir
+    global host_triplet
+
+    # The HPPA assembler syntax is a little different than most, to make
+    # the test source file assemble we need to run it through sed.
+    #
+    # This is a hack in that it won't scale well if other targets need
+    # similar transformations to assemble.  We'll generalize the hack
+    # if/when other targets need similar handling.
+    if [istarget "hppa*-*-*" ] then {
+       send_log "sed -f $srcdir/config/hppa.sed < $source > asm.s\n"
+       verbose "sed -f $srcdir/config/hppa.sed < $source > asm.s"
+       catch "exec sed -f $srcdir/config/hppa.sed < $source > asm.s";
+       set source asm.s
+    }
+
+    set exec_output [target_assemble $source $object ""];
+    set exec_output [prune_warnings $exec_output]
+
+    if [string match "" $exec_output] {
+       return 1
+    } else {
+       send_log "$exec_output\n"
+       verbose "$exec_output"
+       perror "$source: assembly failed"
+       return 0
+    }
+}
+
+if ![info exists target_assemble] {
+#
+# Stolen from dejagnu/lib/target.exp--please remove after 1/1/98.
+#
+uplevel #0 {
+    proc target_assemble { source destfile flags } {
+       return [default_target_assemble $source $destfile $flags];
+    }
+
+    proc default_target_assemble { source destfile flags } {
+       global AS_FOR_TARGET;
+       global ASFLAGS_FOR_TARGET;
+
+       if [info exists AS_FOR_TARGET] {
+           set AS "$AS_FOR_TARGET";
+       } else {
+           if ![board_info target exists assembler] {
+               set AS [find_gas];
+           } else {
+               set AS [board_info target assembler];
+           }
+       }
+
+       if [info exists ASFLAGS_FOR_TARGET] {
+           append flags " $ASFLAGS_FOR_TARGET";
+       }
+
+       if [is_remote host] {
+           set source [remote_download host $source];
+           set dest "a.out"
+       } else {
+           set dest $destfile
+       }
+       set status [remote_exec host "$AS $source $flags -o $dest"]
+       if [is_remote host] {
+           remote_upload host $dest $destfile
+       }
+
+       set comp_output [prune_warnings [lindex $status 1]];
+       if { [lindex $status 0] != 0 } {
+           verbose -log "assembler exited with status [lindex $status 0]";
+       }
+       if { [lindex $status 1] != "" } {
+           verbose -log "assembler output is:\n[lindex $status 1]" 2;
+       }
+       return ${comp_output};
+}
+}
+}
diff --git a/binutils/version.c b/binutils/version.c
new file mode 100644 (file)
index 0000000..1055939
--- /dev/null
@@ -0,0 +1,44 @@
+/* version.c -- binutils version information
+   Copyright 1991, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of 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 2, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <stdio.h>
+#include "bfd.h"
+#include "bucomm.h"
+
+/* This is the version numbers for the binutils.  They all change in
+   lockstep -- it's easier that way. */
+
+const char *program_version = VERSION;
+
+/* Print the version number and copyright information, and exit.  This
+   implements the --version option for the various programs.  */
+
+void
+print_version (name)
+     const char *name;
+{
+  /* This output is intended to follow the GNU standards document.  */
+  /* xgettext:c-format */
+  printf ("GNU %s %s\n", name, program_version);
+  printf (_("Copyright 1997, 1998, 1999 Free Software Foundation, Inc.\n"));
+  printf (_("\
+This program is free software; you may redistribute it under the terms of\n\
+the GNU General Public License.  This program has absolutely no warranty.\n"));
+  exit (0);
+}
diff --git a/binutils/windres.c b/binutils/windres.c
new file mode 100644 (file)
index 0000000..7de28c2
--- /dev/null
@@ -0,0 +1,947 @@
+/* windres.c -- a program to manipulate Windows resources
+   Copyright 1997, 1998, 1999 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This program can read and write Windows resources in various
+   formats.  In particular, it can act like the rc resource compiler
+   program, and it can act like the cvtres res to COFF conversion
+   program.
+
+   It is based on information taken from the following sources:
+
+   * Microsoft documentation.
+
+   * The rcl program, written by Gunther Ebert
+     <gunther.ebert@ixos-leipzig.de>.
+
+   * The res2coff program, written by Pedro A. Aranda <paag@tid.es>.
+
+   */
+
+#include "bfd.h"
+#include "getopt.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "obstack.h"
+#include "windres.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <time.h>
+
+/* An enumeration of format types.  */
+
+enum res_format
+{
+  /* Unknown format.  */
+  RES_FORMAT_UNKNOWN,
+  /* Textual RC file.  */
+  RES_FORMAT_RC,
+  /* Binary RES file.  */
+  RES_FORMAT_RES,
+  /* COFF file.  */
+  RES_FORMAT_COFF
+};
+
+/* A structure used to map between format types and strings.  */
+
+struct format_map
+{
+  const char *name;
+  enum res_format format;
+};
+
+/* A mapping between names and format types.  */
+
+static const struct format_map format_names[] =
+{
+  { "rc", RES_FORMAT_RC },
+  { "res", RES_FORMAT_RES },
+  { "coff", RES_FORMAT_COFF },
+  { NULL, RES_FORMAT_UNKNOWN }
+};
+
+/* A mapping from file extensions to format types.  */
+
+static const struct format_map format_fileexts[] =
+{
+  { "rc", RES_FORMAT_RC },
+  { "res", RES_FORMAT_RES },
+  { "exe", RES_FORMAT_COFF },
+  { "obj", RES_FORMAT_COFF },
+  { "o", RES_FORMAT_COFF },
+  { NULL, RES_FORMAT_UNKNOWN }
+};
+
+/* A list of include directories.  */
+
+struct include_dir
+{
+  struct include_dir *next;
+  char *dir;
+};
+
+static struct include_dir *include_dirs;
+
+/* Long options.  */
+
+/* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
+
+#define OPTION_DEFINE 150
+#define OPTION_HELP (OPTION_DEFINE + 1)
+#define OPTION_INCLUDE_DIR (OPTION_HELP + 1)
+#define OPTION_LANGUAGE (OPTION_INCLUDE_DIR + 1)
+#define OPTION_PREPROCESSOR (OPTION_LANGUAGE + 1)
+#define OPTION_VERSION (OPTION_PREPROCESSOR + 1)
+#define OPTION_YYDEBUG (OPTION_VERSION + 1)
+
+static const struct option long_options[] =
+{
+  {"define", required_argument, 0, OPTION_DEFINE},
+  {"help", no_argument, 0, OPTION_HELP},
+  {"include-dir", required_argument, 0, OPTION_INCLUDE_DIR},
+  {"input-format", required_argument, 0, 'I'},
+  {"language", required_argument, 0, OPTION_LANGUAGE},
+  {"output-format", required_argument, 0, 'O'},
+  {"preprocessor", required_argument, 0, OPTION_PREPROCESSOR},
+  {"target", required_argument, 0, 'F'},
+  {"version", no_argument, 0, OPTION_VERSION},
+  {"yydebug", no_argument, 0, OPTION_YYDEBUG},
+  {0, no_argument, 0, 0}
+};
+
+/* Static functions.  */
+
+static void res_init PARAMS ((void));
+static int extended_menuitems PARAMS ((const struct menuitem *));
+static enum res_format format_from_name PARAMS ((const char *));
+static enum res_format format_from_filename PARAMS ((const char *, int));
+static void usage PARAMS ((FILE *, int));
+static int cmp_res_entry PARAMS ((const PTR, const PTR));
+static struct res_directory *sort_resources PARAMS ((struct res_directory *));
+\f
+/* When we are building a resource tree, we allocate everything onto
+   an obstack, so that we can free it all at once if we want.  */
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
+/* The resource building obstack.  */
+
+static struct obstack res_obstack;
+
+/* Initialize the resource building obstack.  */
+
+static void
+res_init ()
+{
+  obstack_init (&res_obstack);
+}
+
+/* Allocate space on the resource building obstack.  */
+
+PTR
+res_alloc (bytes)
+     size_t bytes;
+{
+  return (PTR) obstack_alloc (&res_obstack, bytes);
+}
+
+/* We also use an obstack to save memory used while writing out a set
+   of resources.  */
+
+static struct obstack reswr_obstack;
+
+/* Initialize the resource writing obstack.  */
+
+static void
+reswr_init ()
+{
+  obstack_init (&reswr_obstack);
+}
+
+/* Allocate space on the resource writing obstack.  */
+
+PTR
+reswr_alloc (bytes)
+     size_t bytes;
+{
+  return (PTR) obstack_alloc (&reswr_obstack, bytes);
+}
+\f
+/* Open a file using the include directory search list.  */
+
+FILE *
+open_file_search (filename, mode, errmsg, real_filename)
+     const char *filename;
+     const char *mode;
+     const char *errmsg;
+     char **real_filename;
+{
+  FILE *e;
+  struct include_dir *d;
+
+  e = fopen (filename, mode);
+  if (e != NULL)
+    {
+      *real_filename = xstrdup (filename);
+      return e;
+    }
+
+  if (errno == ENOENT)
+    {
+      for (d = include_dirs; d != NULL; d = d->next)
+       {
+         char *n;
+
+         n = (char *) xmalloc (strlen (d->dir) + strlen (filename) + 2);
+         sprintf (n, "%s/%s", d->dir, filename);
+         e = fopen (n, mode);
+         if (e != NULL)
+           {
+             *real_filename = n;
+             return e;
+           }
+
+         if (errno != ENOENT)
+           break;
+       }
+    }
+
+  fatal (_("can't open %s `%s': %s"), errmsg, filename, strerror (errno));
+
+  /* Return a value to avoid a compiler warning.  */
+  return NULL;
+}
+\f
+/* Compare two resource ID's.  We consider name entries to come before
+   numeric entries, because that is how they appear in the COFF .rsrc
+   section.  */
+
+int
+res_id_cmp (a, b)
+     struct res_id a;
+     struct res_id b;
+{
+  if (! a.named)
+    {
+      if (b.named)
+       return 1;
+      if (a.u.id > b.u.id)
+       return 1;
+      else if (a.u.id < b.u.id)
+       return -1;
+      else
+       return 0;
+    }
+  else
+    {
+      unichar *as, *ase, *bs, *bse;
+
+      if (! b.named)
+       return -1;
+
+      as = a.u.n.name;
+      ase = as + a.u.n.length;
+      bs = b.u.n.name;
+      bse = bs + b.u.n.length;
+
+      while (as < ase)
+       {
+         int i;
+
+         if (bs >= bse)
+           return 1;
+         i = (int) *as - (int) *bs;
+         if (i != 0)
+           return i;
+         ++as;
+         ++bs;
+       }
+
+      if (bs < bse)
+       return -1;
+
+      return 0;
+    }
+}
+
+/* Print a resource ID.  */
+
+void
+res_id_print (stream, id, quote)
+     FILE *stream;
+     struct res_id id;
+     int quote;
+{
+  if (! id.named)
+    fprintf (stream, "%lu", id.u.id);
+  else
+    {
+      if (quote)
+       putc ('"', stream);
+      unicode_print (stream, id.u.n.name, id.u.n.length);
+      if (quote)
+       putc ('"', stream);
+    }
+}
+
+/* Print a list of resource ID's.  */
+
+void
+res_ids_print (stream, cids, ids)
+     FILE *stream;
+     int cids;
+     const struct res_id *ids;
+{
+  int i;
+
+  for (i = 0; i < cids; i++)
+    {
+      res_id_print (stream, ids[i], 1);
+      if (i + 1 < cids)
+       fprintf (stream, ": ");
+    }
+}
+
+/* Convert an ASCII string to a resource ID.  */
+
+void
+res_string_to_id (res_id, string)
+     struct res_id *res_id;
+     const char *string;
+{
+  res_id->named = 1;
+  unicode_from_ascii (&res_id->u.n.length, &res_id->u.n.name, string);
+}
+
+/* Define a resource.  The arguments are the resource tree, RESOURCES,
+   and the location at which to put it in the tree, CIDS and IDS.
+   This returns a newly allocated res_resource structure, which the
+   caller is expected to initialize.  If DUPOK is non-zero, then if a
+   resource with this ID exists, it is returned.  Otherwise, a warning
+   is issued, and a new resource is created replacing the existing
+   one.  */
+
+struct res_resource *
+define_resource (resources, cids, ids, dupok)
+     struct res_directory **resources;
+     int cids;
+     const struct res_id *ids;
+     int dupok;
+{
+  struct res_entry *re = NULL;
+  int i;
+
+  assert (cids > 0);
+  for (i = 0; i < cids; i++)
+    {
+      struct res_entry **pp;
+
+      if (*resources == NULL)
+       {
+         static unsigned long timeval;
+
+         /* Use the same timestamp for every resource created in a
+             single run.  */
+         if (timeval == 0)
+           timeval = time (NULL);
+
+         *resources = ((struct res_directory *)
+                       res_alloc (sizeof **resources));
+         (*resources)->characteristics = 0;
+         (*resources)->time = timeval;
+         (*resources)->major = 0;
+         (*resources)->minor = 0;
+         (*resources)->entries = NULL;
+       }
+
+      for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
+       if (res_id_cmp ((*pp)->id, ids[i]) == 0)
+         break;
+
+      if (*pp != NULL)
+       re = *pp;
+      else
+       {
+         re = (struct res_entry *) res_alloc (sizeof *re);
+         re->next = NULL;
+         re->id = ids[i];
+         if ((i + 1) < cids)
+           {
+             re->subdir = 1;
+             re->u.dir = NULL;
+           }
+         else
+           {
+             re->subdir = 0;
+             re->u.res = NULL;
+           }
+
+         *pp = re;
+       }
+
+      if ((i + 1) < cids)
+       {
+         if (! re->subdir)
+           {
+             fprintf (stderr, "%s: ", program_name);
+             res_ids_print (stderr, i, ids);
+             fprintf (stderr, _(": expected to be a directory\n"));
+             xexit (1);
+           }
+
+         resources = &re->u.dir;
+       }
+    }
+
+  if (re->subdir)
+    {
+      fprintf (stderr, "%s: ", program_name);
+      res_ids_print (stderr, cids, ids);
+      fprintf (stderr, _(": expected to be a leaf\n"));
+      xexit (1);
+    }
+
+  if (re->u.res != NULL)
+    {
+      if (dupok)
+       return re->u.res;
+
+      fprintf (stderr, _("%s: warning: "), program_name);
+      res_ids_print (stderr, cids, ids);
+      fprintf (stderr, _(": duplicate value\n"));
+    }
+
+  re->u.res = ((struct res_resource *)
+              res_alloc (sizeof (struct res_resource)));
+
+  re->u.res->type = RES_TYPE_UNINITIALIZED;
+  memset (&re->u.res->res_info, 0, sizeof (struct res_res_info));
+  memset (&re->u.res->coff_info, 0, sizeof (struct res_coff_info));
+
+  return re->u.res;
+}
+
+/* Define a standard resource.  This is a version of define_resource
+   that just takes type, name, and language arguments.  */
+
+struct res_resource *
+define_standard_resource (resources, type, name, language, dupok)
+     struct res_directory **resources;
+     int type;
+     struct res_id name;
+     int language;
+     int dupok;
+{
+  struct res_id a[3];
+
+  a[0].named = 0;
+  a[0].u.id = type;
+  a[1] = name;
+  a[2].named = 0;
+  a[2].u.id = language;
+  return define_resource (resources, 3, a, dupok);
+}
+
+/* Comparison routine for resource sorting.  */
+
+static int
+cmp_res_entry (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  const struct res_entry **re1, **re2;
+
+  re1 = (const struct res_entry **) p1;
+  re2 = (const struct res_entry **) p2;
+  return res_id_cmp ((*re1)->id, (*re2)->id);
+}
+
+/* Sort the resources.  */
+
+static struct res_directory *
+sort_resources (resdir)
+     struct res_directory *resdir;
+{
+  int c, i;
+  struct res_entry *re;
+  struct res_entry **a;
+
+  if (resdir->entries == NULL)
+    return resdir;
+
+  c = 0;
+  for (re = resdir->entries; re != NULL; re = re->next)
+    ++c;
+
+  /* This is a recursive routine, so using xmalloc is probably better
+     than alloca.  */
+  a = (struct res_entry **) xmalloc (c * sizeof (struct res_entry *));
+
+  for (i = 0, re = resdir->entries; re != NULL; re = re->next, i++)
+    a[i] = re;
+
+  qsort (a, c, sizeof (struct res_entry *), cmp_res_entry);
+
+  resdir->entries = a[0];
+  for (i = 0; i < c - 1; i++)
+    a[i]->next = a[i + 1];
+  a[i]->next = NULL;
+
+  free (a);
+
+  /* Now sort the subdirectories.  */
+
+  for (re = resdir->entries; re != NULL; re = re->next)
+    if (re->subdir)
+      re->u.dir = sort_resources (re->u.dir);
+
+  return resdir;
+}
+\f
+/* Return whether the dialog resource DIALOG is a DIALOG or a
+   DIALOGEX.  */
+
+int
+extended_dialog (dialog)
+     const struct dialog *dialog;
+{
+  const struct dialog_control *c;
+
+  if (dialog->ex != NULL)
+    return 1;
+
+  for (c = dialog->controls; c != NULL; c = c->next)
+    if (c->data != NULL || c->help != 0)
+      return 1;
+
+  return 0;
+}
+
+/* Return whether MENUITEMS are a MENU or a MENUEX.  */
+
+int
+extended_menu (menu)
+     const struct menu *menu;
+{
+  return extended_menuitems (menu->items);
+}
+
+static int
+extended_menuitems (menuitems)
+     const struct menuitem *menuitems;
+{
+  const struct menuitem *mi;
+
+  for (mi = menuitems; mi != NULL; mi = mi->next)
+    {
+      if (mi->help != 0 || mi->state != 0)
+       return 1;
+      if (mi->popup != NULL && mi->id != 0)
+       return 1;
+      if ((mi->type
+          & ~ (MENUITEM_CHECKED
+               | MENUITEM_GRAYED
+               | MENUITEM_HELP
+               | MENUITEM_INACTIVE
+               | MENUITEM_MENUBARBREAK
+               | MENUITEM_MENUBREAK))
+         != 0)
+       return 1;
+      if (mi->popup != NULL)
+       {
+         if (extended_menuitems (mi->popup))
+           return 1;
+       }
+    }
+
+  return 0;
+}
+\f
+/* Convert a string to a format type, or exit if it can't be done.  */
+
+static enum res_format
+format_from_name (name)
+     const char *name;
+{
+  const struct format_map *m;
+
+  for (m = format_names; m->name != NULL; m++)
+    if (strcasecmp (m->name, name) == 0)
+      break;
+
+  if (m->name == NULL)
+    {
+      fprintf (stderr, _("%s: unknown format type `%s'\n"), program_name, name);
+      fprintf (stderr, _("%s: supported formats:"), program_name);
+      for (m = format_names; m->name != NULL; m++)
+       fprintf (stderr, " %s", m->name);
+      fprintf (stderr, "\n");
+      xexit (1);
+    }
+
+  return m->format;
+}
+
+/* Work out a format type given a file name.  If INPUT is non-zero,
+   it's OK to look at the file itself.  */
+
+static enum res_format
+format_from_filename (filename, input)
+     const char *filename;
+     int input;
+{
+  const char *ext;
+  FILE *e;
+  unsigned char b1, b2, b3, b4, b5;
+  int magic;
+
+  /* If we have an extension, see if we recognize it as implying a
+     particular format.  */
+  ext = strrchr (filename, '.');
+  if (ext != NULL)
+    {
+      const struct format_map *m;
+
+      ++ext;
+      for (m = format_fileexts; m->name != NULL; m++)
+       if (strcasecmp (m->name, ext) == 0)
+         return m->format;
+    }
+
+  /* If we don't recognize the name of an output file, assume it's a
+     COFF file.  */
+
+  if (! input)
+    return RES_FORMAT_COFF;
+
+  /* Read the first few bytes of the file to see if we can guess what
+     it is.  */
+
+  e = fopen (filename, FOPEN_RB);
+  if (e == NULL)
+    fatal ("%s: %s", filename, strerror (errno));
+
+  b1 = getc (e);
+  b2 = getc (e);
+  b3 = getc (e);
+  b4 = getc (e);
+  b5 = getc (e);
+
+  fclose (e);
+
+  /* A PE executable starts with 0x4d 0x5a.  */
+  if (b1 == 0x4d && b2 == 0x5a)
+    return RES_FORMAT_COFF;
+
+  /* A COFF .o file starts with a COFF magic number.  */
+  magic = (b2 << 8) | b1;
+  switch (magic)
+    {
+    case 0x14c: /* i386 */
+    case 0x166: /* MIPS */
+    case 0x184: /* Alpha */
+    case 0x268: /* 68k */
+    case 0x1f0: /* PowerPC */
+    case 0x290: /* PA */
+      return RES_FORMAT_COFF;
+    }
+
+  /* A RES file starts with 0x0 0x0 0x0 0x0 0x20 0x0 0x0 0x0.  */
+  if (b1 == 0 && b2 == 0 && b3 == 0 && b4 == 0 && b5 == 0x20)
+    return RES_FORMAT_RES;
+
+  /* If every character is printable or space, assume it's an RC file.  */
+  if ((isprint (b1) || isspace (b1))
+      && (isprint (b2) || isspace (b2))
+      && (isprint (b3) || isspace (b3))
+      && (isprint (b4) || isspace (b4))
+      && (isprint (b5) || isspace (b5)))
+    return RES_FORMAT_RC;
+
+  /* Otherwise, we give up.  */
+  fatal (_("can not determine type of file `%s'; use the -I option"),
+        filename);
+
+  /* Return something to silence the compiler warning.  */
+  return RES_FORMAT_UNKNOWN;
+}
+
+/* Print a usage message and exit.  */
+
+static void
+usage (stream, status)
+     FILE *stream;
+     int status;
+{
+  fprintf (stream, _("Usage: %s [options] [input-file] [output-file]\n"),
+          program_name);
+  fprintf (stream, _("\
+Options:\n\
+  -i FILE, --input FILE       Name input file\n\
+  -o FILE, --output FILE      Name output file\n\
+  -I FORMAT, --input-format FORMAT\n\
+                              Specify input format\n\
+  -O FORMAT, --output-format FORMAT\n\
+                              Specify output format\n\
+  -F TARGET, --target TARGET  Specify COFF target\n\
+  --preprocessor PROGRAM      Program to use to preprocess rc file\n\
+  --include-dir DIR           Include directory when preprocessing rc file\n\
+  --define SYM[=VAL]          Define SYM when preprocessing rc file\n\
+  --language VAL              Set language when reading rc file\n"));
+#ifdef YYDEBUG
+  fprintf (stream, _("\
+  --yydebug                   Turn on parser debugging\n"));
+#endif
+  fprintf (stream, _("\
+  --help                      Print this help message\n\
+  --version                   Print version information\n"));
+  fprintf (stream, _("\
+FORMAT is one of rc, res, or coff, and is deduced from the file name\n\
+extension if not specified.  A single file name is an input file.\n\
+No input-file is stdin, default rc.  No output-file is stdout, default rc.\n"));
+  list_supported_targets (program_name, stream);
+  if (status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  exit (status);
+}
+
+/* The main function.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  char *input_filename;
+  char *output_filename;
+  enum res_format input_format;
+  enum res_format output_format;
+  char *target;
+  char *preprocessor;
+  char *preprocargs;
+  int language;
+  struct res_directory *resources;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  program_name = argv[0];
+  xmalloc_set_program_name (program_name);
+
+  bfd_init ();
+  set_default_bfd_target ();
+
+  res_init ();
+
+  input_filename = NULL;
+  output_filename = NULL;
+  input_format = RES_FORMAT_UNKNOWN;
+  output_format = RES_FORMAT_UNKNOWN;
+  target = NULL;
+  preprocessor = NULL;
+  preprocargs = NULL;
+  language = -1;
+
+  while ((c = getopt_long (argc, argv, "i:o:I:O:F:", long_options,
+                          (int *) 0)) != EOF)
+    {
+      switch (c)
+       {
+       case 'i':
+         input_filename = optarg;
+         break;
+
+       case 'o':
+         output_filename = optarg;
+         break;
+
+       case 'I':
+         input_format = format_from_name (optarg);
+         break;
+
+       case 'O':
+         output_format = format_from_name (optarg);
+         break;
+
+       case 'F':
+         target = optarg;
+         break;
+
+       case OPTION_PREPROCESSOR:
+         preprocessor = optarg;
+         break;
+
+       case OPTION_DEFINE:
+         if (preprocargs == NULL)
+           {
+             preprocargs = xmalloc (strlen (optarg) + 3);
+             sprintf (preprocargs, "-D%s", optarg);
+           }
+         else
+           {
+             char *n;
+
+             n = xmalloc (strlen (preprocargs) + strlen (optarg) + 4);
+             sprintf (n, "%s -D%s", preprocargs, optarg);
+             free (preprocargs);
+             preprocargs = n;
+           }
+         break;
+
+       case OPTION_INCLUDE_DIR:
+         if (preprocargs == NULL)
+           {
+             preprocargs = xmalloc (strlen (optarg) + 3);
+             sprintf (preprocargs, "-I%s", optarg);
+           }
+         else
+           {
+             char *n;
+
+             n = xmalloc (strlen (preprocargs) + strlen (optarg) + 4);
+             sprintf (n, "%s -I%s", preprocargs, optarg);
+             free (preprocargs);
+             preprocargs = n;
+           }
+
+         {
+           struct include_dir *n, **pp;
+
+           n = (struct include_dir *) xmalloc (sizeof *n);
+           n->next = NULL;
+           n->dir = optarg;
+
+           for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
+             ;
+           *pp = n;
+         }
+
+         break;
+
+       case OPTION_LANGUAGE:
+         language = strtol (optarg, (char **) NULL, 16);
+         break;
+
+#ifdef YYDEBUG
+       case OPTION_YYDEBUG:
+         yydebug = 1;
+         break;
+#endif
+
+       case OPTION_HELP:
+         usage (stdout, 0);
+         break;
+
+       case OPTION_VERSION:
+         print_version ("windres");
+         break;
+
+       default:
+         usage (stderr, 1);
+         break;
+       }
+    }
+
+  if (input_filename == NULL && optind < argc)
+    {
+      input_filename = argv[optind];
+      ++optind;
+    }
+
+  if (output_filename == NULL && optind < argc)
+    {
+      output_filename = argv[optind];
+      ++optind;
+    }
+
+  if (argc != optind)
+    usage (stderr, 1);
+
+  if (input_format == RES_FORMAT_UNKNOWN)
+    {
+      if (input_filename == NULL)
+       input_format = RES_FORMAT_RC;
+      else
+       input_format = format_from_filename (input_filename, 1);
+    }
+
+  if (output_format == RES_FORMAT_UNKNOWN)
+    {
+      if (output_filename == NULL)
+       output_format = RES_FORMAT_RC;
+      else
+       output_format = format_from_filename (output_filename, 0);
+    }
+
+  /* Read the input file.  */
+
+  switch (input_format)
+    {
+    default:
+      abort ();
+    case RES_FORMAT_RC:
+      resources = read_rc_file (input_filename, preprocessor, preprocargs,
+                               language);
+      break;
+    case RES_FORMAT_RES:
+      resources = read_res_file (input_filename);
+      break;
+    case RES_FORMAT_COFF:
+      resources = read_coff_rsrc (input_filename, target);
+      break;
+    }
+
+  if (resources == NULL)
+    fatal (_("no resources"));
+
+  /* Sort the resources.  This is required for COFF, convenient for
+     rc, and unimportant for res.  */
+
+  resources = sort_resources (resources);
+
+  /* Write the output file.  */
+
+  reswr_init ();
+
+  switch (output_format)
+    {
+    default:
+      abort ();
+    case RES_FORMAT_RC:
+      write_rc_file (output_filename, resources);
+      break;
+    case RES_FORMAT_RES:
+      write_res_file (output_filename, resources);
+      break;
+    case RES_FORMAT_COFF:
+      write_coff_file (output_filename, target, resources);
+      break;
+    }
+
+  xexit (0);
+  return 0;
+}
+
diff --git a/binutils/windres.h b/binutils/windres.h
new file mode 100644 (file)
index 0000000..a3c789a
--- /dev/null
@@ -0,0 +1,847 @@
+/* windres.h -- header file for windres program.
+   Copyright 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#include <ansidecl.h>
+
+/* This is the header file for the windres program.  It defines
+   structures and declares functions used within the program.  */
+
+#include "winduni.h"
+
+/* We represent resources internally as a tree, similar to the tree
+   used in the .rsrc section of a COFF file.  The root is a
+   res_directory structure.  */
+
+struct res_directory
+{
+  /* Resource flags.  According to the MS docs, this is currently
+     always zero.  */
+  unsigned long characteristics;
+  /* Time/date stamp.  */
+  unsigned long time;
+  /* Major version number.  */
+  unsigned short major;
+  /* Minor version number.  */
+  unsigned short minor;
+  /* Directory entries.  */
+  struct res_entry *entries;
+};
+
+/* A resource ID is stored in a res_id structure.  */
+
+struct res_id
+{
+  /* Non-zero if this entry has a name rather than an ID.  */
+  unsigned int named : 1;
+  union
+  {
+    /* If the named field is non-zero, this is the name.  */
+    struct
+    {
+      /* Length of the name.  */
+      int length;
+      /* Pointer to the name, which is a Unicode string.  */
+      unichar *name;
+    } n;
+    /* If the named field is zero, this is the ID.  */
+    unsigned long id;
+  } u;
+};
+
+/* Each entry in the tree is a res_entry structure.  We mix
+   directories and resources because in a COFF file all entries in a
+   directory are sorted together, whether the entries are
+   subdirectories or resources.  */
+
+struct res_entry
+{
+  /* Next entry.  */
+  struct res_entry *next;
+  /* Resource ID.  */
+  struct res_id id;
+  /* Non-zero if this entry is a subdirectory rather than a leaf.  */
+  unsigned int subdir : 1;
+  union
+  {
+    /* If the subdir field is non-zero, this is a pointer to the
+       subdirectory.  */
+    struct res_directory *dir;
+    /* If the subdir field is zero, this is a pointer to the resource
+       data.  */
+    struct res_resource *res;
+  } u;
+};
+
+/* Types of resources.  */
+
+enum res_type
+{
+  RES_TYPE_UNINITIALIZED,
+  RES_TYPE_ACCELERATOR,
+  RES_TYPE_BITMAP,
+  RES_TYPE_CURSOR,
+  RES_TYPE_GROUP_CURSOR,
+  RES_TYPE_DIALOG,
+  RES_TYPE_FONT,
+  RES_TYPE_FONTDIR,
+  RES_TYPE_ICON,
+  RES_TYPE_GROUP_ICON,
+  RES_TYPE_MENU,
+  RES_TYPE_MESSAGETABLE,
+  RES_TYPE_RCDATA,
+  RES_TYPE_STRINGTABLE,
+  RES_TYPE_USERDATA,
+  RES_TYPE_VERSIONINFO
+};
+
+/* A res file and a COFF file store information differently.  The
+   res_info structures holds data which in a res file is stored with
+   each resource, but in a COFF file is stored elsewhere.  */
+
+struct res_res_info
+{
+  /* Language.  In a COFF file, the third level of the directory is
+     keyed by the language, so the language of a resource is defined
+     by its location in the resource tree.  */
+  unsigned short language;
+  /* Characteristics of the resource.  Entirely user defined.  In a
+     COFF file, the res_directory structure has a characteristics
+     field, but I don't know if it's related to the one in the res
+     file.  */
+  unsigned long characteristics;
+  /* Version of the resource.  Entirely user defined.  In a COFF file,
+     the res_directory structure has a characteristics field, but I
+     don't know if it's related to the one in the res file.  */
+  unsigned long version;
+  /* Memory flags.  This is a combination of the MEMFLAG values
+     defined below.  Most of these values are historical, and are not
+     meaningful for win32.  I don't think there is any way to store
+     this information in a COFF file.  */
+  unsigned short memflags;
+};
+
+/* Each resource in a COFF file has some information which can does
+   not appear in a res file.  */
+
+struct res_coff_info
+{
+  /* The code page used for the data.  I don't really know what this
+     should be.  */
+  unsigned long codepage;
+  /* A resource entry in a COFF file has a reserved field, which we
+     record here when reading a COFF file.  When writing a COFF file,
+     we set this field to zero.  */
+  unsigned long reserved;
+};
+
+/* Resource data is stored in a res_resource structure.  */
+
+struct res_resource
+{
+  /* The type of resource.  */
+  enum res_type type;
+  /* The data for the resource.  */
+  union
+  {
+    struct
+    {
+      unsigned long length;
+      const unsigned char *data;
+    } data;
+    struct accelerator *acc;
+    struct cursor *cursor;
+    struct group_cursor *group_cursor;
+    struct dialog *dialog;
+    struct fontdir *fontdir;
+    struct group_icon *group_icon;
+    struct menu *menu;
+    struct rcdata_item *rcdata;
+    struct stringtable *stringtable;
+    struct rcdata_item *userdata;
+    struct versioninfo *versioninfo;
+  } u;
+  /* Information from a res file.  */
+  struct res_res_info res_info;
+  /* Information from a COFF file.  */
+  struct res_coff_info coff_info;
+};
+
+/* Memory flags in the memflags field of a struct res_resource.  */
+
+#define MEMFLAG_MOVEABLE       0x10
+#define MEMFLAG_PURE           0x20
+#define MEMFLAG_PRELOAD                0x40
+#define MEMFLAG_DISCARDABLE    0x1000
+
+/* Standard resource type codes.  These are used in the ID field of a
+   res_entry structure.  */
+
+#define RT_CURSOR               1
+#define RT_BITMAP               2
+#define RT_ICON                         3
+#define RT_MENU                         4
+#define RT_DIALOG               5
+#define RT_STRING               6
+#define RT_FONTDIR              7
+#define RT_FONT                         8
+#define RT_ACCELERATOR          9
+#define RT_RCDATA              10
+#define RT_MESSAGETABLE                11
+#define RT_GROUP_CURSOR                12
+#define RT_GROUP_ICON          14
+#define RT_VERSION             16
+#define RT_DLGINCLUDE          17
+#define RT_PLUGPLAY            19
+#define RT_VXD                 20
+#define RT_ANICURSOR           21
+#define RT_ANIICON             22
+
+/* An accelerator resource is a linked list of these structures.  */
+
+struct accelerator
+{
+  /* Next accelerator.  */
+  struct accelerator *next;
+  /* Flags.  A combination of the ACC values defined below.  */
+  unsigned short flags;
+  /* Key value.  */
+  unsigned short key;
+  /* Resource ID.  */
+  unsigned short id;
+};
+
+/* Accelerator flags in the flags field of a struct accelerator.
+   These are the same values that appear in a res file.  I hope.  */
+
+#define ACC_VIRTKEY    0x01
+#define ACC_NOINVERT   0x02
+#define ACC_SHIFT      0x04
+#define ACC_CONTROL    0x08
+#define ACC_ALT                0x10
+#define ACC_LAST       0x80
+
+/* A cursor resource.  */
+
+struct cursor
+{
+  /* X coordinate of hotspot.  */
+  short xhotspot;
+  /* Y coordinate of hotspot.  */
+  short yhotspot;
+  /* Length of bitmap data.  */
+  unsigned long length;
+  /* Data.  */
+  const unsigned char *data;
+};
+
+/* A group_cursor resource is a list of group_cursor structures.  */
+
+struct group_cursor
+{
+  /* Next cursor in group.  */
+  struct group_cursor *next;
+  /* Width.  */
+  unsigned short width;
+  /* Height.  */
+  unsigned short height;
+  /* Planes.  */
+  unsigned short planes;
+  /* Bits per pixel.  */
+  unsigned short bits;
+  /* Number of bytes in cursor resource.  */
+  unsigned long bytes;
+  /* Index of cursor resource.  */
+  unsigned short index;
+};
+
+/* A dialog resource.  */
+
+struct dialog
+{
+  /* Basic window style.  */
+  unsigned long style;
+  /* Extended window style.  */
+  unsigned long exstyle;
+  /* X coordinate.  */
+  unsigned short x;
+  /* Y coordinate.  */
+  unsigned short y;
+  /* Width.  */
+  unsigned short width;
+  /* Height.  */
+  unsigned short height;
+  /* Menu name.  */
+  struct res_id menu;
+  /* Class name.  */
+  struct res_id class;
+  /* Caption.  */
+  unichar *caption;
+  /* Font point size.  */
+  unsigned short pointsize;
+  /* Font name.  */
+  unichar *font;
+  /* Extended information for a dialogex.  */
+  struct dialog_ex *ex;
+  /* Controls.  */
+  struct dialog_control *controls;
+};
+
+/* An extended dialog has additional information.  */
+
+struct dialog_ex
+{
+  /* Help ID.  */
+  unsigned long help;
+  /* Font weight.  */
+  unsigned short weight;
+  /* Whether the font is italic.  */
+  unsigned short italic;
+};
+
+/* Window style flags, from the winsup Defines.h header file.  These
+   can appear in the style field of a struct dialog or a struct
+   dialog_control.  */
+
+#define CW_USEDEFAULT  (0x80000000)
+#define WS_BORDER      (0x800000L)
+#define WS_CAPTION     (0xc00000L)
+#define WS_CHILD       (0x40000000L)
+#define WS_CHILDWINDOW (0x40000000L)
+#define WS_CLIPCHILDREN        (0x2000000L)
+#define WS_CLIPSIBLINGS        (0x4000000L)
+#define WS_DISABLED    (0x8000000L)
+#define WS_DLGFRAME    (0x400000L)
+#define WS_GROUP       (0x20000L)
+#define WS_HSCROLL     (0x100000L)
+#define WS_ICONIC      (0x20000000L)
+#define WS_MAXIMIZE    (0x1000000L)
+#define WS_MAXIMIZEBOX (0x10000L)
+#define WS_MINIMIZE    (0x20000000L)
+#define WS_MINIMIZEBOX (0x20000L)
+#define WS_OVERLAPPED  (0L)
+#define WS_OVERLAPPEDWINDOW    (0xcf0000L)
+#define WS_POPUP       (0x80000000L)
+#define WS_POPUPWINDOW (0x80880000L)
+#define WS_SIZEBOX     (0x40000L)
+#define WS_SYSMENU     (0x80000L)
+#define WS_TABSTOP     (0x10000L)
+#define WS_THICKFRAME  (0x40000L)
+#define WS_TILED       (0L)
+#define WS_TILEDWINDOW (0xcf0000L)
+#define WS_VISIBLE     (0x10000000L)
+#define WS_VSCROLL     (0x200000L)
+#define MDIS_ALLCHILDSTYLES    (0x1)
+#define BS_3STATE      (0x5L)
+#define BS_AUTO3STATE  (0x6L)
+#define BS_AUTOCHECKBOX        (0x3L)
+#define BS_AUTORADIOBUTTON     (0x9L)
+#define BS_BITMAP      (0x80L)
+#define BS_BOTTOM      (0x800L)
+#define BS_CENTER      (0x300L)
+#define BS_CHECKBOX    (0x2L)
+#define BS_DEFPUSHBUTTON       (0x1L)
+#define BS_GROUPBOX    (0x7L)
+#define BS_ICON        (0x40L)
+#define BS_LEFT        (0x100L)
+#define BS_LEFTTEXT    (0x20L)
+#define BS_MULTILINE   (0x2000L)
+#define BS_NOTIFY      (0x4000L)
+#define BS_OWNERDRAW   (0xbL)
+#define BS_PUSHBOX     (0xcL)          /* FIXME!  What should this be?  */
+#define BS_PUSHBUTTON  (0L)
+#define BS_PUSHLIKE    (0x1000L)
+#define BS_RADIOBUTTON (0x4L)
+#define BS_RIGHT       (0x200L)
+#define BS_RIGHTBUTTON (0x20L)
+#define BS_TEXT        (0L)
+#define BS_TOP (0x400L)
+#define BS_USERBUTTON  (0x8L)
+#define BS_VCENTER     (0xc00L)
+#define CBS_AUTOHSCROLL        (0x40L)
+#define CBS_DISABLENOSCROLL    (0x800L)
+#define CBS_DROPDOWN   (0x2L)
+#define CBS_DROPDOWNLIST       (0x3L)
+#define CBS_HASSTRINGS (0x200L)
+#define CBS_LOWERCASE  (0x4000L)
+#define CBS_NOINTEGRALHEIGHT   (0x400L)
+#define CBS_OEMCONVERT (0x80L)
+#define CBS_OWNERDRAWFIXED     (0x10L)
+#define CBS_OWNERDRAWVARIABLE  (0x20L)
+#define CBS_SIMPLE     (0x1L)
+#define CBS_SORT       (0x100L)
+#define CBS_UPPERCASE  (0x2000L)
+#define ES_AUTOHSCROLL (0x80L)
+#define ES_AUTOVSCROLL (0x40L)
+#define ES_CENTER      (0x1L)
+#define ES_LEFT        (0L)
+#define ES_LOWERCASE   (0x10L)
+#define ES_MULTILINE   (0x4L)
+#define ES_NOHIDESEL   (0x100L)
+#define ES_NUMBER      (0x2000L)
+#define ES_OEMCONVERT  (0x400L)
+#define ES_PASSWORD    (0x20L)
+#define ES_READONLY    (0x800L)
+#define ES_RIGHT       (0x2L)
+#define ES_UPPERCASE   (0x8L)
+#define ES_WANTRETURN  (0x1000L)
+#define LBS_DISABLENOSCROLL    (0x1000L)
+#define LBS_EXTENDEDSEL        (0x800L)
+#define LBS_HASSTRINGS (0x40L)
+#define LBS_MULTICOLUMN        (0x200L)
+#define LBS_MULTIPLESEL        (0x8L)
+#define LBS_NODATA     (0x2000L)
+#define LBS_NOINTEGRALHEIGHT   (0x100L)
+#define LBS_NOREDRAW   (0x4L)
+#define LBS_NOSEL      (0x4000L)
+#define LBS_NOTIFY     (0x1L)
+#define LBS_OWNERDRAWFIXED     (0x10L)
+#define LBS_OWNERDRAWVARIABLE  (0x20L)
+#define LBS_SORT       (0x2L)
+#define LBS_STANDARD   (0xa00003L)
+#define LBS_USETABSTOPS        (0x80L)
+#define LBS_WANTKEYBOARDINPUT  (0x400L)
+#define SBS_BOTTOMALIGN        (0x4L)
+#define SBS_HORZ       (0L)
+#define SBS_LEFTALIGN  (0x2L)
+#define SBS_RIGHTALIGN (0x4L)
+#define SBS_SIZEBOX    (0x8L)
+#define SBS_SIZEBOXBOTTOMRIGHTALIGN    (0x4L)
+#define SBS_SIZEBOXTOPLEFTALIGN        (0x2L)
+#define SBS_SIZEGRIP   (0x10L)
+#define SBS_TOPALIGN   (0x2L)
+#define SBS_VERT       (0x1L)
+#define SS_BITMAP      (0xeL)
+#define SS_BLACKFRAME  (0x7L)
+#define SS_BLACKRECT   (0x4L)
+#define SS_CENTER      (0x1L)
+#define SS_CENTERIMAGE (0x200L)
+#define SS_ENHMETAFILE (0xfL)
+#define SS_ETCHEDFRAME (0x12L)
+#define SS_ETCHEDHORZ  (0x10L)
+#define SS_ETCHEDVERT  (0x11L)
+#define SS_GRAYFRAME   (0x8L)
+#define SS_GRAYRECT    (0x5L)
+#define SS_ICON        (0x3L)
+#define SS_LEFT        (0L)
+#define SS_LEFTNOWORDWRAP      (0xcL)
+#define SS_NOPREFIX    (0x80L)
+#define SS_NOTIFY      (0x100L)
+#define SS_OWNERDRAW   (0xdL)
+#define SS_REALSIZEIMAGE       (0x800L)
+#define SS_RIGHT       (0x2L)
+#define SS_RIGHTJUST   (0x400L)
+#define SS_SIMPLE      (0xbL)
+#define SS_SUNKEN      (0x1000L)
+#define SS_USERITEM     (0xaL)
+#define SS_WHITEFRAME  (0x9L)
+#define SS_WHITERECT   (0x6L)
+#define DS_3DLOOK      (0x4L)
+#define DS_ABSALIGN    (0x1L)
+#define DS_CENTER      (0x800L)
+#define DS_CENTERMOUSE (0x1000L)
+#define DS_CONTEXTHELP (0x2000L)
+#define DS_CONTROL     (0x400L)
+#define DS_FIXEDSYS    (0x8L)
+#define DS_LOCALEDIT   (0x20L)
+#define DS_MODALFRAME  (0x80L)
+#define DS_NOFAILCREATE        (0x10L)
+#define DS_NOIDLEMSG   (0x100L)
+#define DS_SETFONT     (0x40L)
+#define DS_SETFOREGROUND       (0x200L)
+#define DS_SYSMODAL    (0x2L)
+
+/* A dialog control.  */
+
+struct dialog_control
+{
+  /* Next control.  */
+  struct dialog_control *next;
+  /* ID.  */
+  unsigned short id;
+  /* Style.  */
+  unsigned long style;
+  /* Extended style.  */
+  unsigned long exstyle;
+  /* X coordinate.  */
+  unsigned short x;
+  /* Y coordinate.  */
+  unsigned short y;
+  /* Width.  */
+  unsigned short width;
+  /* Height.  */
+  unsigned short height;
+  /* Class name.  */
+  struct res_id class;
+  /* Associated text.  */
+  struct res_id text;
+  /* Extra data for the window procedure.  */
+  struct rcdata_item *data;
+  /* Help ID.  Only used in an extended dialog.  */
+  unsigned long help;
+};
+
+/* Control classes.  These can be used as the ID field in a struct
+   dialog_control.  */
+
+#define CTL_BUTTON     0x80
+#define CTL_EDIT       0x81
+#define CTL_STATIC     0x82
+#define CTL_LISTBOX    0x83
+#define CTL_SCROLLBAR  0x84
+#define CTL_COMBOBOX   0x85
+
+/* A fontdir resource is a list of fontdir structures.  */
+
+struct fontdir
+{
+  struct fontdir *next;
+  /* Index of font entry.  */
+  short index;
+  /* Length of font information.  */
+  unsigned long length;
+  /* Font information. */
+  const unsigned char *data;
+};
+
+/* A group_icon resource is a list of group_icon structures.  */
+
+struct group_icon
+{
+  /* Next icon in group.  */
+  struct group_icon *next;
+  /* Width.  */
+  unsigned char width;
+  /* Height.  */
+  unsigned char height;
+  /* Color count.  */
+  unsigned char colors;
+  /* Planes.  */
+  unsigned short planes;
+  /* Bits per pixel.  */
+  unsigned short bits;
+  /* Number of bytes in cursor resource.  */
+  unsigned long bytes;
+  /* Index of cursor resource.  */
+  unsigned short index;
+};
+
+/* A menu resource.  */
+
+struct menu
+{
+  /* List of menuitems.  */
+  struct menuitem *items;
+  /* Help ID.  I don't think there is any way to set this in an rc
+     file, but it can appear in the binary format.  */
+  unsigned long help;
+};
+
+/* A menu resource is a list of menuitem structures.  */
+
+struct menuitem
+{
+  /* Next menuitem.  */
+  struct menuitem *next;
+  /* Type.  In a normal menu, rather than a menuex, this is the flags
+     field.  */
+  unsigned long type;
+  /* State.  This is only used in a menuex.  */
+  unsigned long state;
+  /* Id.  */
+  unsigned short id;
+  /* Unicode text.  */
+  unichar *text;
+  /* Popup menu items for a popup.  */
+  struct menuitem *popup;
+  /* Help ID.  This is only used in a menuex.  */
+  unsigned long help;
+};
+
+/* Menu item flags.  These can appear in the flags field of a struct
+   menuitem.  */
+
+#define MENUITEM_GRAYED                0x001
+#define MENUITEM_INACTIVE      0x002
+#define MENUITEM_BITMAP                0x004
+#define MENUITEM_OWNERDRAW     0x100
+#define MENUITEM_CHECKED       0x008
+#define MENUITEM_POPUP         0x010
+#define MENUITEM_MENUBARBREAK  0x020
+#define MENUITEM_MENUBREAK     0x040
+#define MENUITEM_ENDMENU       0x080
+#define MENUITEM_HELP         0x4000
+
+/* An rcdata resource is a pointer to a list of rcdata_item
+   structures.  */
+
+struct rcdata_item
+{
+  /* Next data item.  */
+  struct rcdata_item *next;
+  /* Type of data.  */
+  enum
+  {
+    RCDATA_WORD,
+    RCDATA_DWORD,
+    RCDATA_STRING,
+    RCDATA_WSTRING,
+    RCDATA_BUFFER
+  } type;
+  union
+  {
+    unsigned int word;
+    unsigned long dword;
+    struct
+    {
+      unsigned long length;
+      const char *s;
+    } string;
+    struct
+    {
+      unsigned long length;
+      const unichar *w;
+    } wstring;
+    struct
+    {
+      unsigned long length;
+      const unsigned char *data;
+    } buffer;
+  } u;
+};
+
+/* A stringtable resource is a pointer to a stringtable structure.  */
+
+struct stringtable
+{
+  /* Each stringtable resource is a list of 16 unicode strings.  */
+  struct
+  {
+    /* Length of string.  */
+    int length;
+    /* String data if length > 0.  */
+    unichar *string;
+  } strings[16];
+};
+
+/* A versioninfo resource points to a versioninfo structure.  */
+
+struct versioninfo
+{
+  /* Fixed version information.  */
+  struct fixed_versioninfo *fixed;
+  /* Variable version information.  */
+  struct ver_info *var;
+};
+
+/* The fixed portion of a versioninfo resource.  */
+
+struct fixed_versioninfo
+{
+  /* The file version, which is two 32 bit integers.  */
+  unsigned long file_version_ms;
+  unsigned long file_version_ls;
+  /* The product version, which is two 32 bit integers.  */
+  unsigned long product_version_ms;
+  unsigned long product_version_ls;
+  /* The file flags mask.  */
+  unsigned long file_flags_mask;
+  /* The file flags.  */
+  unsigned long file_flags;
+  /* The OS type.  */
+  unsigned long file_os;
+  /* The file type.  */
+  unsigned long file_type;
+  /* The file subtype.  */
+  unsigned long file_subtype;
+  /* The date, which in Windows is two 32 bit integers.  */
+  unsigned long file_date_ms;
+  unsigned long file_date_ls;
+};
+
+/* A list of variable version information.  */
+
+struct ver_info
+{
+  /* Next item.  */
+  struct ver_info *next;
+  /* Type of data.  */
+  enum { VERINFO_STRING, VERINFO_VAR } type;
+  union
+  {
+    /* StringFileInfo data.  */
+    struct
+    {
+      /* Language.  */
+      unichar *language;
+      /* Strings.  */
+      struct ver_stringinfo *strings;
+    } string;
+    /* VarFileInfo data.  */
+    struct
+    {
+      /* Key.  */
+      unichar *key;
+      /* Values.  */
+      struct ver_varinfo *var;
+    } var;
+  } u;
+};
+
+/* A list of string version information.  */
+
+struct ver_stringinfo
+{
+  /* Next string.  */
+  struct ver_stringinfo *next;
+  /* Key.  */
+  unichar *key;
+  /* Value.  */
+  unichar *value;
+};
+
+/* A list of variable version information.  */
+
+struct ver_varinfo
+{
+  /* Next item.  */
+  struct ver_varinfo *next;
+  /* Language ID.  */
+  unsigned short language;
+  /* Character set ID.  */
+  unsigned short charset;
+};
+
+/* This structure is used when converting resource information to
+   binary.  */
+
+struct bindata
+{
+  /* Next data.  */
+  struct bindata *next;
+  /* Length of data.  */
+  unsigned long length;
+  /* Data.  */
+  unsigned char *data;
+};
+
+/* Function declarations.  */
+
+extern struct res_directory *read_rc_file
+  PARAMS ((const char *, const char *, const char *, int));
+extern struct res_directory *read_res_file PARAMS ((const char *));
+extern struct res_directory *read_coff_rsrc
+  PARAMS ((const char *, const char *));
+extern void write_rc_file
+  PARAMS ((const char *, const struct res_directory *));
+extern void write_res_file
+  PARAMS ((const char *, const struct res_directory *));
+extern void write_coff_file
+  PARAMS ((const char *, const char *, const struct res_directory *));
+
+extern struct res_resource *bin_to_res
+  PARAMS ((struct res_id, const unsigned char *, unsigned long, int));
+extern struct bindata *res_to_bin PARAMS ((const struct res_resource *, int));
+
+extern FILE *open_file_search
+  PARAMS ((const char *, const char *, const char *, char **));
+
+extern PTR res_alloc PARAMS ((size_t));
+extern PTR reswr_alloc PARAMS ((size_t));
+
+/* Resource ID handling.  */
+
+extern int res_id_cmp PARAMS ((struct res_id, struct res_id));
+extern void res_id_print PARAMS ((FILE *, struct res_id, int));
+extern void res_ids_print PARAMS ((FILE *, int, const struct res_id *));
+extern void res_string_to_id PARAMS ((struct res_id *, const char *));
+
+/* Manipulation of the resource tree.  */
+
+extern struct res_resource *define_resource
+  PARAMS ((struct res_directory **, int, const struct res_id *, int));
+extern struct res_resource *define_standard_resource
+  PARAMS ((struct res_directory **, int, struct res_id, int, int));
+
+extern int extended_dialog PARAMS ((const struct dialog *));
+extern int extended_menu PARAMS ((const struct menu *));
+
+/* Communication between the rc file support and the parser and lexer.  */
+
+extern int yydebug;
+extern FILE *yyin;
+extern char *rc_filename;
+extern int rc_lineno;
+extern int yyparse PARAMS ((void));
+extern int yylex PARAMS ((void));
+extern void yyerror PARAMS ((const char *));
+extern void rcparse_warning PARAMS ((const char *));
+extern void rcparse_set_language PARAMS ((int));
+extern void rcparse_discard_strings PARAMS ((void));
+extern void rcparse_rcdata PARAMS ((void));
+extern void rcparse_normal PARAMS ((void));
+
+extern void define_accelerator
+  PARAMS ((struct res_id, const struct res_res_info *, struct accelerator *));
+extern void define_bitmap
+  PARAMS ((struct res_id, const struct res_res_info *, const char *));
+extern void define_cursor
+  PARAMS ((struct res_id, const struct res_res_info *, const char *));
+extern void define_dialog
+  PARAMS ((struct res_id, const struct res_res_info *, const struct dialog *));
+extern struct dialog_control *define_control
+  PARAMS ((const char *, unsigned long, unsigned long, unsigned long,
+          unsigned long, unsigned long, unsigned long, unsigned long,
+          unsigned long));
+extern void define_font
+  PARAMS ((struct res_id, const struct res_res_info *, const char *));
+extern void define_icon
+  PARAMS ((struct res_id, const struct res_res_info *, const char *));
+extern void define_menu
+  PARAMS ((struct res_id, const struct res_res_info *, struct menuitem *));
+extern struct menuitem *define_menuitem
+  PARAMS ((const char *, int, unsigned long, unsigned long, unsigned long,
+          struct menuitem *));
+extern void define_messagetable
+  PARAMS ((struct res_id, const struct res_res_info *, const char *));
+extern void define_rcdata
+  PARAMS ((struct res_id, const struct res_res_info *, struct rcdata_item *));
+extern struct rcdata_item *define_rcdata_string
+  PARAMS ((const char *, unsigned long));
+extern struct rcdata_item *define_rcdata_number PARAMS ((unsigned long, int));
+extern void define_stringtable
+  PARAMS ((const struct res_res_info *, unsigned long, const char *));
+extern void define_user_data
+  PARAMS ((struct res_id, struct res_id, const struct res_res_info *,
+          struct rcdata_item *));
+extern void define_user_file
+  PARAMS ((struct res_id, struct res_id, const struct res_res_info *,
+          const char *));
+extern void define_versioninfo
+  PARAMS ((struct res_id, int, struct fixed_versioninfo *,
+          struct ver_info *));
+extern struct ver_info *append_ver_stringfileinfo
+  PARAMS ((struct ver_info *, const char *, struct ver_stringinfo *));
+extern struct ver_info *append_ver_varfileinfo
+  PARAMS ((struct ver_info *, const char *, struct ver_varinfo *));
+extern struct ver_stringinfo *append_verval
+  PARAMS ((struct ver_stringinfo *, const char *, const char *));
+extern struct ver_varinfo *append_vertrans
+  PARAMS ((struct ver_varinfo *, unsigned long, unsigned long));
diff --git a/binutils/winduni.c b/binutils/winduni.c
new file mode 100644 (file)
index 0000000..d79f47a
--- /dev/null
@@ -0,0 +1,147 @@
+/* winduni.c -- unicode support for the windres program.
+   Copyright 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file contains unicode support routines for the windres
+   program.  Ideally, we would have generic unicode support which
+   would work on all systems.  However, we don't.  Instead, on a
+   Windows host, we are prepared to call some Windows routines.  This
+   means that we will generate different output on Windows and Unix
+   hosts, but that seems better than not really supporting unicode at
+   all.  */
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "winduni.h"
+
+#include <ctype.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+/* Convert an ASCII string to a unicode string.  We just copy it,
+   expanding chars to shorts, rather than doing something intelligent.  */
+
+void
+unicode_from_ascii (length, unicode, ascii)
+     int *length;
+     unichar **unicode;
+     const char *ascii;
+{
+  int len;
+  const char *s;
+  unsigned short *w;
+
+  len = strlen (ascii);
+
+  if (length != NULL)
+    *length = len;
+
+  *unicode = ((unichar *) res_alloc ((len + 1) * sizeof (unichar)));
+
+#ifdef _WIN32
+  /* FIXME: On Windows, we should be using MultiByteToWideChar to set
+     the length.  */
+  MultiByteToWideChar (CP_ACP, 0, ascii, len + 1, *unicode, len + 1);
+#else
+  for (s = ascii, w = *unicode; *s != '\0'; s++, w++)
+    *w = *s & 0xff;
+  *w = 0;
+#endif
+}
+
+/* Print the unicode string UNICODE to the file E.  LENGTH is the
+   number of characters to print, or -1 if we should print until the
+   end of the string.  FIXME: On a Windows host, we should be calling
+   some Windows function, probably WideCharToMultiByte.  */
+
+void
+unicode_print (e, unicode, length)
+     FILE *e;
+     const unichar *unicode;
+     int length;
+{
+  while (1)
+    {
+      unichar ch;
+
+      if (length == 0)
+       return;
+      if (length > 0)
+       --length;
+
+      ch = *unicode;
+
+      if (ch == 0 && length < 0)
+       return;
+
+      ++unicode;
+
+      if ((ch & 0x7f) == ch)
+       {
+         if (ch == '\\')
+           fputs ("\\", e);
+         else if (isprint (ch))
+           putc (ch, e);
+         else
+           {
+             switch (ch)
+               {
+               case ESCAPE_A:
+                 fputs ("\\a", e);
+                 break;
+
+               case ESCAPE_B:
+                 fputs ("\\b", e);
+                 break;
+
+               case ESCAPE_F:
+                 fputs ("\\f", e);
+                 break;
+
+               case ESCAPE_N:
+                 fputs ("\\n", e);
+                 break;
+
+               case ESCAPE_R:
+                 fputs ("\\r", e);
+                 break;
+
+               case ESCAPE_T:
+                 fputs ("\\t", e);
+                 break;
+
+               case ESCAPE_V:
+                 fputs ("\\v", e);
+                 break;
+
+               default:
+                 fprintf (e, "\\%03o", (unsigned int) ch);
+                 break;
+               }
+           }
+       }
+      else if ((ch & 0xff) == ch)
+       fprintf (e, "\\%03o", (unsigned int) ch);
+      else
+       fprintf (e, "\\x%x", (unsigned int) ch);
+    }
+}
diff --git a/binutils/winduni.h b/binutils/winduni.h
new file mode 100644 (file)
index 0000000..13a9af2
--- /dev/null
@@ -0,0 +1,60 @@
+/* winduni.h -- header file for unicode support for windres program.
+   Copyright 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#include <ansidecl.h>
+
+/* This header file declares the types and functions we use for
+   unicode support in windres.  Our unicode support is very limited at
+   present.
+
+   We don't put this stuff in windres.h so that winduni.c doesn't have
+   to include windres.h.  winduni.c needs to includes windows.h, and
+   that would conflict with the definitions of Windows macros we
+   already have in windres.h.  */
+
+/* We use this type to hold a unicode character.  */
+
+typedef unsigned short unichar;
+
+/* Escape character translations.  */
+
+#define ESCAPE_A (007)
+#define ESCAPE_B (010)
+#define ESCAPE_F (014)
+#define ESCAPE_N (012)
+#define ESCAPE_R (015)
+#define ESCAPE_T (011)
+#define ESCAPE_V (013)
+
+/* Convert an ASCII string to a unicode string.  */
+
+extern void unicode_from_ascii
+  PARAMS ((int *, unichar **, const char *));
+
+/* Print a unicode string to a file.  */
+
+extern void unicode_print PARAMS ((FILE *, const unichar *, int));
+
+/* Windres support routine called by unicode_from_ascii.  This is both
+   here and in windres.h.  It should probably be in a separate header
+   file, but it hardly seems worth it for one function.  */
+
+extern PTR res_alloc PARAMS ((size_t));
diff --git a/binutils/wrstabs.c b/binutils/wrstabs.c
new file mode 100644 (file)
index 0000000..e428174
--- /dev/null
@@ -0,0 +1,2416 @@
+/* wrstabs.c -- Output stabs debugging information
+   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor <ian@cygnus.com>.
+
+   This file is part of 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 2 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+/* This file contains code which writes out stabs debugging
+   information.  */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
+#include "debug.h"
+#include "budbg.h"
+
+/* Meaningless definition needs by aout64.h.  FIXME.  */
+#define BYTES_IN_WORD 4
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+
+/* The size of a stabs symbol.  This presumes 32 bit values.  */
+
+#define STAB_SYMBOL_SIZE (12)
+
+/* An entry in a string hash table.  */
+
+struct string_hash_entry
+{
+  struct bfd_hash_entry root;
+  /* Next string in this table.  */
+  struct string_hash_entry *next;
+  /* Index in string table.  */
+  long index;
+  /* Size of type if this is a typedef.  */
+  unsigned int size;
+};
+
+/* A string hash table.  */
+
+struct string_hash_table
+{
+  struct bfd_hash_table table;
+};
+
+/* The type stack.  Each element on the stack is a string.  */
+
+struct stab_type_stack
+{
+  /* The next element on the stack.  */
+  struct stab_type_stack *next;
+  /* This element as a string.  */
+  char *string;
+  /* The type index of this element.  */
+  long index;
+  /* The size of the type.  */
+  unsigned int size;
+  /* Whether type string defines a new type.  */
+  boolean definition;
+  /* String defining struct fields.  */
+  char *fields;
+  /* NULL terminated array of strings defining base classes for a
+     class.  */
+  char **baseclasses;
+  /* String defining class methods.  */
+  char *methods;
+  /* String defining vtable pointer for a class.  */
+  char *vtable;
+};
+
+/* This structure is used to keep track of type indices for tagged
+   types.  */
+
+struct stab_tag
+{
+  /* The type index.  */
+  long index;
+  /* The tag name.  */
+  const char *tag;
+  /* The kind of type.  This is set to DEBUG_KIND_ILLEGAL when the
+     type is defined.  */
+  enum debug_type_kind kind;
+  /* The size of the struct.  */
+  unsigned int size;
+};
+
+/* We remember various sorts of type indices.  They are not related,
+   but, for convenience, we keep all the information in this
+   structure.  */
+
+struct stab_type_cache
+{
+  /* The void type index.  */
+  long void_type;
+  /* Signed integer type indices, indexed by size - 1.  */
+  long signed_integer_types[8];
+  /* Unsigned integer type indices, indexed by size - 1.  */
+  long unsigned_integer_types[8];
+  /* Floating point types, indexed by size - 1.  */
+  long float_types[16];
+  /* Pointers to types, indexed by the type index.  */
+  long *pointer_types;
+  size_t pointer_types_alloc;
+  /* Functions returning types, indexed by the type index.  */
+  long *function_types;
+  size_t function_types_alloc;
+  /* References to types, indexed by the type index.  */
+  long *reference_types;
+  size_t reference_types_alloc;
+  /* Struct/union/class type indices, indexed by the struct id.  */
+  struct stab_tag *struct_types;
+  size_t struct_types_alloc;
+};
+
+/* This is the handle passed through debug_write.  */
+
+struct stab_write_handle
+{
+  /* The BFD.  */
+  bfd *abfd;
+  /* This buffer holds the symbols.  */
+  bfd_byte *symbols;
+  size_t symbols_size;
+  size_t symbols_alloc;
+  /* This is a list of hash table entries for the strings.  */
+  struct string_hash_entry *strings;
+  /* The last string hash table entry.  */
+  struct string_hash_entry *last_string;
+  /* The size of the strings.  */
+  size_t strings_size;
+  /* This hash table eliminates duplicate strings.  */
+  struct string_hash_table strhash;
+  /* The type stack.  */
+  struct stab_type_stack *type_stack;
+  /* The next type index.  */
+  long type_index;
+  /* The type cache.  */
+  struct stab_type_cache type_cache;
+  /* A mapping from typedef names to type indices.  */
+  struct string_hash_table typedef_hash;
+  /* If this is not -1, it is the offset to the most recent N_SO
+     symbol, and the value of that symbol needs to be set.  */
+  long so_offset;
+  /* If this is not -1, it is the offset to the most recent N_FUN
+     symbol, and the value of that symbol needs to be set.  */
+  long fun_offset;
+  /* The last text section address seen.  */
+  bfd_vma last_text_address;
+  /* The block nesting depth.  */
+  unsigned int nesting;
+  /* The function address.  */
+  bfd_vma fnaddr;
+  /* A pending LBRAC symbol.  */
+  bfd_vma pending_lbrac;
+  /* The current line number file name.  */
+  const char *lineno_filename;
+};
+
+static struct bfd_hash_entry *string_hash_newfunc
+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean stab_write_symbol
+  PARAMS ((struct stab_write_handle *, int, int, bfd_vma, const char *));
+static boolean stab_push_string
+  PARAMS ((struct stab_write_handle *, const char *, long, boolean,
+          unsigned int));
+static boolean stab_push_defined_type
+  PARAMS ((struct stab_write_handle *, long, unsigned int));
+static char *stab_pop_type PARAMS ((struct stab_write_handle *));
+static boolean stab_modify_type
+  PARAMS ((struct stab_write_handle *, int, unsigned int, long **, size_t *));
+static long stab_get_struct_index
+  PARAMS ((struct stab_write_handle *, const char *, unsigned int,
+          enum debug_type_kind, unsigned int *));
+static boolean stab_class_method_var
+  PARAMS ((struct stab_write_handle *, const char *, enum debug_visibility,
+          boolean, boolean, boolean, bfd_vma, boolean));
+
+static boolean stab_start_compilation_unit PARAMS ((PTR, const char *));
+static boolean stab_start_source PARAMS ((PTR, const char *));
+static boolean stab_empty_type PARAMS ((PTR));
+static boolean stab_void_type PARAMS ((PTR));
+static boolean stab_int_type PARAMS ((PTR, unsigned int, boolean));
+static boolean stab_float_type PARAMS ((PTR, unsigned int));
+static boolean stab_complex_type PARAMS ((PTR, unsigned int));
+static boolean stab_bool_type PARAMS ((PTR, unsigned int));
+static boolean stab_enum_type
+  PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
+static boolean stab_pointer_type PARAMS ((PTR));
+static boolean stab_function_type PARAMS ((PTR, int, boolean));
+static boolean stab_reference_type PARAMS ((PTR));
+static boolean stab_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
+static boolean stab_array_type
+  PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
+static boolean stab_set_type PARAMS ((PTR, boolean));
+static boolean stab_offset_type PARAMS ((PTR));
+static boolean stab_method_type PARAMS ((PTR, boolean, int, boolean));
+static boolean stab_const_type PARAMS ((PTR));
+static boolean stab_volatile_type PARAMS ((PTR));
+static boolean stab_start_struct_type
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
+static boolean stab_struct_field
+  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
+static boolean stab_end_struct_type PARAMS ((PTR));
+static boolean stab_start_class_type
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+          boolean));
+static boolean stab_class_static_member
+  PARAMS ((PTR, const char *, const char *, enum debug_visibility));
+static boolean stab_class_baseclass
+  PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
+static boolean stab_class_start_method PARAMS ((PTR, const char *));
+static boolean stab_class_method_variant
+  PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
+          bfd_vma, boolean));
+static boolean stab_class_static_method_variant
+  PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
+static boolean stab_class_end_method PARAMS ((PTR));
+static boolean stab_end_class_type PARAMS ((PTR));
+static boolean stab_typedef_type PARAMS ((PTR, const char *));
+static boolean stab_tag_type
+  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
+static boolean stab_typdef PARAMS ((PTR, const char *));
+static boolean stab_tag PARAMS ((PTR, const char *));
+static boolean stab_int_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean stab_float_constant PARAMS ((PTR, const char *, double));
+static boolean stab_typed_constant PARAMS ((PTR, const char *, bfd_vma));
+static boolean stab_variable
+  PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
+static boolean stab_start_function PARAMS ((PTR, const char *, boolean));
+static boolean stab_function_parameter
+  PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
+static boolean stab_start_block PARAMS ((PTR, bfd_vma));
+static boolean stab_end_block PARAMS ((PTR, bfd_vma));
+static boolean stab_end_function PARAMS ((PTR));
+static boolean stab_lineno
+  PARAMS ((PTR, const char *, unsigned long, bfd_vma));
+
+static const struct debug_write_fns stab_fns =
+{
+  stab_start_compilation_unit,
+  stab_start_source,
+  stab_empty_type,
+  stab_void_type,
+  stab_int_type,
+  stab_float_type,
+  stab_complex_type,
+  stab_bool_type,
+  stab_enum_type,
+  stab_pointer_type,
+  stab_function_type,
+  stab_reference_type,
+  stab_range_type,
+  stab_array_type,
+  stab_set_type,
+  stab_offset_type,
+  stab_method_type,
+  stab_const_type,
+  stab_volatile_type,
+  stab_start_struct_type,
+  stab_struct_field,
+  stab_end_struct_type,
+  stab_start_class_type,
+  stab_class_static_member,
+  stab_class_baseclass,
+  stab_class_start_method,
+  stab_class_method_variant,
+  stab_class_static_method_variant,
+  stab_class_end_method,
+  stab_end_class_type,
+  stab_typedef_type,
+  stab_tag_type,
+  stab_typdef,
+  stab_tag,
+  stab_int_constant,
+  stab_float_constant,
+  stab_typed_constant,
+  stab_variable,
+  stab_start_function,
+  stab_function_parameter,
+  stab_start_block,
+  stab_end_block,
+  stab_end_function,
+  stab_lineno
+};
+\f
+/* Routine to create an entry in a string hash table.  */
+
+static struct bfd_hash_entry *
+string_hash_newfunc (entry, table, string)
+     struct bfd_hash_entry *entry;
+     struct bfd_hash_table *table;
+     const char *string;
+{
+  struct string_hash_entry *ret = (struct string_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (ret == (struct string_hash_entry *) NULL)
+    ret = ((struct string_hash_entry *)
+          bfd_hash_allocate (table, sizeof (struct string_hash_entry)));
+  if (ret == (struct string_hash_entry *) NULL)
+    return NULL;
+
+  /* Call the allocation method of the superclass.  */
+  ret = ((struct string_hash_entry *)
+        bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+  if (ret)
+    {
+      /* Initialize the local fields.  */
+      ret->next = NULL;
+      ret->index = -1;
+      ret->size = 0;
+    }
+
+  return (struct bfd_hash_entry *) ret;
+}
+
+/* Look up an entry in a string hash table.  */
+
+#define string_hash_lookup(t, string, create, copy) \
+  ((struct string_hash_entry *) \
+   bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
+
+/* Add a symbol to the stabs debugging information we are building.  */
+
+static boolean
+stab_write_symbol (info, type, desc, value, string)
+     struct stab_write_handle *info;
+     int type;
+     int desc;
+     bfd_vma value;
+     const char *string;
+{
+  bfd_size_type strx;
+  bfd_byte sym[STAB_SYMBOL_SIZE];
+
+  if (string == NULL)
+    strx = 0;
+  else
+    {
+      struct string_hash_entry *h;
+
+      h = string_hash_lookup (&info->strhash, string, true, true);
+      if (h == NULL)
+       {
+         fprintf (stderr, _("string_hash_lookup failed: %s\n"),
+                  bfd_errmsg (bfd_get_error ()));
+         return false;
+       }
+      if (h->index != -1)
+       strx = h->index;
+      else
+       {
+         strx = info->strings_size;
+         h->index = strx;
+         if (info->last_string == NULL)
+           info->strings = h;
+         else
+           info->last_string->next = h;
+         info->last_string = h;
+         info->strings_size += strlen (string) + 1;
+       }
+    }
+
+  /* This presumes 32 bit values.  */
+  bfd_put_32 (info->abfd, strx, sym);
+  bfd_put_8 (info->abfd, type, sym + 4);
+  bfd_put_8 (info->abfd, 0, sym + 5);
+  bfd_put_16 (info->abfd, desc, sym + 6);
+  bfd_put_32 (info->abfd, value, sym + 8);
+
+  if (info->symbols_size + STAB_SYMBOL_SIZE > info->symbols_alloc)
+    {
+      info->symbols_alloc *= 2;
+      info->symbols = (bfd_byte *) xrealloc (info->symbols,
+                                            info->symbols_alloc);
+    }
+
+  memcpy (info->symbols + info->symbols_size, sym, STAB_SYMBOL_SIZE);
+
+  info->symbols_size += STAB_SYMBOL_SIZE;
+
+  return true;
+}
+
+/* Push a string on to the type stack.  */
+
+static boolean
+stab_push_string (info, string, index, definition, size)
+     struct stab_write_handle *info;
+     const char *string;
+     long index;
+     boolean definition;
+     unsigned int size;
+{
+  struct stab_type_stack *s;
+
+  s = (struct stab_type_stack *) xmalloc (sizeof *s);
+  s->string = xstrdup (string);
+  s->index = index;
+  s->definition = definition;
+  s->size = size;
+
+  s->fields = NULL;
+  s->baseclasses = NULL;
+  s->methods = NULL;
+  s->vtable = NULL;
+
+  s->next = info->type_stack;
+  info->type_stack = s;
+
+  return true;
+}
+
+/* Push a type index which has already been defined.  */
+
+static boolean
+stab_push_defined_type (info, index, size)
+     struct stab_write_handle *info;
+     long index;
+     unsigned int size;
+{
+  char buf[20];
+
+  sprintf (buf, "%ld", index);
+  return stab_push_string (info, buf, index, false, size);
+}
+
+/* Pop a type off the type stack.  The caller is responsible for
+   freeing the string.  */
+
+static char *
+stab_pop_type (info)
+     struct stab_write_handle *info;
+{
+  struct stab_type_stack *s;
+  char *ret;
+
+  s = info->type_stack;
+  assert (s != NULL);
+
+  info->type_stack = s->next;
+
+  ret = s->string;
+
+  free (s);
+
+  return ret;
+}
+\f
+/* The general routine to write out stabs in sections debugging
+   information.  This accumulates the stabs symbols and the strings in
+   two obstacks.  We can't easily write out the information as we go
+   along, because we need to know the section sizes before we can
+   write out the section contents.  ABFD is the BFD and DHANDLE is the
+   handle for the debugging information.  This sets *PSYMS to point to
+   the symbols, *PSYMSIZE the size of the symbols, *PSTRINGS to the
+   strings, and *PSTRINGSIZE to the size of the strings.  */
+
+boolean
+write_stabs_in_sections_debugging_info (abfd, dhandle, psyms, psymsize,
+                                       pstrings, pstringsize)
+     bfd *abfd;
+     PTR dhandle;
+     bfd_byte **psyms;
+     bfd_size_type *psymsize;
+     bfd_byte **pstrings;
+     bfd_size_type *pstringsize;
+{
+  struct stab_write_handle info;
+  struct string_hash_entry *h;
+  bfd_byte *p;
+
+  info.abfd = abfd;
+
+  info.symbols_size = 0;
+  info.symbols_alloc = 500;
+  info.symbols = (bfd_byte *) xmalloc (info.symbols_alloc);
+
+  info.strings = NULL;
+  info.last_string = NULL;
+  /* Reserve 1 byte for a null byte.  */
+  info.strings_size = 1;
+
+  if (! bfd_hash_table_init (&info.strhash.table, string_hash_newfunc)
+      || ! bfd_hash_table_init (&info.typedef_hash.table, string_hash_newfunc))
+    {
+      fprintf (stderr, "bfd_hash_table_init_failed: %s\n",
+              bfd_errmsg (bfd_get_error ()));
+      return false;
+    }
+
+  info.type_stack = NULL;
+  info.type_index = 1;
+  memset (&info.type_cache, 0, sizeof info.type_cache);
+  info.so_offset = -1;
+  info.fun_offset = -1;
+  info.last_text_address = 0;
+  info.nesting = 0;
+  info.fnaddr = 0;
+  info.pending_lbrac = (bfd_vma) -1;
+
+  /* The initial symbol holds the string size.  */
+  if (! stab_write_symbol (&info, 0, 0, 0, (const char *) NULL))
+    return false;
+
+  /* Output an initial N_SO symbol.  */
+  info.so_offset = info.symbols_size;
+  if (! stab_write_symbol (&info, N_SO, 0, 0, bfd_get_filename (abfd)))
+    return false;
+
+  if (! debug_write (dhandle, &stab_fns, (PTR) &info))
+    return false;
+
+  assert (info.pending_lbrac == (bfd_vma) -1);
+
+  /* Output a trailing N_SO.  */
+  if (! stab_write_symbol (&info, N_SO, 0, info.last_text_address,
+                          (const char *) NULL))
+    return false;
+
+  /* Put the string size in the initial symbol.  */
+  bfd_put_32 (abfd, info.strings_size, info.symbols + 8);
+
+  *psyms = info.symbols;
+  *psymsize = info.symbols_size;
+
+  *pstringsize = info.strings_size;
+  *pstrings = (bfd_byte *) xmalloc (info.strings_size);
+
+  p = *pstrings;
+  *p++ = '\0';
+  for (h = info.strings; h != NULL; h = h->next)
+    {
+      strcpy ((char *) p, h->root.string);
+      p += strlen ((char *) p) + 1;
+    }
+
+  return true;
+}
+
+/* Start writing out information for a compilation unit.  */
+
+static boolean
+stab_start_compilation_unit (p, filename)
+     PTR p;
+     const char *filename;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  /* We would normally output an N_SO symbol here.  However, that
+     would force us to reset all of our type information.  I think we
+     will be better off just outputting an N_SOL symbol, and not
+     worrying about splitting information between files.  */
+
+  info->lineno_filename = filename;
+
+  return stab_write_symbol (info, N_SOL, 0, 0, filename);
+}
+
+/* Start writing out information for a particular source file.  */
+
+static boolean
+stab_start_source (p, filename)
+     PTR p;
+     const char *filename;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  /* FIXME: The symbol's value is supposed to be the text section
+     address.  However, we would have to fill it in later, and gdb
+     doesn't care, so we don't bother with it.  */
+
+  info->lineno_filename = filename;
+
+  return stab_write_symbol (info, N_SOL, 0, 0, filename);
+}
+
+/* Push an empty type.  This shouldn't normally happen.  We just use a
+   void type.  */
+
+static boolean
+stab_empty_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  /* We don't call stab_void_type if the type is not yet defined,
+     because that might screw up the typedef.  */
+
+  if (info->type_cache.void_type != 0)
+    return stab_push_defined_type (info, info->type_cache.void_type, 0);
+  else
+    {
+      long index;
+      char buf[40];
+
+      index = info->type_index;
+      ++info->type_index;
+
+      sprintf (buf, "%ld=%ld", index, index);
+
+      return stab_push_string (info, buf, index, false, 0);
+    }
+}
+
+/* Push a void type.  */
+
+static boolean
+stab_void_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  if (info->type_cache.void_type != 0)
+    return stab_push_defined_type (info, info->type_cache.void_type, 0);
+  else
+    {
+      long index;
+      char buf[40];
+
+      index = info->type_index;
+      ++info->type_index;
+
+      info->type_cache.void_type = index;
+
+      sprintf (buf, "%ld=%ld", index, index);
+
+      return stab_push_string (info, buf, index, true, 0);
+    }
+}
+
+/* Push an integer type.  */
+
+static boolean
+stab_int_type (p, size, unsignedp)
+     PTR p;
+     unsigned int size;
+     boolean unsignedp;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  long *cache;
+
+  if (size <= 0 || (size > sizeof (long) && size != 8))
+    {
+      fprintf (stderr, _("stab_int_type: bad size %u\n"), size);
+      return false;
+    }
+
+  if (unsignedp)
+    cache = info->type_cache.signed_integer_types;
+  else
+    cache = info->type_cache.unsigned_integer_types;
+
+  if (cache[size - 1] != 0)
+    return stab_push_defined_type (info, cache[size - 1], size);
+  else
+    {
+      long index;
+      char buf[100];
+
+      index = info->type_index;
+      ++info->type_index;
+
+      cache[size - 1] = index;
+
+      sprintf (buf, "%ld=r%ld;", index, index);
+      if (unsignedp)
+       {
+         strcat (buf, "0;");
+         if (size < sizeof (long))
+           sprintf (buf + strlen (buf), "%ld;", ((long) 1 << (size * 8)) - 1);
+         else if (size == sizeof (long))
+           strcat (buf, "-1;");
+         else if (size == 8)
+           strcat (buf, "01777777777777777777777;");
+         else
+           abort ();
+       }
+      else
+       {
+         if (size <= sizeof (long))
+           sprintf (buf + strlen (buf), "%ld;%ld;",
+                    (long) - ((unsigned long) 1 << (size * 8 - 1)),
+                    (long) (((unsigned long) 1 << (size * 8 - 1)) - 1));
+         else if (size == 8)
+           strcat (buf, "01000000000000000000000;0777777777777777777777;");
+         else
+           abort ();
+       }
+
+      return stab_push_string (info, buf, index, true, size);
+    }
+}
+
+/* Push a floating point type.  */
+
+static boolean
+stab_float_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  if (size > 0
+      && size - 1 < (sizeof info->type_cache.float_types
+                    / sizeof info->type_cache.float_types[0])
+      && info->type_cache.float_types[size - 1] != 0)
+    return stab_push_defined_type (info,
+                                  info->type_cache.float_types[size - 1],
+                                  size);
+  else
+    {
+      long index;
+      char *int_type;
+      char buf[50];
+
+      /* Floats are defined as a subrange of int.  */
+      if (! stab_int_type (info, 4, false))
+       return false;
+      int_type = stab_pop_type (info);
+
+      index = info->type_index;
+      ++info->type_index;
+
+      if (size > 0
+         && size - 1 < (sizeof info->type_cache.float_types
+                        / sizeof info->type_cache.float_types[0]))
+       info->type_cache.float_types[size - 1] = index;
+
+      sprintf (buf, "%ld=r%s;%u;0;", index, int_type, size);
+
+      free (int_type);
+
+      return stab_push_string (info, buf, index, true, size);
+    }
+}
+
+/* Push a complex type.  */
+
+static boolean
+stab_complex_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char buf[50];
+  long index;
+
+  index = info->type_index;
+  ++info->type_index;
+
+  sprintf (buf, "%ld=r%ld;%u;0;", index, index, size);
+
+  return stab_push_string (info, buf, index, true, size * 2);
+}
+
+/* Push a boolean type.  We use an XCOFF predefined type, since gdb
+   always recognizes them.  */
+
+static boolean
+stab_bool_type (p, size)
+     PTR p;
+     unsigned int size;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  long index;
+
+  switch (size)
+    {
+    case 1:
+      index = -21;
+      break;
+
+    case 2:
+      index = -22;
+      break;
+      
+    default:
+    case 4:
+      index = -16;
+      break;
+
+    case 8:
+      index = -33;
+      break;
+    }
+
+  return stab_push_defined_type (info, index, size);
+}
+
+/* Push an enum type.  */
+
+static boolean
+stab_enum_type (p, tag, names, vals)
+     PTR p;
+     const char *tag;
+     const char **names;
+     bfd_signed_vma *vals;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  size_t len;
+  const char **pn;
+  char *buf;
+  long index = 0;
+  bfd_signed_vma *pv;
+
+  if (names == NULL)
+    {
+      assert (tag != NULL);
+
+      buf = (char *) xmalloc (10 + strlen (tag));
+      sprintf (buf, "xe%s:", tag);
+      /* FIXME: The size is just a guess.  */
+      if (! stab_push_string (info, buf, 0, false, 4))
+       return false;
+      free (buf);
+      return true;
+    }
+
+  len = 10;
+  if (tag != NULL)
+    len += strlen (tag);
+  for (pn = names; *pn != NULL; pn++)
+    len += strlen (*pn) + 20;
+
+  buf = (char *) xmalloc (len);
+
+  if (tag == NULL)
+    strcpy (buf, "e");
+  else
+    {
+      index = info->type_index;
+      ++info->type_index;
+      sprintf (buf, "%s:T%ld=e", tag, index);
+    }
+
+  for (pn = names, pv = vals; *pn != NULL; pn++, pv++)
+    sprintf (buf + strlen (buf), "%s:%ld,", *pn, (long) *pv);
+  strcat (buf, ";");
+
+  if (tag == NULL)
+    {
+      /* FIXME: The size is just a guess.  */
+      if (! stab_push_string (info, buf, 0, false, 4))
+       return false;
+    }
+  else
+    {
+      /* FIXME: The size is just a guess.  */
+      if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)
+         || ! stab_push_defined_type (info, index, 4))
+       return false;
+    }
+
+  free (buf);
+
+  return true;
+}
+
+/* Push a modification of the top type on the stack.  Cache the
+   results in CACHE and CACHE_ALLOC.  */
+
+static boolean
+stab_modify_type (info, mod, size, cache, cache_alloc)
+     struct stab_write_handle *info;
+     int mod;
+     unsigned int size;
+     long **cache;
+     size_t *cache_alloc;
+{
+  long targindex;
+  long index;
+  char *s, *buf;
+
+  assert (info->type_stack != NULL);
+  targindex = info->type_stack->index;
+
+  if (targindex <= 0
+      || cache == NULL)
+    {
+      boolean definition;
+
+      /* Either the target type has no index, or we aren't caching
+         this modifier.  Either way we have no way of recording the
+         new type, so we don't bother to define one.  */
+      definition = info->type_stack->definition;
+      s = stab_pop_type (info);
+      buf = (char *) xmalloc (strlen (s) + 2);
+      sprintf (buf, "%c%s", mod, s);
+      free (s);
+      if (! stab_push_string (info, buf, 0, definition, size))
+       return false;
+      free (buf);
+    }
+  else
+    {
+      if ((size_t) targindex >= *cache_alloc)
+       {
+         size_t alloc;
+
+         alloc = *cache_alloc;
+         if (alloc == 0)
+           alloc = 10;
+         while ((size_t) targindex >= alloc)
+           alloc *= 2;
+         *cache = (long *) xrealloc (*cache, alloc * sizeof (long));
+         memset (*cache + *cache_alloc, 0,
+                 (alloc - *cache_alloc) * sizeof (long));
+         *cache_alloc = alloc;
+       }
+
+      index = (*cache)[targindex];
+      if (index != 0 && ! info->type_stack->definition)
+       {
+         /* We have already defined a modification of this type, and
+             the entry on the type stack is not a definition, so we
+             can safely discard it (we may have a definition on the
+             stack, even if we already defined a modification, if it
+             is a struct which we did not define at the time it was
+             referenced).  */
+         free (stab_pop_type (info));
+         if (! stab_push_defined_type (info, index, size))
+           return false;
+       }
+      else
+       {
+         index = info->type_index;
+         ++info->type_index;
+
+         s = stab_pop_type (info);
+         buf = (char *) xmalloc (strlen (s) + 20);
+         sprintf (buf, "%ld=%c%s", index, mod, s);
+         free (s);
+
+         (*cache)[targindex] = index;
+
+         if (! stab_push_string (info, buf, index, true, size))
+           return false;
+
+         free (buf);
+       }
+    }
+
+  return true;
+}  
+
+/* Push a pointer type.  */
+
+static boolean
+stab_pointer_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  /* FIXME: The size should depend upon the architecture.  */
+  return stab_modify_type (info, '*', 4, &info->type_cache.pointer_types,
+                          &info->type_cache.pointer_types_alloc);
+}
+
+/* Push a function type.  */
+
+static boolean
+stab_function_type (p, argcount, varargs)
+     PTR p;
+     int argcount;
+     boolean varargs;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  int i;
+
+  /* We have no way to represent the argument types, so we just
+     discard them.  However, if they define new types, we must output
+     them.  We do this by producing empty typedefs.  */
+  for (i = 0; i < argcount; i++)
+    {
+      if (! info->type_stack->definition)
+       free (stab_pop_type (info));
+      else
+       {
+         char *s, *buf;
+
+         s = stab_pop_type (info);
+
+         buf = (char *) xmalloc (strlen (s) + 3);
+         sprintf (buf, ":t%s", s);
+         free (s);
+
+         if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+           return false;
+
+         free (buf);
+       }
+    }
+
+  return stab_modify_type (info, 'f', 0, &info->type_cache.function_types,
+                          &info->type_cache.function_types_alloc);
+}
+
+/* Push a reference type.  */
+
+static boolean
+stab_reference_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  /* FIXME: The size should depend upon the architecture.  */
+  return stab_modify_type (info, '&', 4, &info->type_cache.reference_types,
+                          &info->type_cache.reference_types_alloc);
+}
+
+/* Push a range type.  */
+
+static boolean
+stab_range_type (p, low, high)
+     PTR p;
+     bfd_signed_vma low;
+     bfd_signed_vma high;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  unsigned int size;
+  char *s, *buf;
+
+  definition = info->type_stack->definition;
+  size = info->type_stack->size;
+
+  s = stab_pop_type (info);
+  buf = (char *) xmalloc (strlen (s) + 100);
+  sprintf (buf, "r%s;%ld;%ld;", s, (long) low, (long) high);
+  free (s);
+
+  if (! stab_push_string (info, buf, 0, definition, size))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Push an array type.  */
+
+static boolean
+stab_array_type (p, low, high, stringp)
+     PTR p;
+     bfd_signed_vma low;
+     bfd_signed_vma high;
+     boolean stringp;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  unsigned int element_size;
+  char *range, *element, *buf;
+  long index;
+  unsigned int size;
+
+  definition = info->type_stack->definition;
+  range = stab_pop_type (info);
+
+  definition = definition || info->type_stack->definition;
+  element_size = info->type_stack->size;
+  element = stab_pop_type (info);
+
+  buf = (char *) xmalloc (strlen (range) + strlen (element) + 100);
+
+  if (! stringp)
+    {
+      index = 0;
+      *buf = '\0';
+    }
+  else
+    {
+      /* We need to define a type in order to include the string
+         attribute.  */
+      index = info->type_index;
+      ++info->type_index;
+      definition = true;
+      sprintf (buf, "%ld=@S;", index);
+    }
+
+  sprintf (buf + strlen (buf), "ar%s;%ld;%ld;%s",
+          range, (long) low, (long) high, element);
+  free (range);
+  free (element);
+
+  if (high < low)
+    size = 0;
+  else
+    size = element_size * ((high - low) + 1);
+  if (! stab_push_string (info, buf, index, definition, size))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Push a set type.  */
+
+static boolean
+stab_set_type (p, bitstringp)
+     PTR p;
+     boolean bitstringp;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  char *s, *buf;
+  long index;
+
+  definition = info->type_stack->definition;
+
+  s = stab_pop_type (info);
+  buf = (char *) xmalloc (strlen (s) + 30);
+
+  if (! bitstringp)
+    {
+      *buf = '\0';
+      index = 0;
+    }
+  else
+    {
+      /* We need to define a type in order to include the string
+         attribute.  */
+      index = info->type_index;
+      ++info->type_index;
+      definition = true;
+      sprintf (buf, "%ld=@S;", index);
+    }
+
+  sprintf (buf + strlen (buf), "S%s", s);
+  free (s);
+
+  if (! stab_push_string (info, buf, index, definition, 0))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Push an offset type.  */
+
+static boolean
+stab_offset_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  char *target, *base, *buf;
+
+  definition = info->type_stack->definition;
+  target = stab_pop_type (info);
+
+  definition = definition || info->type_stack->definition;
+  base = stab_pop_type (info);
+
+  buf = (char *) xmalloc (strlen (target) + strlen (base) + 3);
+  sprintf (buf, "@%s,%s", base, target);
+  free (base);
+  free (target);
+
+  if (! stab_push_string (info, buf, 0, definition, 0))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Push a method type.  */
+
+static boolean
+stab_method_type (p, domainp, argcount, varargs)
+     PTR p;
+     boolean domainp;
+     int argcount;
+     boolean varargs;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  char *domain, *return_type, *buf;
+  char **args;
+  int i;
+  size_t len;
+
+  /* We don't bother with stub method types, because that would
+     require a mangler for C++ argument types.  This will waste space
+     in the debugging output.  */
+
+  /* We need a domain.  I'm not sure DOMAINP can ever be false,
+     anyhow.  */
+  if (! domainp)
+    {
+      if (! stab_empty_type (p))
+       return false;
+    }
+
+  definition = info->type_stack->definition;
+  domain = stab_pop_type (info);
+
+  /* A non-varargs function is indicated by making the last parameter
+     type be void.  */
+
+  if (argcount < 0)
+    {
+      args = NULL;
+      argcount = 0;
+    }
+  else if (argcount == 0)
+    {
+      if (varargs)
+       args = NULL;
+      else
+       {
+         args = (char **) xmalloc (1 * sizeof (*args));
+         if (! stab_empty_type (p))
+           return false;
+         definition = definition || info->type_stack->definition;
+         args[0] = stab_pop_type (info);
+         argcount = 1;
+       }
+    }
+  else
+    {
+      args = (char **) xmalloc ((argcount + 1) * sizeof (*args));
+      for (i = argcount - 1; i >= 0; i--)
+       {
+         definition = definition || info->type_stack->definition;
+         args[i] = stab_pop_type (info);
+       }
+      if (! varargs)
+       {
+         if (! stab_empty_type (p))
+           return false;
+         definition = definition || info->type_stack->definition;
+         args[argcount] = stab_pop_type (info);
+         ++argcount;
+       }
+    }
+
+  definition = definition || info->type_stack->definition;
+  return_type = stab_pop_type (info);
+
+  len = strlen (domain) + strlen (return_type) + 10;
+  for (i = 0; i < argcount; i++)
+    len += strlen (args[i]);
+
+  buf = (char *) xmalloc (len);
+
+  sprintf (buf, "#%s,%s", domain, return_type);
+  free (domain);
+  free (return_type);
+  for (i = 0; i < argcount; i++)
+    {
+      strcat (buf, ",");
+      strcat (buf, args[i]);
+      free (args[i]);
+    }
+  strcat (buf, ";");
+
+  if (args != NULL)
+    free (args);
+
+  if (! stab_push_string (info, buf, 0, definition, 0))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Push a const version of a type.  */
+
+static boolean
+stab_const_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  return stab_modify_type (info, 'k', info->type_stack->size,
+                          (long **) NULL, (size_t *) NULL);
+}
+
+/* Push a volatile version of a type.  */
+
+static boolean
+stab_volatile_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  return stab_modify_type (info, 'B', info->type_stack->size,
+                          (long **) NULL, (size_t *) NULL);
+}
+
+/* Get the type index to use for a struct/union/class ID.  This should
+   return -1 if it fails.  */
+
+static long
+stab_get_struct_index (info, tag, id, kind, psize)
+     struct stab_write_handle *info;
+     const char *tag;
+     unsigned int id;
+     enum debug_type_kind kind;
+     unsigned int *psize;
+{
+  if (id >= info->type_cache.struct_types_alloc)
+    {
+      size_t alloc;
+
+      alloc = info->type_cache.struct_types_alloc;
+      if (alloc == 0)
+       alloc = 10;
+      while (id >= alloc)
+       alloc *= 2;
+      info->type_cache.struct_types =
+       (struct stab_tag *) xrealloc (info->type_cache.struct_types,
+                                     alloc * sizeof (struct stab_tag));
+      memset ((info->type_cache.struct_types
+              + info->type_cache.struct_types_alloc),
+             0,
+             ((alloc - info->type_cache.struct_types_alloc)
+              * sizeof (struct stab_tag)));
+      info->type_cache.struct_types_alloc = alloc;
+    }
+
+  if (info->type_cache.struct_types[id].index == 0)
+    {
+      info->type_cache.struct_types[id].index = info->type_index;
+      ++info->type_index;
+      info->type_cache.struct_types[id].tag = tag;
+      info->type_cache.struct_types[id].kind = kind;
+    }
+
+  if (kind == DEBUG_KIND_ILLEGAL)
+    {
+      /* This is a definition of the struct.  */
+      info->type_cache.struct_types[id].kind = kind;
+      info->type_cache.struct_types[id].size = *psize;
+    }
+  else
+    *psize = info->type_cache.struct_types[id].size;
+
+  return info->type_cache.struct_types[id].index;
+}
+
+/* Start outputting a struct.  We ignore the tag, and handle it in
+   stab_tag.  */
+
+/*ARGSUSED*/
+static boolean
+stab_start_struct_type (p, tag, id, structp, size)
+     PTR p;
+     const char *tag;
+     unsigned int id;
+     boolean structp;
+     unsigned int size;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  long index;
+  boolean definition;
+  char *buf;
+
+  buf = (char *) xmalloc (40);
+
+  if (id == 0)
+    {
+      index = 0;
+      *buf = '\0';
+      definition = false;
+    }
+  else
+    {
+      index = stab_get_struct_index (info, tag, id, DEBUG_KIND_ILLEGAL,
+                                    &size);
+      if (index < 0)
+       return false;
+      sprintf (buf, "%ld=", index);
+      definition = true;
+    }
+
+  sprintf (buf + strlen (buf), "%c%u",
+          structp ? 's' : 'u',
+          size);
+
+  if (! stab_push_string (info, buf, index, definition, size))
+    return false;
+
+  info->type_stack->fields = (char *) xmalloc (1);
+  info->type_stack->fields[0] = '\0';
+
+  return true;
+}
+
+/* Add a field to a struct.  */
+
+static boolean
+stab_struct_field (p, name, bitpos, bitsize, visibility)
+     PTR p;
+     const char *name;
+     bfd_vma bitpos;
+     bfd_vma bitsize;
+     enum debug_visibility visibility;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  unsigned int size;
+  char *s, *n;
+  const char *vis;
+
+  definition = info->type_stack->definition;
+  size = info->type_stack->size;
+  s = stab_pop_type (info);
+
+  /* Add this field to the end of the current struct fields, which is
+     currently on the top of the stack.  */
+
+  assert (info->type_stack->fields != NULL);
+  n = (char *) xmalloc (strlen (info->type_stack->fields)
+                       + strlen (name)
+                       + strlen (s)
+                       + 50);
+
+  switch (visibility)
+    {
+    default:
+      abort ();
+
+    case DEBUG_VISIBILITY_PUBLIC:
+      vis = "";
+      break;
+
+    case DEBUG_VISIBILITY_PRIVATE:
+      vis = "/0";
+      break;
+
+    case DEBUG_VISIBILITY_PROTECTED:
+      vis = "/1";
+      break;
+    }
+
+  if (bitsize == 0)
+    {
+      bitsize = size * 8;
+      if (bitsize == 0)
+       fprintf (stderr,
+                _("%s: warning: unknown size for field `%s' in struct\n"),
+                bfd_get_filename (info->abfd), name);
+    }
+
+  sprintf (n, "%s%s:%s%s,%ld,%ld;", info->type_stack->fields, name, vis, s,
+          (long) bitpos, (long) bitsize);
+
+  free (info->type_stack->fields);
+  info->type_stack->fields = n;
+
+  if (definition)
+    info->type_stack->definition = true;
+
+  return true;
+}
+
+/* Finish up a struct.  */
+
+static boolean
+stab_end_struct_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  long index;
+  unsigned int size;
+  char *fields, *first, *buf;
+
+  assert (info->type_stack != NULL && info->type_stack->fields != NULL);
+
+  definition = info->type_stack->definition;
+  index = info->type_stack->index;
+  size = info->type_stack->size;
+  fields = info->type_stack->fields;
+  first = stab_pop_type (info);
+
+  buf = (char *) xmalloc (strlen (first) + strlen (fields) + 2);
+  sprintf (buf, "%s%s;", first, fields);
+  free (first);
+  free (fields);
+
+  if (! stab_push_string (info, buf, index, definition, size))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Start outputting a class.  */
+
+static boolean
+stab_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
+     PTR p;
+     const char *tag;
+     unsigned int id;
+     boolean structp;
+     unsigned int size;
+     boolean vptr;
+     boolean ownvptr;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  char *vstring;
+
+  if (! vptr || ownvptr)
+    {
+      definition = false;
+      vstring = NULL;
+    }
+  else
+    {
+      definition = info->type_stack->definition;
+      vstring = stab_pop_type (info);
+    }
+
+  if (! stab_start_struct_type (p, tag, id, structp, size))
+    return false;
+
+  if (vptr)
+    {
+      char *vtable;
+
+      if (ownvptr)
+       {
+         assert (info->type_stack->index > 0);
+         vtable = (char *) xmalloc (20);
+         sprintf (vtable, "~%%%ld", info->type_stack->index);
+       }
+      else
+       {
+         vtable = (char *) xmalloc (strlen (vstring) + 3);
+         sprintf (vtable, "~%%%s", vstring);
+         free (vstring);
+       }
+
+      info->type_stack->vtable = vtable;
+    }
+
+  if (definition)
+    info->type_stack->definition = true;
+
+  return true;
+}
+
+/* Add a static member to the class on the type stack.  */
+
+static boolean
+stab_class_static_member (p, name, physname, visibility)
+     PTR p;
+     const char *name;
+     const char *physname;
+     enum debug_visibility visibility;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  char *s, *n;
+  const char *vis;
+
+  definition = info->type_stack->definition;
+  s = stab_pop_type (info);
+
+  /* Add this field to the end of the current struct fields, which is
+     currently on the top of the stack.  */
+
+  assert (info->type_stack->fields != NULL);
+  n = (char *) xmalloc (strlen (info->type_stack->fields)
+                       + strlen (name)
+                       + strlen (s)
+                       + strlen (physname)
+                       + 10);
+
+  switch (visibility)
+    {
+    default:
+      abort ();
+
+    case DEBUG_VISIBILITY_PUBLIC:
+      vis = "";
+      break;
+
+    case DEBUG_VISIBILITY_PRIVATE:
+      vis = "/0";
+      break;
+
+    case DEBUG_VISIBILITY_PROTECTED:
+      vis = "/1";
+      break;
+    }
+
+  sprintf (n, "%s%s:%s%s:%s;", info->type_stack->fields, name, vis, s,
+          physname);
+
+  free (info->type_stack->fields);
+  info->type_stack->fields = n;
+
+  if (definition)
+    info->type_stack->definition = true;
+
+  return true;
+}
+
+/* Add a base class to the class on the type stack.  */
+
+static boolean
+stab_class_baseclass (p, bitpos, virtual, visibility)
+     PTR p;
+     bfd_vma bitpos;
+     boolean virtual;
+     enum debug_visibility visibility;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  boolean definition;
+  char *s;
+  char *buf;
+  unsigned int c;
+  char **baseclasses;
+
+  definition = info->type_stack->definition;
+  s = stab_pop_type (info);
+
+  /* Build the base class specifier.  */
+
+  buf = (char *) xmalloc (strlen (s) + 25);
+  buf[0] = virtual ? '1' : '0';
+  switch (visibility)
+    {
+    default:
+      abort ();
+
+    case DEBUG_VISIBILITY_PRIVATE:
+      buf[1] = '0';
+      break;
+
+    case DEBUG_VISIBILITY_PROTECTED:
+      buf[1] = '1';
+      break;
+
+    case DEBUG_VISIBILITY_PUBLIC:
+      buf[1] = '2';
+      break;
+    }
+
+  sprintf (buf + 2, "%ld,%s;", (long) bitpos, s);
+  free (s);
+
+  /* Add the new baseclass to the existing ones.  */
+
+  assert (info->type_stack != NULL && info->type_stack->fields != NULL);
+
+  if (info->type_stack->baseclasses == NULL)
+    c = 0;
+  else
+    {
+      c = 0;
+      while (info->type_stack->baseclasses[c] != NULL)
+       ++c;
+    }
+
+  baseclasses = (char **) xrealloc (info->type_stack->baseclasses,
+                                   (c + 2) * sizeof (*baseclasses));
+  baseclasses[c] = buf;
+  baseclasses[c + 1] = NULL;
+
+  info->type_stack->baseclasses = baseclasses;
+
+  if (definition)
+    info->type_stack->definition = true;
+
+  return true;
+}
+
+/* Start adding a method to the class on the type stack.  */
+
+static boolean
+stab_class_start_method (p, name)
+     PTR p;
+     const char *name;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char *m;
+
+  assert (info->type_stack != NULL && info->type_stack->fields != NULL);
+
+  if (info->type_stack->methods == NULL)
+    {
+      m = (char *) xmalloc (strlen (name) + 3);
+      *m = '\0';
+    }
+  else
+    {
+      m = (char *) xrealloc (info->type_stack->methods,
+                            (strlen (info->type_stack->methods)
+                             + strlen (name)
+                             + 4));
+    }
+
+  sprintf (m + strlen (m), "%s::", name);
+
+  info->type_stack->methods = m;
+
+  return true;
+}
+
+/* Add a variant, either static or not, to the current method.  */
+
+static boolean
+stab_class_method_var (info, physname, visibility, staticp, constp, volatilep,
+                      voffset, contextp)
+     struct stab_write_handle *info;
+     const char *physname;
+     enum debug_visibility visibility;
+     boolean staticp;
+     boolean constp;
+     boolean volatilep;
+     bfd_vma voffset;
+     boolean contextp;
+{
+  boolean definition;
+  char *type;
+  char *context = NULL;
+  char visc, qualc, typec;
+
+  definition = info->type_stack->definition;
+  type = stab_pop_type (info);
+
+  if (contextp)
+    {
+      definition = definition || info->type_stack->definition;
+      context = stab_pop_type (info);
+    }
+
+  assert (info->type_stack != NULL && info->type_stack->methods != NULL);
+
+  switch (visibility)
+    {
+    default:
+      abort ();
+
+    case DEBUG_VISIBILITY_PRIVATE:
+      visc = '0';
+      break;
+
+    case DEBUG_VISIBILITY_PROTECTED:
+      visc = '1';
+      break;
+
+    case DEBUG_VISIBILITY_PUBLIC:
+      visc = '2';
+      break;
+    }
+
+  if (constp)
+    {
+      if (volatilep)
+       qualc = 'D';
+      else
+       qualc = 'B';
+    }
+  else
+    {
+      if (volatilep)
+       qualc = 'C';
+      else
+       qualc = 'A';
+    }
+
+  if (staticp)
+    typec = '?';
+  else if (! contextp)
+    typec = '.';
+  else
+    typec = '*';
+
+  info->type_stack->methods =
+    (char *) xrealloc (info->type_stack->methods,
+                      (strlen (info->type_stack->methods)
+                       + strlen (type)
+                       + strlen (physname)
+                       + (contextp ? strlen (context) : 0)
+                       + 40));
+
+  sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
+          "%s:%s;%c%c%c", type, physname, visc, qualc, typec);
+  free (type);
+
+  if (contextp)
+    {
+      sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
+              "%ld;%s;", (long) voffset, context);
+      free (context);
+    }
+
+  if (definition)
+    info->type_stack->definition = true;
+
+  return true;
+}
+
+/* Add a variant to the current method.  */
+
+static boolean
+stab_class_method_variant (p, physname, visibility, constp, volatilep,
+                          voffset, contextp)
+     PTR p;
+     const char *physname;
+     enum debug_visibility visibility;
+     boolean constp;
+     boolean volatilep;
+     bfd_vma voffset;
+     boolean contextp;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  return stab_class_method_var (info, physname, visibility, false, constp,
+                               volatilep, voffset, contextp);
+}
+
+/* Add a static variant to the current method.  */
+
+static boolean
+stab_class_static_method_variant (p, physname, visibility, constp, volatilep)
+     PTR p;
+     const char *physname;
+     enum debug_visibility visibility;
+     boolean constp;
+     boolean volatilep;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  return stab_class_method_var (info, physname, visibility, true, constp,
+                               volatilep, 0, false);
+}
+
+/* Finish up a method.  */
+
+static boolean
+stab_class_end_method (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  assert (info->type_stack != NULL && info->type_stack->methods != NULL);
+
+  /* We allocated enough room on info->type_stack->methods to add the
+     trailing semicolon.  */
+  strcat (info->type_stack->methods, ";");
+
+  return true;
+}
+
+/* Finish up a class.  */
+
+static boolean
+stab_end_class_type (p)
+     PTR p;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  size_t len;
+  unsigned int i = 0;
+  char *buf;
+
+  assert (info->type_stack != NULL && info->type_stack->fields != NULL);
+
+  /* Work out the size we need to allocate for the class definition.  */
+
+  len = (strlen (info->type_stack->string)
+        + strlen (info->type_stack->fields)
+        + 10);
+  if (info->type_stack->baseclasses != NULL)
+    {
+      len += 20;
+      for (i = 0; info->type_stack->baseclasses[i] != NULL; i++)
+       len += strlen (info->type_stack->baseclasses[i]);
+    }
+  if (info->type_stack->methods != NULL)
+    len += strlen (info->type_stack->methods);
+  if (info->type_stack->vtable != NULL)
+    len += strlen (info->type_stack->vtable);
+
+  /* Build the class definition.  */
+
+  buf = (char *) xmalloc (len);
+
+  strcpy (buf, info->type_stack->string);
+
+  if (info->type_stack->baseclasses != NULL)
+    {
+      sprintf (buf + strlen (buf), "!%u,", i);
+      for (i = 0; info->type_stack->baseclasses[i] != NULL; i++)
+       {
+         strcat (buf, info->type_stack->baseclasses[i]);
+         free (info->type_stack->baseclasses[i]);
+       }
+      free (info->type_stack->baseclasses);
+      info->type_stack->baseclasses = NULL;
+    }
+
+  strcat (buf, info->type_stack->fields);
+  free (info->type_stack->fields);
+  info->type_stack->fields = NULL;
+
+  if (info->type_stack->methods != NULL)
+    {
+      strcat (buf, info->type_stack->methods);
+      free (info->type_stack->methods);
+      info->type_stack->methods = NULL;
+    }
+
+  strcat (buf, ";");
+
+  if (info->type_stack->vtable != NULL)
+    {
+      strcat (buf, info->type_stack->vtable);
+      free (info->type_stack->vtable);
+      info->type_stack->vtable = NULL;
+    }
+
+  /* Replace the string on the top of the stack with the complete
+     class definition.  */
+  free (info->type_stack->string);
+  info->type_stack->string = buf;
+
+  return true;
+}
+
+/* Push a typedef which was previously defined.  */
+
+static boolean
+stab_typedef_type (p, name)
+     PTR p;
+     const char *name;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  struct string_hash_entry *h;
+
+  h = string_hash_lookup (&info->typedef_hash, name, false, false);
+  assert (h != NULL && h->index > 0);
+
+  return stab_push_defined_type (info, h->index, h->size);
+}
+
+/* Push a struct, union or class tag.  */
+
+static boolean
+stab_tag_type (p, name, id, kind)
+     PTR p;
+     const char *name;
+     unsigned int id;
+     enum debug_type_kind kind;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  long index;
+  unsigned int size;
+
+  index = stab_get_struct_index (info, name, id, kind, &size);
+  if (index < 0)
+    return false;
+
+  return stab_push_defined_type (info, index, size);
+}
+
+/* Define a typedef.  */
+
+static boolean
+stab_typdef (p, name)
+     PTR p;
+     const char *name;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  long index;
+  unsigned int size;
+  char *s, *buf;
+  struct string_hash_entry *h;
+
+  index = info->type_stack->index;
+  size = info->type_stack->size;
+  s = stab_pop_type (info);
+
+  buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
+
+  if (index > 0)
+    sprintf (buf, "%s:t%s", name, s);
+  else
+    {
+      index = info->type_index;
+      ++info->type_index;
+      sprintf (buf, "%s:t%ld=%s", name, index, s);
+    }
+
+  free (s);
+
+  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+    return false;
+
+  free (buf);
+
+  h = string_hash_lookup (&info->typedef_hash, name, true, false);
+  if (h == NULL)
+    {
+      fprintf (stderr, _("string_hash_lookup failed: %s\n"),
+              bfd_errmsg (bfd_get_error ()));
+      return false;
+    }
+
+  /* I don't think we care about redefinitions.  */
+
+  h->index = index;
+  h->size = size;
+
+  return true;
+}
+
+/* Define a tag.  */
+
+static boolean
+stab_tag (p, tag)
+     PTR p;
+     const char *tag;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char *s, *buf;
+
+  s = stab_pop_type (info);
+
+  buf = (char *) xmalloc (strlen (tag) + strlen (s) + 3);
+
+  sprintf (buf, "%s:T%s", tag, s);
+  free (s);
+
+  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Define an integer constant.  */
+
+static boolean
+stab_int_constant (p, name, val)
+     PTR p;
+     const char *name;
+     bfd_vma val;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char *buf;
+
+  buf = (char *) xmalloc (strlen (name) + 20);
+  sprintf (buf, "%s:c=i%ld", name, (long) val);
+
+  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Define a floating point constant.  */
+
+static boolean
+stab_float_constant (p, name, val)
+     PTR p;
+     const char *name;
+     double val;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char *buf;
+
+  buf = (char *) xmalloc (strlen (name) + 20);
+  sprintf (buf, "%s:c=f%g", name, val);
+
+  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Define a typed constant.  */
+
+static boolean
+stab_typed_constant (p, name, val)
+     PTR p;
+     const char *name;
+     bfd_vma val;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char *s, *buf;
+
+  s = stab_pop_type (info);
+
+  buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
+  sprintf (buf, "%s:c=e%s,%ld", name, s, (long) val);
+  free (s);
+
+  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Record a variable.  */
+
+static boolean
+stab_variable (p, name, kind, val)
+     PTR p;
+     const char *name;
+     enum debug_var_kind kind;
+     bfd_vma val;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char *s, *buf;
+  int stab_type;
+  const char *kindstr;
+
+  s = stab_pop_type (info);
+
+  switch (kind)
+    {
+    default:
+      abort ();
+
+    case DEBUG_GLOBAL:
+      stab_type = N_GSYM;
+      kindstr = "G";
+      break;
+
+    case DEBUG_STATIC:
+      stab_type = N_STSYM;
+      kindstr = "S";
+      break;
+
+    case DEBUG_LOCAL_STATIC:
+      stab_type = N_STSYM;
+      kindstr = "V";
+      break;
+
+    case DEBUG_LOCAL:
+      stab_type = N_LSYM;
+      kindstr = "";
+
+      /* Make sure that this is a type reference or definition.  */
+      if (! isdigit ((unsigned char) *s))
+       {
+         char *n;
+         long index;
+
+         index = info->type_index;
+         ++info->type_index;
+         n = (char *) xmalloc (strlen (s) + 20);
+         sprintf (n, "%ld=%s", index, s);
+         free (s);
+         s = n;
+       }
+      break;
+
+    case DEBUG_REGISTER:
+      stab_type = N_RSYM;
+      kindstr = "r";
+      break;
+    }
+
+  buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
+  sprintf (buf, "%s:%s%s", name, kindstr, s);
+  free (s);
+
+  if (! stab_write_symbol (info, stab_type, 0, val, buf))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Start outputting a function.  */
+
+static boolean
+stab_start_function (p, name, globalp)
+     PTR p;
+     const char *name;
+     boolean globalp;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char *rettype, *buf;
+
+  assert (info->nesting == 0 && info->fun_offset == -1);
+
+  rettype = stab_pop_type (info);
+
+  buf = (char *) xmalloc (strlen (name) + strlen (rettype) + 3);
+  sprintf (buf, "%s:%c%s", name,
+          globalp ? 'F' : 'f',
+          rettype);
+
+  /* We don't know the value now, so we set it in start_block.  */
+  info->fun_offset = info->symbols_size;
+
+  if (! stab_write_symbol (info, N_FUN, 0, 0, buf))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Output a function parameter.  */
+
+static boolean
+stab_function_parameter (p, name, kind, val)
+     PTR p;
+     const char *name;
+     enum debug_parm_kind kind;
+     bfd_vma val;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+  char *s, *buf;
+  int stab_type;
+  char kindc;
+
+  s = stab_pop_type (info);
+
+  switch (kind)
+    {
+    default:
+      abort ();
+
+    case DEBUG_PARM_STACK:
+      stab_type = N_PSYM;
+      kindc = 'p';
+      break;
+
+    case DEBUG_PARM_REG:
+      stab_type = N_RSYM;
+      kindc = 'P';
+      break;
+
+    case DEBUG_PARM_REFERENCE:
+      stab_type = N_PSYM;
+      kindc = 'v';
+      break;
+
+    case DEBUG_PARM_REF_REG:
+      stab_type = N_RSYM;
+      kindc = 'a';
+      break;
+    }
+
+  buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
+  sprintf (buf, "%s:%c%s", name, kindc, s);
+  free (s);
+
+  if (! stab_write_symbol (info, stab_type, 0, val, buf))
+    return false;
+
+  free (buf);
+
+  return true;
+}
+
+/* Start a block.  */
+
+static boolean
+stab_start_block (p, addr)
+     PTR p;
+     bfd_vma addr;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  /* Fill in any slots which have been waiting for the first known
+     text address.  */
+
+  if (info->so_offset != -1)
+    {
+      bfd_put_32 (info->abfd, addr, info->symbols + info->so_offset + 8);
+      info->so_offset = -1;
+    }
+
+  if (info->fun_offset != -1)
+    {
+      bfd_put_32 (info->abfd, addr, info->symbols + info->fun_offset + 8);
+      info->fun_offset = -1;
+    }
+
+  ++info->nesting;
+
+  /* We will be called with a top level block surrounding the
+     function, but stabs information does not output that block, so we
+     ignore it.  */
+
+  if (info->nesting == 1)
+    {
+      info->fnaddr = addr;
+      return true;
+    }
+
+  /* We have to output the LBRAC symbol after any variables which are
+     declared inside the block.  We postpone the LBRAC until the next
+     start_block or end_block.  */
+
+  /* If we have postponed an LBRAC, output it now.  */
+  if (info->pending_lbrac != (bfd_vma) -1)
+    {
+      if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac,
+                              (const char *) NULL))
+       return false;
+    }
+
+  /* Remember the address and output it later.  */
+
+  info->pending_lbrac = addr - info->fnaddr;
+
+  return true;
+}
+
+/* End a block.  */
+
+static boolean
+stab_end_block (p, addr)
+     PTR p;
+     bfd_vma addr;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  if (addr > info->last_text_address)
+    info->last_text_address = addr;
+
+  /* If we have postponed an LBRAC, output it now.  */
+  if (info->pending_lbrac != (bfd_vma) -1)
+    {
+      if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac,
+                              (const char *) NULL))
+       return false;
+      info->pending_lbrac = (bfd_vma) -1;
+    }
+
+  assert (info->nesting > 0);
+
+  --info->nesting;
+
+  /* We ignore the outermost block.  */
+  if (info->nesting == 0)
+    return true;
+
+  return stab_write_symbol (info, N_RBRAC, 0, addr - info->fnaddr,
+                           (const char *) NULL);
+}
+
+/* End a function.  */
+
+/*ARGSUSED*/
+static boolean
+stab_end_function (p)
+     PTR p;
+{
+  return true;
+}
+
+/* Output a line number.  */
+
+static boolean
+stab_lineno (p, file, lineno, addr)
+     PTR p;
+     const char *file;
+     unsigned long lineno;
+     bfd_vma addr;
+{
+  struct stab_write_handle *info = (struct stab_write_handle *) p;
+
+  assert (info->lineno_filename != NULL);
+
+  if (addr > info->last_text_address)
+    info->last_text_address = addr;
+
+  if (strcmp (file, info->lineno_filename) != 0)
+    {
+      if (! stab_write_symbol (info, N_SOL, 0, addr, file))
+       return false;
+      info->lineno_filename = file;
+    }
+
+  return stab_write_symbol (info, N_SLINE, lineno, addr - info->fnaddr,
+                           (const char *) NULL);
+}
diff --git a/config/ChangeLog b/config/ChangeLog
new file mode 100644 (file)
index 0000000..7d6fc60
--- /dev/null
@@ -0,0 +1,392 @@
+1999-04-07  Michael Meissner  <meissner@cygnus.com>
+
+       * mt-d30v: New file, pass -g -Os -Wa,-C as default options.
+
+1999-02-08  Syd Polk  <spolk@cygnus.com>
+
+       * acinclude.m4: Added macros to find itcl files.
+       Export TCL_CFLAGS from tclConfig.sh.
+       Export TCL_LIB_FULL_PATH, TK_LIB_FULL_PATH, ITCL_LIB_FULL_PATH,
+       ITK_LIB_FULL_PATH, and TIX_LIB_FULL_PATH
+       Replace TIX macros with better ones from snavigator.
+
+Tue Feb  2 22:51:21 1999 Philip Blundell  <philb@gnu.org>
+
+       * mh-armpic: New file.  Patch from Jim Pick <jim@jimpick.com>.
+       * mt-armpic: Likewise.
+
+Mon Jan 18 19:41:08 1999  Christopher Faylor <cgf@cygnus.com>
+
+       * cygwin.mh: Activate commented out dependencies for
+       gdb: libtermcap.
+
+Wed Nov 18 20:29:46 1998  Christopher Faylor <cgf@cygnus.com>
+
+       * cygwin.mh: Add extra libtermcap target information.
+       Add commented out dependency for gdb to libtermcap for
+       future readline requirement.
+
+Mon Nov  2 15:15:33 1998  Geoffrey Noer  <noer@cygnus.com>
+
+        * mh-cygwin32: delete
+        * mh-cygwin: was mh-cygwin32
+
+1998-10-26  Syd Polk  <spolk@cygnus.com>
+
+       * acinclude.m4: TCLHDIR and TKHDIR need to be run through
+       cygpath for Microsoft builds.
+
+1998-10-20  Syd Polk  <spolk@cygnus.com>
+
+       * acinclude.m4: Re-exported TCL_LIBS and TCL_LD_SEARCH_FLAGS
+       because itcl needs them.
+
+Mon Aug 31 17:50:53 1998  David Edelsohn  <edelsohn@mhpcc.edu>
+
+       * mh-aix43 (NM_FOR_TARGET): Add -X32_64 as well.
+
+Sat Aug 29 14:32:55 1998  David Edelsohn  <edelsohn@mhpcc.edu>
+
+       * mh-aix43: New file.
+
+Mon Aug 10 00:15:47 1998  HJ Lu (hjl@gnu.org)
+
+       * mt-linux (CXXFLAGS_FOR_TARGET): Add -D_GNU_SOURCE.
+
+1998-05-29  Rob Savoye  <rob@chinadoll.cygnus.com>
+
+       * acinclude.m4: New collection of generic autoconf macros.
+       
+Wed Apr 22 12:24:28 1998  Michael Meissner  <meissner@cygnus.com>
+
+       * mt-ospace: New file, support using -Os instead of -O2 to compile
+       the libraries.
+
+Wed Apr 22 10:53:14 1998  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * mt-linux (CXXFLAGS_FOR_TARGET): Set this instead of CXXFLAGS.
+
+Sat Apr 11 22:43:17 1998  J. Kean Johnston  <jkj@sco.com>
+
+       * mh-svsv5: New file - support for SCO UnixWare 7 / SVR5.
+
+Thu Mar 26 01:54:25 1998  Geoffrey Noer  <noer@cygnus.com>
+
+       * mh-cygwin32: stop configuring and building dosrel.
+
+Thu Sep 11 16:43:27 1997  Jim Wilson  <wilson@cygnus.com>
+
+       * mh-elfalphapic, mt-elfalphapic: New files.
+
+Wed Jul 23 12:32:18 1997  Robert Hoehne <robert.hoehne@Mathematik.TU-Chemnitz.DE>
+
+       * mh-go32 (CFLAGS): Don't set -fno-omit-frame-pointer.
+
+Mon Jun 16 19:06:41 1997  Geoff Keating  <geoffk@ozemail.com.au>
+
+       * mh-ppcpic: New file.
+       * mt-ppcpic: New file.
+
+Thu Mar 27 15:52:40 1997  Geoffrey Noer  <noer@cygnus.com>
+
+       * mh-cygwin32: override CXXFLAGS, setting to -O2 only
+       (no debug)
+
+Tue Mar 25 18:16:43 1997  Geoffrey Noer  <noer@cygnus.com>
+
+       * mh-cygwin32: override LIBGCC2_DEBUG_CFLAGS so debug info
+       isn't included in cygwin32-hosted libgcc2.a by default
+
+Wed Jan  8 19:56:43 1997  Geoffrey Noer  <noer@cygnus.com>
+
+        * mh-cygwin32: override CFLAGS so debug info isn't included
+        in cygwin32-hosted tools by default
+
+Tue Dec 31 16:04:26 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * mh-linux: Remove.
+
+Mon Nov 11 10:29:51 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * mt-ppc: Delete file, options moved to newlib configure.
+
+Fri Oct  4 12:21:03 1996  Angela Marie Thomas (angela@cygnus.com)
+
+       * mh-dgux386: New file.  x86 dgux specific flags
+
+Mon Sep 30 15:10:07 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-mh-mpw (EXTRALIBS_PPC_XCOFF): New, was EXTRALIBS_PPC.
+       (EXTRALIBS_PPC): Use shared libraries instead of xcoff.
+
+Sat Aug 17 04:56:25 1996  Geoffrey Noer  <noer@skaro.cygnus.com>
+
+       * mh-cygwin32: don't -D_WIN32 here anymore
+
+Thu Aug 15 19:46:44 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-mh-mpw (SEGFLAG_68K, SEGFLAG_PPC): Remove.
+       (EXTRALIBS_PPC): Add libgcc.xcoff.
+
+Thu Aug  8 14:51:47 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * mt-ppc: New file, add -mrelocatable-lib and -mno-eabi to all
+       target builds for PowerPC eabi targets.
+
+Fri Jul 12 12:06:01 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw: New subdir, Mac MPW configuration support bits.
+
+Mon Jul  8 17:30:52 1996  Jim Wilson  <wilson@cygnus.com>
+
+       * mh-irix6: New file.
+
+Mon Jul  8 15:15:37 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * mt-sparcpic (PICFLAG_FOR_TARGET): Use -fPIC.
+
+Fri Jul  5 11:49:02 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * mh-irix4 (RANLIB): Don't define; Irix 4 does have ranlib.
+
+Sun Jun 23 22:59:25 1996  Geoffrey Noer  <noer@cygnus.com>
+
+       * mh-cygwin32: new file.  Like mh-go32 without the CFLAGS entry.
+
+Tue Mar 26 14:10:41 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * mh-go32 (CFLAGS): Define.
+
+Thu Mar 14 19:20:54 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * mh-necv4: New file.
+
+Thu Feb 15 13:07:43 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * mh-cxux (CC): New variable.
+       (CFLAGS, LDFLAGS): Remove.
+       * mh-ncrsvr43 (CC): New variable.
+       (CFLAGS): Remove.
+       * mh-solaris (CFLAGS): Remove.
+
+       * mh-go32: Remove most variable settings, since they presumed a
+       Canadian Cross, which is now handled correctly by the configure
+       script.
+
+       * mh-sparcpic (PICFLAG): Set to -fPIC, not -fpic.
+
+Mon Feb 12 14:53:39 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * mh-m68kpic, mt-m68kpic: New files.
+
+Thu Feb  1 14:15:42 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-mh-mpw (CC_MWC68K): Add options similar to those used
+       in CC_MWCPPC, and -mc68020 -model far.
+       (AR_MWLINK68K): Add -xm library.
+       (AR_AR): Define.
+       (CC_LD_MWLINK68K): Remove -d.
+       (EXTRALIBS_MWC68K): Define.
+
+Thu Jan 25 16:05:33 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * mh-ncrsvr43 (CFLAGS): Remove -Hnocopyr.
+
+Tue Nov  7 15:41:30 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-mh-mpw (CC_MWC68K, CC_MWCPPC): Remove unused include path.
+       (CC_MWCPPC): Add -mpw_chars, disable warnings, add comments
+       explaining reasons for various flags.
+       (EXTRALIBS_PPC, EXTRALIBS_MWCPPC ): Put runtime library first.
+       
+Fri Oct 13 14:44:25 1995  Jason Molenda  (crash@phydeaux.cygnus.com)
+
+       * mh-aix, mh-sun:  Removed.
+
+       * mh-decstation (X11_EXTRA_CFLAGS): Define.
+
+       * mh-sco, mh-solaris, mh-sysv4 (X11_EXTRA_LIBS): Define.
+
+        * mh-hp300, mh-hpux, mh-hpux8, mh-solaris, mh-sun3, mh-sysv4: Don't 
+       hardcode location of X stuff here.
+
+Thu Sep 28 13:14:56 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-mh-mpw: Add definitions for various 68K and PowerMac
+       compilers, add definitions for library and link steps for
+       PowerMacs.
+
+Thu Sep 14 08:20:04 1995  Fred Fish  <fnf@cygnus.com>
+
+       * mh-hp300 (CC): Add "CC = cc -Wp,-H256000" to avoid
+       "too much defining" errors from the HPUX compiler.
+
+Thu Aug 17 17:28:56 1995  Ken Raeburn  <raeburn@kr-laptop.cygnus.com>
+
+       * mh-hp300 (RANLIB): Use "ar ts", in case GNU ar was used and
+       didn't build a symbol table.
+
+Thu Jun 22 17:47:24 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-mh-mpw (CC): Define ANSI_PROTOTYPES.
+
+Mon Apr 10 12:29:48 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-mh-mpw (EXTRALIBS): Always link in Math.o, CSANELIB.o,
+        and ToolLibs.o.
+
+       * mpw-mh-mpw (CC): Define ALMOST_STDC.
+       (CFLAGS): Remove ALMOST_STDC, -mc68881.
+       (LDFLAGS): add -w.
+
+       * mpw-mh-mpw (CFLAGS): Add -b option to put strings at the ends of
+       functions.
+
+       * mpw-mh-mpw: New file, host makefile definitions for MPW.
+
+Fri Mar 31 11:35:17 1995  Jason Molenda (crash@phydeaux.cygnus.com)
+
+       * mt-netware: New file.
+
+Mon Mar 13 12:31:29 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * mh-hpux8: New file.
+       * mh-hpux: Use X11R5 rather than X11R4.
+
+Thu Feb  9 11:04:13 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * mh-linux (SYSV): Don't define.
+       (RANLIB): Don't define.
+
+Wed Jan 11 16:29:34 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * m?-*pic (LIBCXXFLAGS): Add -fno-implicit-templates.
+
+Thu Nov  3 17:27:19 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * mh-irix4 (CC): Increase maximum string length.
+
+       * mh-sco (CC): Define away const, it doesn't work right; elements
+       of arrays of ptr-to-const are considered const themselves.
+
+Sat Jul 16 12:17:49 1994  Stan Shebs  (shebs@andros.cygnus.com)
+
+       * mh-cxux: New file, from Bob Rusk (rrusk@mail.csd.harris.com).
+
+Sat Jun  4 17:22:12 1994  Per Bothner  (bothner@kalessin.cygnus.com)
+
+       * mh-ncrsvr43:  New file from Tom McConnell
+       <tmcconne@sedona.intel.com>.
+
+Thu May 19 00:32:11 1994  Jeff Law  (law@snake.cs.utah.edu)
+
+       * mh-hpux (CC): Add -Wp,-H256000 to avoid "too much defining"
+       errors from the HPUX 8 compilers.
+
+Wed May  4 20:14:47 1994  D. V. Henkel-Wallace  (gumby@cygnus.com)
+
+       * mh-lynxrs6k: set SHELL to /bin/bash
+
+Tue Apr 12 12:38:17 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * mh-irix4 (CC): Change -XNh1500 to -XNh2000.
+
+Sat Dec 25 20:03:45 1993  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * mt-hppa: Delete.
+
+Tue Nov 16 22:54:39 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * mh-a68bsd: Define CC to gcc.
+
+Mon Nov 15 16:56:51 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * mh-linux: Don't put -static in LDFLAGS.  Add comments.
+
+Mon Nov 15 13:37:58 1993  david d `zoo' zuhn  (zoo@cirdan.cygnus.com)
+
+       * mh-sysv4 (AR_FLAGS): change from cq to cr
+
+Fri Nov  5 08:12:32 1993  D. V. Henkel-Wallace  (gumby@blues.cygnus.com)
+
+       * mh-unixware: remove.  It's the same as sysv4, and config.guess
+       can't tell the difference.  So don't allow skew.
+
+Wed Oct 20 20:35:14 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * mh-hp300: Revert yesterday's change, but add comment explaining.
+
+Tue Oct 19 18:58:21 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * mh-hp300: Don't define CFLAGS to empty.  Why should hp300 be
+       different from anything else?  ("gdb doesn't understand the native
+       debug format" isn't a good enough answer because we might be using
+       gcc).
+
+Tue Oct  5 12:17:40 1993  Peter Schauer  (pes@regent.e-technik.tu-muenchen.de)
+
+       * mh-alphaosf: Remove, no longer necessary now that gdb knows
+       how to handle OSF/1 shared libraries.
+
+Tue Jul  6 11:27:33 1993  Steve Chamberlain  (sac@phydeaux.cygnus.com)
+
+       * mh-alphaosf: New file.
+
+Thu Jul  1 15:49:33 1993  Jim Kingdon  (kingdon@lioth.cygnus.com)
+
+       * mh-riscos: New file.
+
+Mon Jun 14 12:03:18 1993  david d `zoo' zuhn  (zoo at rtl.cygnus.com)
+
+       * mh-aix, mh-aix386, mh-decstation, mh-delta88, mh-hpux, mh-irix4,
+       mh-ncr3000, mh-solaris, mh-sysv, mh-sysv4: remove INSTALL=cp line,
+       now that we're using install.sh globally
+
+Fri Jun  4 16:09:34 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * mh-sysv4 (INSTALL): Use cp, not /usr/ucb/install.
+
+Thu Apr  8 11:21:52 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * mt-a29k, mt-ebmon29k, mt-os68k, mt-ose68000, mt-ose68k,
+       mt-vxworks68, mt-vxworks960: Removed obsolete, unused target
+       Makefile fragment files.
+
+Mon Mar  8 15:05:25 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
+
+       * mh-aix386: New file; old mh-aix, plus no-op RANLIB.
+
+Thu Oct  1 13:50:48 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * mh-solaris: INSTALL is NOT /usr/ucb/install
+
+Mon Aug 24 14:25:35 1992  Ian Lance Taylor  (ian@cygnus.com)
+
+       * mt-ose68000, mt-ose68k: renamed from mt-OSE*.
+
+Tue Jul 21 02:11:01 1992  D. V. Henkel-Wallace  (gumby@cygnus.com)
+
+       * mt-OSE68k, mt-680000: new configs.
+
+Thu Jul 16 17:12:09 1992  K. Richard Pixley  (rich@rtl.cygnus.com)
+
+       * mh-irix4: merged changes from progressive.
+
+Tue Jun  9 23:29:38 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Everywhere: Change RANLIB=echo>/dev/null (which confuses
+       some shells - and I don't blame them) to RANLIB=true.
+       * mh-solaris:  Use /usr/ucb/install for INSTALL.
+
+Sun May 31 14:45:23 1992  Mark Eichin  (eichin at cygnus.com)
+
+       * mh-solaris2: Add new configuration for Solaris 2 (sysv, no ranlib)
+
+Fri Apr 10 23:10:08 1992  Fred Fish  (fnf@cygnus.com)
+
+       * mh-ncr3000:  Add new configuration for NCR 3000.
+
+Tue Dec 10 00:10:55 1991  K. Richard Pixley  (rich at rtl.cygnus.com)
+
+       * ChangeLog: fresh changelog.
+
diff --git a/config/acinclude.m4 b/config/acinclude.m4
new file mode 100755 (executable)
index 0000000..f799ced
--- /dev/null
@@ -0,0 +1,1994 @@
+dnl This file is included into all any other acinclude file that needs
+dnl to use these macros.
+
+dnl This is copied from autoconf 2.12, but does calls our own AC_PROG_CC_WORKS,
+dnl and doesn't call AC_PROG_CXX_GNU, cause we test for that in  AC_PROG_CC_WORKS.
+dnl We are probably using a cross compiler, which will not be able to fully
+dnl link an executable.  This should really be fixed in autoconf itself.
+dnl Find a working G++ cross compiler. This only works for the GNU C++ compiler.
+AC_DEFUN(CYG_AC_PROG_CXX_CROSS,
+[AC_BEFORE([$0], [AC_PROG_CXXCPP])
+AC_CHECK_PROGS(CXX, $CCC c++ g++ gcc CC cxx cc++, gcc)
+
+CYG_AC_PROG_GXX_WORKS
+
+if test $ac_cv_prog_gxx = yes; then
+  GXX=yes
+dnl Check whether -g works, even if CXXFLAGS is set, in case the package
+dnl plays around with CXXFLAGS (such as to build both debugging and
+dnl normal versions of a library), tasteless as that idea is.
+  ac_test_CXXFLAGS="${CXXFLAGS+set}"
+  ac_save_CXXFLAGS="$CXXFLAGS"
+  CXXFLAGS=
+  AC_PROG_CXX_G
+  if test "$ac_test_CXXFLAGS" = set; then
+    CXXFLAGS="$ac_save_CXXFLAGS"
+  elif test $ac_cv_prog_cxx_g = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-O2"
+  fi
+else
+  GXX=
+  test "${CXXFLAGS+set}" = set || CXXFLAGS="-g"
+fi
+])
+
+dnl See if the G++ compiler we found works.
+AC_DEFUN(CYG_AC_PROG_GXX_WORKS,
+[AC_MSG_CHECKING([whether the G++ compiler ($CXX $CXXFLAGS $LDFLAGS) actually works])
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+dnl Try a test case. We only compile, because it's close to impossible
+dnl to get a correct fully linked executable with a cross compiler. For
+dnl most cross compilers, this test is bogus. For G++, we can use various
+dnl other compile line options to get a decent idea that the cross compiler
+dnl actually does work, even though we can't produce an executable without
+dnl more info about the target it's being compiled for. This only works
+dnl for the GNU C++ compiler.
+
+dnl Transform the name of the compiler to it's cross variant, unless
+dnl CXX is set. This is also what CXX gets set to in the generated
+dnl Makefile.
+if test x"${CXX}" = xc++ ; then
+    CXX=`echo gcc | sed -e "${program_transform_name}"`
+fi
+
+dnl Get G++'s full path to libgcc.a
+libgccpath=`${CXX} --print-libgcc`
+
+dnl If we don't have a path with libgcc.a on the end, this isn't G++.
+if test `echo $libgccpath | sed -e 's:/.*/::'` = libgcc.a ; then
+   ac_cv_prog_gxx=yes
+else
+   ac_cv_prog_gxx=no
+fi
+
+dnl If we are using G++, look for the files that need to exist if this
+dnl compiler works.
+if test x"${ac_cv_prog_gxx}" = xyes ; then
+    gccfiles=`echo $libgccpath | sed -e 's:/libgcc.a::'`
+    if test -f ${gccfiles}/specs -a -f ${gccfiles}/cpp -a -f ${gccfiles}/cc1plus; then
+       gccfiles=yes
+    else
+       gccfiles=no
+    fi
+    gcclibs=`echo $libgccpath | sed -e 's:lib/gcc-lib/::' -e 's:/libgcc.a::' -e 's,\(.*\)/.*,\1,g'`/lib
+    if test -d ${gcclibs}/ldscripts -a -f ${gcclibs}/libc.a -a -f ${gcclibs}/libstdc++.a ; then
+       gcclibs=yes
+    else
+       gcclibs=no
+    fi
+fi
+
+dnl If everything is OK, then we can safely assume the compiler works.
+if test x"${gccfiles}" = xno -o x"${gcclibs}" = xno; then
+    ac_cv_prog_cxx_works=no
+    AC_MSG_ERROR(${CXX} is a non-working cross compiler)
+else
+   ac_cv_prog_cxx_works=yes 
+fi
+
+AC_LANG_RESTORE
+AC_MSG_RESULT($ac_cv_prog_cxx_works)
+if test x"$ac_cv_prog_cxx_works" = xno; then
+  AC_MSG_ERROR([installation or configuration problem: C++ compiler cannot create executables.])
+fi
+AC_MSG_CHECKING([whether the G++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler])
+AC_MSG_RESULT($ac_cv_prog_cxx_cross)
+cross_compiling=$ac_cv_prog_cxx_cross
+AC_SUBST(CXX)
+])
+
+dnl ====================================================================
+dnl Find a working GCC cross compiler. This only works for the GNU gcc compiler.
+dnl This is based on the macros above for G++.
+AC_DEFUN(CYG_AC_PROG_CC_CROSS,
+[AC_BEFORE([$0], [AC_PROG_CCPP])
+AC_CHECK_PROGS(CC, cc, gcc)
+
+CYG_AC_PROG_GCC_WORKS
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+dnl Check whether -g works, even if CFLAGS is set, in case the package
+dnl plays around with CFLAGS (such as to build both debugging and
+dnl normal versions of a library), tasteless as that idea is.
+  ac_test_CFLAGS="${CFLAGS+set}"
+  ac_save_CFLAGS="$CFLAGS"
+  CFLAGS=
+  AC_PROG_CC_G
+  if test "$ac_test_CFLAGS" = set; then
+    CFLAGS="$ac_save_CFLAGS"
+  elif test $ac_cv_prog_cc_g = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-O2"
+  fi
+else
+  GXX=
+  test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+])
+
+dnl See if the GCC compiler we found works.
+AC_DEFUN(CYG_AC_PROG_GCC_WORKS,
+[AC_MSG_CHECKING([whether the Gcc compiler ($CC $CFLAGS $LDFLAGS) actually works])
+AC_LANG_SAVE
+AC_LANG_C
+dnl Try a test case. We only compile, because it's close to impossible
+dnl to get a correct fully linked executable with a cross
+dnl compiler. For most cross compilers, this test is bogus. For G++,
+dnl we can use various other compile line options to get a decent idea
+dnl that the cross compiler actually does work, even though we can't
+dnl produce an executable without more info about the target it's
+dnl being compiled for. This only works for the GNU C++ compiler.
+
+dnl Transform the name of the compiler to it's cross variant, unless
+dnl CXX is set. This is also what CC gets set to in the generated Makefile.
+if test x"${CC}" = xcc ; then
+    CC=`echo gcc | sed -e "${program_transform_name}"`
+fi
+
+dnl Get Gcc's full path to libgcc.a
+libgccpath=`${CC} --print-libgcc`
+
+dnl If we don't have a path with libgcc.a on the end, this isn't G++.
+if test `echo $libgccpath | sed -e 's:/.*/::'` = libgcc.a ; then
+   ac_cv_prog_gcc=yes
+else
+   ac_cv_prog_gcc=no
+fi
+
+dnl If we are using Gcc, look for the files that need to exist if this
+dnl compiler works.
+if test x"${ac_cv_prog_gcc}" = xyes ; then
+    gccfiles=`echo $libgccpath | sed -e 's:/libgcc.a::'`
+    if test -f ${gccfiles}/specs -a -f ${gccfiles}/cpp -a -f ${gccfiles}/cc1plus; then
+       gccfiles=yes
+    else
+       gccfiles=no
+    fi
+    gcclibs=`echo $libgccpath | sed -e 's:lib/gcc-lib/::' -e 's:/libgcc.a::' -e 's,\(.*\)/.*,\1,g'`/lib
+    if test -d ${gcclibs}/ldscripts -a -f ${gcclibs}/libc.a -a -f ${gcclibs}/libstdc++.a ; then
+       gcclibs=yes
+    else
+       gcclibs=no
+    fi
+fi
+
+dnl If everything is OK, then we can safely assume the compiler works.
+if test x"${gccfiles}" = xno -o x"${gcclibs}" = xno; then
+    ac_cv_prog_cc_works=no
+    AC_MSG_ERROR(${CC} is a non-working cross compiler)    
+else
+    ac_cv_prog_cc_works=yes
+fi
+
+AC_LANG_RESTORE
+AC_MSG_RESULT($ac_cv_prog_cc_works)
+if test x"$ac_cv_prog_cc_works" = xno; then
+  AC_MSG_ERROR([installation or configuration problem: C++ compiler cannot create executables.])
+fi
+AC_MSG_CHECKING([whether the Gcc compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler])
+AC_MSG_RESULT($ac_cv_prog_cc_cross)
+cross_compiling=$ac_cv_prog_cc_cross
+AC_SUBST(CC)
+])
+
+dnl ====================================================================
+dnl Find the BFD library in the build tree. This is used to access and
+dnl manipulate object or executable files.
+AC_DEFUN(CYG_AC_PATH_BFD, [
+AC_MSG_CHECKING(for the bfd header in the build tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+dnl Look for the header file
+AC_CACHE_VAL(ac_cv_c_bfdh,[
+for i in $dirlist; do
+    if test -f "$i/bfd/bfd.h" ; then
+       ac_cv_c_bfdh=`(cd $i/bfd; pwd)`
+       break
+    fi
+done
+])
+if test x"${ac_cv_c_bfdh}" != x; then
+    BFDHDIR="-I${ac_cv_c_bfdh}"
+    AC_MSG_RESULT(${ac_cv_c_bfdh})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(BFDHDIR)
+
+dnl Look for the library
+AC_MSG_CHECKING(for the bfd library in the build tree)
+AC_CACHE_VAL(ac_cv_c_bfdlib,[
+for i in $dirlist; do
+    if test -f "$i/bfd/Makefile" ; then
+       ac_cv_c_bfdlib=`(cd $i/bfd; pwd)`
+    fi
+done
+])
+dnl We list two directories cause bfd now uses libtool
+if test x"${ac_cv_c_bfdlib}" != x; then
+    BFDLIB="-L${ac_cv_c_bfdlib} -L${ac_cv_c_bfdlib}/.libs"
+    AC_MSG_RESULT(${ac_cv_c_bfdlib})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(BFDLIB)
+])
+
+dnl ====================================================================
+dnl Find the libiberty library. This defines many commonly used C
+dnl functions that exists in various states based on the underlying OS.
+AC_DEFUN(CYG_AC_PATH_LIBERTY, [
+AC_MSG_CHECKING(for the liberty library in the build tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+AC_CACHE_VAL(ac_cv_c_liberty,[
+for i in $dirlist; do
+    if test -f "$i/libiberty/Makefile" ; then
+       ac_cv_c_liberty=`(cd $i/libiberty; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_liberty}" != x; then
+    LIBERTY="-L${ac_cv_c_liberty}"
+    AC_MSG_RESULT(${ac_cv_c_liberty})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(LIBERTY)
+])
+
+dnl ====================================================================
+dnl Find the opcodes library. This is used to do dissasemblies.
+AC_DEFUN(CYG_AC_PATH_OPCODES, [
+AC_MSG_CHECKING(for the opcodes library in the build tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+AC_CACHE_VAL(ac_cv_c_opc,[
+for i in $dirlist; do
+    if test -f "$i/opcodes/Makefile" ; then
+       ac_cv_c_opc=`(cd $i/opcodes; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_opc}" != x; then
+    OPCODESLIB="-L${ac_cv_c_opc}"
+    AC_MSG_RESULT(${ac_cv_c_opc})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(OPCODESLIB)
+])
+
+dnl ====================================================================
+dnl Look for the DejaGnu header file in the source tree. This file
+dnl defines the functions used to testing support.
+AC_DEFUN(CYG_AC_PATH_DEJAGNU, [
+AC_MSG_CHECKING(for the testing support files in the source tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+AC_CACHE_VAL(ac_cv_c_dejagnu,[
+for i in $dirlist; do
+    if test -f "$srcdir/$i/ecc/ecc/infra/testlib/current/include/dejagnu.h" ; then
+       ac_cv_c_dejagnu=`(cd $srcdir/$i/ecc/ecc/infra/testlib/current/include; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_dejagnu}" != x; then
+    DEJAGNUHDIR="-I${ac_cv_c_dejagnu}"
+    AC_MSG_RESULT(${ac_cv_c_dejagnu})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_CACHE_VAL(ac_cv_c_dejagnulib,[
+for i in $dirlist; do
+    if test -f "$srcdir/$i/infra/testlib/current/lib/hostutil.exp" ; then
+       ac_cv_c_dejagnulib=`(cd $srcdir/$i/infra/testlib/current/lib; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_dejagnulib}" != x; then
+    DEJAGNULIB="${ac_cv_c_dejagnulib}"
+else
+    DEJAGNULIB=""
+fi
+AC_MSG_CHECKING(for runtest in the source tree)
+AC_CACHE_VAL(ac_cv_c_runtest,[
+for i in $dirlist; do
+    if test -f "$srcdir/$i/dejagnu/runtest" ; then
+       ac_cv_c_runtest=`(cd $srcdir/$i/dejagnu; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_runtest}" != x; then
+    RUNTESTDIR="${ac_cv_c_runtest}"
+   AC_MSG_RESULT(${ac_cv_c_runtest})
+else
+    RUNTESTDIR=""
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(RUNTESTDIR)
+AC_SUBST(DEJAGNULIB)
+AC_SUBST(DEJAGNUHDIR)
+])
+
+dnl ====================================================================
+dnl Find the libintl library in the build tree. This is for
+dnl  internationalization support.
+AC_DEFUN(CYG_AC_PATH_INTL, [
+AC_MSG_CHECKING(for the intl header in the build tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+dnl Look for the header file
+AC_CACHE_VAL(ac_cv_c_intlh,[
+for i in $dirlist; do
+    if test -f "$i/intl/libintl.h" ; then
+       ac_cv_c_intlh=`(cd $i/intl; pwd)`
+       break
+    fi
+done
+])
+if test x"${ac_cv_c_intlh}" != x; then
+    INTLHDIR="-I${ac_cv_c_intlh}"
+    AC_MSG_RESULT(${ac_cv_c_intlh})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(INTLHDIR)
+
+dnl Look for the library
+AC_MSG_CHECKING(for the libintl library in the build tree)
+AC_CACHE_VAL(ac_cv_c_intllib,[
+for i in $dirlist; do
+    if test -f "$i/intl/Makefile" ; then
+       ac_cv_c_intllib=`(cd $i/intl; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_intllib}" != x; then
+    INTLLIB="-L${ac_cv_c_intllib} -lintl"
+    AC_MSG_RESULT(${ac_cv_c_intllib})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(INTLLIB)
+])
+
+dnl ====================================================================
+dnl Find the simulator library.
+AC_DEFUN(CYG_AC_PATH_SIM, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.. ../../../../../../../../../.."
+case "$target_cpu" in
+    powerpc)   target_dir=ppc ;;
+    sparc*)    target_dir=erc32 ;;
+    mips*)     target_dir=mips ;;
+    *)         target_dir=$target_cpu ;;
+esac
+dnl First look for the header file
+AC_MSG_CHECKING(for the simulator header file)
+AC_CACHE_VAL(ac_cv_c_simh,[
+for i in $dirlist; do
+    if test -f "${srcdir}/$i/include/remote-sim.h" ; then
+       ac_cv_c_simh=`(cd ${srcdir}/$i/include; pwd)`
+       break
+    fi
+done
+])
+if test x"${ac_cv_c_simh}" != x; then
+    SIMHDIR="-I${ac_cv_c_simh}"
+    AC_MSG_RESULT(${ac_cv_c_simh})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(SIMHDIR)
+
+dnl See whether it's a devo or Foundry branch simulator
+AC_MSG_CHECKING(Whether this is a devo simulator )
+AC_CACHE_VAL(ac_cv_c_simdevo,[
+    CPPFLAGS="$CPPFLAGS $SIMHDIR"
+    AC_EGREP_HEADER([SIM_DESC sim_open.*struct _bfd], remote-sim.h,
+        ac_cv_c_simdevo=yes,
+        ac_cv_c_simdevo=no)
+])
+if test x"$ac_cv_c_simdevo" = x"yes" ; then
+    AC_DEFINE(HAVE_DEVO_SIM)
+fi
+AC_MSG_RESULT(${ac_cv_c_simdevo})
+AC_SUBST(HAVE_DEVO_SIM)
+
+dnl Next look for the library
+AC_MSG_CHECKING(for the simulator library)
+AC_CACHE_VAL(ac_cv_c_simlib,[
+for i in $dirlist; do
+    if test -f "$i/sim/$target_dir/Makefile" ; then
+       ac_cv_c_simlib=`(cd $i/sim/$target_dir; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_simlib}" != x; then
+    SIMLIB="-L${ac_cv_c_simlib}"
+else
+    AC_MSG_RESULT(none)
+    dnl FIXME: this is kinda bogus, cause umtimately the TM will build
+    dnl all the libraries for several architectures. But for now, this
+    dnl will work till then.
+dnl     AC_MSG_CHECKING(for the simulator installed with the compiler libraries)
+    dnl Transform the name of the compiler to it's cross variant, unless
+    dnl CXX is set. This is also what CXX gets set to in the generated
+    dnl Makefile.
+    CROSS_GCC=`echo gcc | sed -e "s/^/$target/"`
+
+    dnl Get G++'s full path to libgcc.a
+changequote(,)
+    gccpath=`${CROSS_GCC} --print-libgcc | sed -e 's:[a-z0-9A-Z\.\-]*/libgcc.a::' -e 's:lib/gcc-lib/::'`lib
+changequote([,])
+    if test -f $gccpath/libsim.a -o -f $gccpath/libsim.so ; then
+        ac_cv_c_simlib="$gccpath/"
+        SIMLIB="-L${ac_cv_c_simlib}"
+       AC_MSG_RESULT(${ac_cv_c_simlib})
+    else
+        AM_CONDITIONAL(PSIM, test x$psim = xno)
+       SIMLIB=""
+       AC_MSG_RESULT(none)
+dnl         ac_cv_c_simlib=none
+    fi
+fi
+AC_SUBST(SIMLIB)
+])
+
+dnl ====================================================================
+dnl Find the libiberty library.
+AC_DEFUN(CYG_AC_PATH_LIBIBERTY, [
+AC_MSG_CHECKING(for the libiberty library in the build tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+AC_CACHE_VAL(ac_cv_c_libib,[
+for i in $dirlist; do
+    if test -f "$i/libiberty/Makefile" ; then
+       ac_cv_c_libib=`(cd $i/libiberty/; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_libib}" != x; then
+    LIBIBERTY="-L${ac_cv_c_libib}"
+    AC_MSG_RESULT(${ac_cv_c_libib})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(LIBIBERTY)
+])
+
+dnl ====================================================================
+AC_DEFUN(CYG_AC_PATH_DEVO, [
+AC_MSG_CHECKING(for devo headers in the source tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+AC_CACHE_VAL(ac_cv_c_devoh,[
+for i in $dirlist; do
+    if test -f "${srcdir}/$i/include/remote-sim.h" ; then
+       ac_cv_c_devoh=`(cd ${srcdir}/$i/include; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_devoh}" != x; then
+    DEVOHDIR="-I${ac_cv_c_devoh}"
+    AC_MSG_RESULT(${ac_cv_c_devoh})
+else
+    AC_MSG_RESULT(none)
+fi
+AC_SUBST(DEVOHDIR)
+])
+
+dnl ====================================================================
+dnl find the IDE library and headers.
+AC_DEFUN(CYG_AC_PATH_IDE, [
+AC_MSG_CHECKING(for IDE headers in the source tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+IDEHDIR=
+IDELIB=
+AC_CACHE_VAL(ac_cv_c_ideh,[
+for i in $dirlist; do
+    if test -f "${srcdir}/$i/libide/src/event.h" ; then
+       ac_cv_c_ideh=`(cd ${srcdir}/$i/libide/src; pwd)`;
+    fi
+done
+])
+if test x"${ac_cv_c_ideh}" != x; then
+    IDEHDIR="-I${ac_cv_c_ideh}"
+    AC_MSG_RESULT(${ac_cv_c_ideh})
+else
+    AC_MSG_RESULT(none)
+fi
+
+AC_MSG_CHECKING(for LIBIDE TCL headers in the source tree)
+AC_CACHE_VAL(ac_cv_c_idetclh,[
+for i in $dirlist; do
+    if test -f "${srcdir}/$i/libidetcl/src/idetcl.h" ; then
+       ac_cv_c_idetclh=`(cd ${srcdir}/$i/libidetcl/src; pwd)`;
+    fi
+done
+])
+if test x"${ac_cv_c_idetclh}" != x; then
+    IDEHDIR="${IDEHDIR} -I${ac_cv_c_idetclh}"
+    AC_MSG_RESULT(${ac_cv_c_idetclh})
+else
+    AC_MSG_RESULT(none)
+fi
+
+AC_MSG_CHECKING(for IDE headers in the build tree)
+AC_CACHE_VAL(ac_cv_c_ideh2,[
+for i in $dirlist; do
+    if test -f "$i/libide/src/Makefile" ; then
+       ac_cv_c_ideh2=`(cd $i/libide/src; pwd)`;
+    fi
+done
+])
+if test x"${ac_cv_c_ideh2}" != x; then
+    IDEHDIR="${IDEHDIR} -I${ac_cv_c_ideh2}"
+    AC_MSG_RESULT(${ac_cv_c_ideh2})
+else
+    AC_MSG_RESULT(none)
+fi
+
+dnl look for the library
+AC_MSG_CHECKING(for IDE library)
+AC_CACHE_VAL(ac_cv_c_idelib,[
+if test x"${ac_cv_c_idelib}" = x ; then
+    for i in $dirlist; do
+      if test -f "$i/libide/src/Makefile" ; then
+        ac_cv_c_idelib=`(cd $i/libide/src; pwd)`
+        break
+      fi
+    done
+fi]) 
+if test x"${ac_cv_c_idelib}" != x ; then
+     IDELIB="-L${ac_cv_c_idelib}"
+     AC_MSG_RESULT(${ac_cv_c_idelib})
+else
+     AC_MSG_RESULT(none)
+fi
+
+dnl find libiddetcl.a if it exists
+AC_MSG_CHECKING(for IDE TCL library)
+AC_CACHE_VAL(ac_cv_c_idetcllib,[
+if test x"${ac_cv_c_idetcllib}" = x ; then
+    for i in $dirlist; do
+      if test -f "$i/libidetcl/src/Makefile" ; then
+        ac_cv_c_idetcllib=`(cd $i/libidetcl/src; pwd)`
+        break
+      fi
+    done
+fi
+]) 
+if test x"${ac_cv_c_idetcllib}" != x ; then
+     IDELIB="${IDELIB} -L${ac_cv_c_idetcllib}"
+     IDETCLLIB="-lidetcl"
+     AC_MSG_RESULT(${ac_cv_c_idetcllib})
+else
+     AC_MSG_RESULT(none)
+fi
+AC_SUBST(IDEHDIR)
+AC_SUBST(IDELIB)
+AC_SUBST(IDETCLLIB)
+])
+
+dnl ====================================================================
+dnl Find all the ILU headers and libraries
+AC_DEFUN(CYG_AC_PATH_ILU, [
+AC_MSG_CHECKING(for ILU kernel headers in the source tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+AC_CACHE_VAL(ac_cv_c_iluh,[
+for i in $dirlist; do
+    if test -f "${srcdir}/$i/ilu/runtime/kernel/method.h" ; then
+       ac_cv_c_iluh=`(cd ${srcdir}/$i/ilu/runtime/kernel; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_iluh}" != x; then
+    ILUHDIR="-I${ac_cv_c_iluh}"
+    AC_MSG_RESULT(${ac_cv_c_iluh})
+else
+    AC_MSG_RESULT(none)
+fi
+
+AC_MSG_CHECKING(for ILU kernel headers in the build tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+AC_CACHE_VAL(ac_cv_c_iluh5,[
+for i in $dirlist; do
+    if test -f "$i/ilu/runtime/kernel/iluconf.h" ; then
+       ac_cv_c_iluh5=`(cd $i/ilu/runtime/kernel; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_iluh5}" != x; then
+    ILUHDIR="${ILUHDIR} -I${ac_cv_c_iluh5}"
+    AC_MSG_RESULT(${ac_cv_c_iluh5})
+else
+    AC_MSG_RESULT(none)
+fi
+
+AC_MSG_CHECKING(for ILU C++ headers in the source tree)
+AC_CACHE_VAL(ac_cv_c_iluh2,[
+for i in $dirlist; do
+    if test -f "${srcdir}/$i/ilu/stubbers/cpp/resource.h" ; then
+       ac_cv_c_iluh2=`(cd ${srcdir}/$i/ilu/stubbers/cpp; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_iluh2}" != x; then
+    ILUHDIR="${ILUHDIR} -I${ac_cv_c_iluh2}"
+    AC_MSG_RESULT(${ac_cv_c_iluh2})
+else
+    AC_MSG_RESULT(none)
+fi
+
+AC_MSG_CHECKING(for ILU C headers)
+AC_CACHE_VAL(ac_cv_c_iluh3,[
+for i in $dirlist; do
+    if test -f "${srcdir}/$i/ilu/stubbers/c/resource.h" ; then
+       ac_cv_c_iluh3=`(cd ${srcdir}/$i/ilu/stubbers/c  ; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_iluh3}" != x; then
+    ILUHDIR="${ILUHDIR} -I${ac_cv_c_iluh3}"
+    AC_MSG_RESULT(${ac_cv_c_iluh3})
+else
+    AC_MSG_RESULT(none)
+fi
+
+AC_MSG_CHECKING(for ILU C runtime headers)
+AC_CACHE_VAL(ac_cv_c_iluh4,[
+for i in $dirlist; do
+    if test -f "${srcdir}/$i/ilu/runtime/c/ilucstub.h" ; then
+       ac_cv_c_iluh4=`(cd ${srcdir}/$i/ilu/runtime/c  ; pwd)`
+    fi
+done
+])
+if test x"${ac_cv_c_iluh4}" != x; then
+    ILUHDIR="${ILUHDIR} -I${ac_cv_c_iluh4}"
+    AC_MSG_RESULT(${ac_cv_c_iluh4})
+else
+    AC_MSG_RESULT(none)
+fi
+
+AC_CACHE_VAL(ac_cv_c_ilupath,[
+for i in $dirlist; do
+    if test -f "$i/ilu/Makefile" ; then
+       ac_cv_c_ilupath=`(cd $i/ilu; pwd)`
+       break
+    fi
+done
+])
+ILUTOP=${ac_cv_c_ilupath}
+
+AC_MSG_CHECKING(for the ILU library in the build tree)
+AC_CACHE_VAL(ac_cv_c_ilulib,[
+if test -f "$ac_cv_c_ilupath/runtime/kernel/Makefile" ; then
+    ac_cv_c_ilulib=`(cd $ac_cv_c_ilupath/runtime/kernel; pwd)`
+    AC_MSG_RESULT(found ${ac_cv_c_ilulib}/libilu.a)
+else
+    AC_MSG_RESULT(no)
+fi])
+   
+AC_MSG_CHECKING(for the ILU C++ bindings library in the build tree)
+AC_CACHE_VAL(ac_cv_c_ilulib2,[
+if test -f "$ac_cv_c_ilupath/runtime/cpp/Makefile" ; then
+    ac_cv_c_ilulib2=`(cd $ac_cv_c_ilupath/runtime/cpp; pwd)`
+    AC_MSG_RESULT(found ${ac_cv_c_ilulib2}/libilu-c++.a)
+else
+    AC_MSG_RESULT(no)
+fi])
+
+AC_MSG_CHECKING(for the ILU C bindings library in the build tree)
+AC_CACHE_VAL(ac_cv_c_ilulib3,[
+if test -f "$ac_cv_c_ilupath/runtime/c/Makefile" ; then
+    ac_cv_c_ilulib3=`(cd $ac_cv_c_ilupath/runtime/c; pwd)`
+    AC_MSG_RESULT(found ${ac_cv_c_ilulib3}/libilu-c.a)
+else
+    AC_MSG_RESULT(no)
+fi])
+
+AC_MSG_CHECKING(for the ILU Tk bindings library in the build tree)
+AC_CACHE_VAL(ac_cv_c_ilulib4,[
+if test -f "$ac_cv_c_ilupath/runtime/mainloop/Makefile" ; then
+    ac_cv_c_ilulib4=`(cd $ac_cv_c_ilupath/runtime/mainloop; pwd)`
+    AC_MSG_RESULT(found ${ac_cv_c_ilulib4}/libilu-tk.a)
+else
+    AC_MSG_RESULT(no)
+fi])
+
+if test x"${ac_cv_c_ilulib}" = x -a x"${ac_cv_c_ilulib2}" = x; then
+  ILUHDIR=""
+fi
+
+if test x"${ac_cv_c_ilulib}" != x -a x"${ac_cv_c_ilulib2}" != x; then
+    ILULIB="-L${ac_cv_c_ilulib} -L${ac_cv_c_ilulib2} -L${ac_cv_c_ilulib3} -L${ac_cv_c_ilulib4}"
+else
+    ILULIB=""
+fi
+
+if test x"${ILULIB}" = x; then
+    AC_MSG_CHECKING(for ILU libraries installed with the compiler)
+    AC_CACHE_VAL(ac_cv_c_ilulib5,[
+    NATIVE_GCC=`echo gcc | sed -e "${program_transform_name}"`
+
+    dnl Get G++'s full path to it's libraries
+    ac_cv_c_ilulib5=`${NATIVE_GCC} --print-libgcc | sed -e 's:lib/gcc-lib/.*::'`lib
+    if test -f $ac_cv_c_ilulib5/libilu-c.a -o -f $ac_cv_c_ilulib5/libilu-c.so ; then
+        if test x"${ILUHDIR}" = x; then
+               ILUHDIR="-I${ac_cv_c_ilulib5}/../include"
+        fi
+        ILULIB="-L${ac_cv_c_ilulib5}"
+        AC_MSG_RESULT(${ac_cv_c_ilulib5})
+    else
+        ac_cv_c_ilulib=none
+        AC_MSG_RESULT(none)
+    fi
+fi])
+AC_SUBST(ILUHDIR)
+AC_SUBST(ILULIB)
+AC_SUBST(ILUTOP)
+])
+
+dnl ====================================================================
+dnl This defines the byte order for the host. We can't use
+dnl AC_C_BIGENDIAN, cause we want to create a config file and
+dnl substitue the real value, so the header files work right
+AC_DEFUN(CYG_AC_C_ENDIAN, [
+AC_MSG_CHECKING(to see if this is a little endian host)
+AC_CACHE_VAL(ac_cv_c_little_endian, [
+ac_cv_c_little_endian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/param.h>], [
+#if !BYTE_ORDER || !_BIG_ENDIAN || !_LITTLE_ENDIAN
+ bogus endian macros
+#endif], [# It does; now see whether it defined to _LITTLE_ENDIAN or not.
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/param.h>], [
+#if BYTE_ORDER != _LITTLE_ENDIAN
+ not big endian
+#endif], ac_cv_c_little_endian=yes, ac_cv_c_little_endian=no)
+])
+if test ${ac_cv_c_little_endian} = unknown; then
+old_cflags=$CFLAGS
+CFLAGS=-g
+AC_TRY_RUN([
+main () {
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[0] == 1);
+}],
+ac_cv_c_little_endian=no,
+ac_cv_c_little_endian=yes,[
+dnl Yes, this is ugly, and only used for a canadian cross anyway. This
+dnl is just to keep configure from stopping here.
+case "${host}" in
+changequote(,)
+   i[3456]86-*-*) ac_cv_c_little_endian=yes ;;
+   sparc*-*-*)    ac_cv_c_little_endian=no ;;
+changequote([,])
+  *)    AC_MSG_WARN(Can't cross compile this test) ;;
+esac])
+CFLAGS=$old_cflags
+fi])
+
+if test x"${ac_cv_c_little_endian}" = xyes; then
+    AC_DEFINE(LITTLE_ENDIAN_HOST)
+    ENDIAN="CYG_LSBFIRST";
+else
+    ENDIAN="CYG_MSBFIRST";
+fi
+AC_MSG_RESULT(${ac_cv_c_little_endian})
+AC_SUBST(ENDIAN)
+])
+
+dnl ====================================================================
+dnl Look for the path to libgcc, so we can use it to directly link
+dnl in libgcc.a with LD.
+AC_DEFUN(CYG_AC_PATH_LIBGCC,
+[AC_MSG_CHECKING([Looking for the path to libgcc.a])
+AC_LANG_SAVE
+AC_LANG_C
+
+dnl Get Gcc's full path to libgcc.a
+libgccpath=`${CC} --print-libgcc`
+
+dnl If we don't have a path with libgcc.a on the end, this isn't G++.
+if test `echo $libgccpath | sed -e 's:/.*/::'` = libgcc.a ; then
+   ac_cv_prog_gcc=yes
+else
+   ac_cv_prog_gcc=no
+fi
+
+dnl 
+if test x"${ac_cv_prog_gcc}" = xyes ; then
+   gccpath=`echo $libgccpath | sed -e 's:/libgcc.a::'`
+   LIBGCC="-L${gccpath}"
+   AC_MSG_RESULT(${gccpath})
+else
+   LIBGCC=""
+   AC_MSG_ERROR(Not using gcc)
+fi
+
+AC_LANG_RESTORE
+AC_SUBST(LIBGCC)
+])
+
+dnl ====================================================================
+dnl Ok, lets find the tcl source trees so we can use the headers
+dnl Warning: transition of version 9 to 10 will break this algorithm
+dnl because 10 sorts before 9. We also look for just tcl. We have to
+dnl be careful that we don't match stuff like tclX by accident.
+dnl the alternative search directory is involked by --with-tclinclude
+AC_DEFUN(CYG_AC_PATH_TCL, [
+    CYG_AC_PATH_TCLH
+    CYG_AC_PATH_TCLCONFIG
+    CYG_AC_LOAD_TCLCONFIG
+])
+AC_DEFUN(CYG_AC_PATH_TCLH, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+no_tcl=true
+AC_MSG_CHECKING(for Tcl headers in the source tree)
+AC_ARG_WITH(tclinclude, [  --with-tclinclude       directory where tcl headers are], with_tclinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tclh,[
+dnl first check to see if --with-tclinclude was specified
+if test x"${with_tclinclude}" != x ; then
+  if test -f ${with_tclinclude}/tcl.h ; then
+    ac_cv_c_tclh=`(cd ${with_tclinclude}; pwd)`
+  elif test -f ${with_tclinclude}/generic/tcl.h ; then
+    ac_cv_c_tclh=`(cd ${with_tclinclude}/generic; pwd)`
+  else
+    AC_MSG_ERROR([${with_tclinclude} directory doesn't contain headers])
+  fi
+fi
+
+dnl next check if it came with Tcl configuration file
+if test x"${ac_cv_c_tclconfig}" != x ; then
+  for i in $dirlist; do
+    if test -f $ac_cv_c_tclconfig/$i/generic/tcl.h ; then
+      ac_cv_c_tclh=`(cd $ac_cv_c_tclconfig/$i/generic; pwd)`
+      break
+    fi
+  done
+fi
+
+dnl next check in private source directory
+dnl since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+    dnl find the top level Tcl source directory
+    for i in $dirlist; do
+        if test -n "`ls -dr $srcdir/$i/tcl* 2>/dev/null`" ; then
+           tclpath=$srcdir/$i
+           break
+       fi
+    done
+
+    dnl find the exact Tcl source dir. We do it this way, cause there
+    dnl might be multiple version of Tcl, and we want the most recent one.
+    for i in `ls -dr $tclpath/tcl* 2>/dev/null ` ; do
+        if test -f $i/generic/tcl.h ; then
+          ac_cv_c_tclh=`(cd $i/generic; pwd)`
+          break
+        fi
+    done
+fi
+
+dnl check if its installed with the compiler
+if test x"${ac_cv_c_tclh}" = x ; then
+    dnl Get the path to the compiler
+    ccpath=`which ${CC}  | sed -e 's:/bin/.*::'`/include
+    if test -f $ccpath/tcl.h; then
+        ac_cv_c_tclh=$ccpath
+    fi
+fi
+
+dnl see if one is installed
+if test x"${ac_cv_c_tclh}" = x ; then
+   AC_MSG_RESULT(none)
+   AC_CHECK_HEADER(tcl.h, ac_cv_c_tclh=installed, ac_cv_c_tclh="")
+else
+   AC_MSG_RESULT(${ac_cv_c_tclh})
+fi
+])
+  TCLHDIR=""
+if test x"${ac_cv_c_tclh}" = x ; then
+    AC_MSG_ERROR([Can't find any Tcl headers])
+fi
+if test x"${ac_cv_c_tclh}" != x ; then
+    no_tcl=""
+    if test x"${ac_cv_c_tclh}" != x"installed" ; then
+       if test x"${CC}" = xcl ; then
+           tmp="`cygpath --windows ${ac_cv_c_tclh}`"
+           ac_cv_c_tclh="`echo $tmp | sed -e s#\\\\\\\\#/#g`"
+       fi
+        AC_MSG_RESULT(${ac_cv_c_tclh})
+        TCLHDIR="-I${ac_cv_c_tclh}"
+    fi
+fi
+
+AC_SUBST(TCLHDIR)
+])
+
+dnl ====================================================================
+dnl Ok, lets find the tcl configuration
+AC_DEFUN(CYG_AC_PATH_TCLCONFIG, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+dnl First, look for one uninstalled.  
+dnl the alternative search directory is invoked by --with-tclconfig
+if test x"${no_tcl}" = x ; then
+  dnl we reset no_tcl in case something fails here
+    no_tcl=true
+    AC_ARG_WITH(tclconfig, [  --with-tclconfig           directory containing tcl configuration (tclConfig.sh)],
+         with_tclconfig=${withval})
+    AC_MSG_CHECKING([for Tcl configuration script])
+    AC_CACHE_VAL(ac_cv_c_tclconfig,[
+
+    dnl First check to see if --with-tclconfig was specified.
+    if test x"${with_tclconfig}" != x ; then
+        if test -f "${with_tclconfig}/tclConfig.sh" ; then
+            ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
+        else
+            AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
+        fi
+    fi
+
+    dnl next check if it came with Tcl configuration file in the source tree
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+        for i in $dirlist; do
+            if test -f $srcdir/$i/unix/tclConfig.sh ; then
+                ac_cv_c_tclconfig=`(cd $srcdir/$i/unix; pwd)`
+               break
+            fi
+        done
+    fi
+    dnl check in a few other locations
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+        dnl find the top level Tcl source directory
+        for i in $dirlist; do
+            if test -n "`ls -dr $i/tcl* 2>/dev/null`" ; then
+               tclconfpath=$i
+               break
+           fi
+        done
+
+        dnl find the exact Tcl dir. We do it this way, cause there
+        dnl might be multiple version of Tcl, and we want the most recent one.
+        for i in `ls -dr $tclconfpath/tcl* 2>/dev/null ` ; do
+            if test -f $i/unix/tclConfig.sh ; then
+                ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
+                break
+            fi
+        done
+    fi
+
+    dnl Check to see if it's installed. We have to look in the $CC path
+    dnl to find it, cause our $prefix may not match the compilers.
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+        dnl Get the path to the compiler
+       ccpath=`which ${CC}  | sed -e 's:/bin/.*::'`/lib
+        if test -f $ccpath/tclConfig.sh; then
+           ac_cv_c_tclconfig=$ccpath
+        fi
+    fi
+    ]) dnl end of cache_val
+
+    if test x"${ac_cv_c_tclconfig}" = x ; then
+        TCLCONFIG=""
+        AC_MSG_WARN(Can't find Tcl configuration definitions)
+    else
+        no_tcl=""
+        TCLCONFIG=${ac_cv_c_tclconfig}/tclConfig.sh
+        AC_MSG_RESULT(${TCLCONFIG})
+     fi
+fi
+AC_SUBST(TCLCONFIG)
+])
+
+dnl Defined as a separate macro so we don't have to cache the values
+dnl from PATH_TCLCONFIG (because this can also be cached).
+AC_DEFUN(CYG_AC_LOAD_TCLCONFIG, [
+    . $TCLCONFIG
+
+dnl AC_SUBST(TCL_VERSION)
+dnl AC_SUBST(TCL_MAJOR_VERSION)
+dnl AC_SUBST(TCL_MINOR_VERSION)
+dnl AC_SUBST(TCL_CC)
+    AC_SUBST(TCL_DEFS)
+
+dnl not used, don't export to save symbols
+    AC_SUBST(TCL_LIB_FILE)
+    AC_SUBST(TCL_LIB_FULL_PATH)
+    AC_SUBST(TCL_LIBS)
+dnl not used, don't export to save symbols
+dnl    AC_SUBST(TCL_PREFIX)
+
+    AC_SUBST(TCL_CFLAGS)
+
+dnl not used, don't export to save symbols
+dnl    AC_SUBST(TCL_EXEC_PREFIX)
+
+    AC_SUBST(TCL_SHLIB_CFLAGS)
+    AC_SUBST(TCL_SHLIB_LD)
+dnl don't export, not used outside of configure
+dnl AC_SUBST(TCL_SHLIB_LD_LIBS)
+dnl AC_SUBST(TCL_SHLIB_SUFFIX)
+dnl not used, don't export to save symbols
+dnl AC_SUBST(TCL_DL_LIBS)
+    AC_SUBST(TCL_LD_FLAGS)
+    AC_SUBST(TCL_LD_SEARCH_FLAGS)
+dnl don't export, not used outside of configure
+dnl AC_SUBST(TCL_COMPAT_OBJS)
+    AC_SUBST(TCL_RANLIB)
+    AC_SUBST(TCL_BUILD_LIB_SPEC)
+    AC_SUBST(TCL_LIB_SPEC)
+dnl AC_SUBST(TCL_LIB_VERSIONS_OK)
+
+dnl not used, don't export to save symbols
+dnl    AC_SUBST(TCL_SHARED_LIB_SUFFIX)
+
+dnl not used, don't export to save symbols
+dnl    AC_SUBST(TCL_UNSHARED_LIB_SUFFIX)
+])
+
+dnl ====================================================================
+AC_DEFUN(CYG_AC_PATH_TK, [
+    CYG_AC_PATH_TKH
+    CYG_AC_PATH_TKCONFIG
+    CYG_AC_LOAD_TKCONFIG
+])
+AC_DEFUN(CYG_AC_PATH_TKH, [
+#
+# Ok, lets find the tk source trees so we can use the headers
+# If the directory (presumably symlink) named "tk" exists, use that one
+# in preference to any others.  Same logic is used when choosing library
+# and again with Tcl. The search order is the best place to look first, then in
+# decreasing significance. The loop breaks if the trigger file is found.
+# Note the gross little conversion here of srcdir by cd'ing to the found
+# directory. This converts the path from a relative to an absolute, so
+# recursive cache variables for the path will work right. We check all
+# the possible paths in one loop rather than many seperate loops to speed
+# things up.
+# the alternative search directory is involked by --with-tkinclude
+#
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+no_tk=true
+AC_MSG_CHECKING(for Tk headers in the source tree)
+AC_ARG_WITH(tkinclude, [  --with-tkinclude       directory where tk headers are], with_tkinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tkh,[
+dnl first check to see if --with-tkinclude was specified
+if test x"${with_tkinclude}" != x ; then
+  if test -f ${with_tkinclude}/tk.h ; then
+    ac_cv_c_tkh=`(cd ${with_tkinclude}; pwd)`
+  elif test -f ${with_tkinclude}/generic/tk.h ; then
+    ac_cv_c_tkh=`(cd ${with_tkinclude}/generic; pwd)`
+  else
+    AC_MSG_ERROR([${with_tkinclude} directory doesn't contain headers])
+  fi
+fi
+
+dnl next check if it came with Tk configuration file
+if test x"${ac_cv_c_tkconfig}" != x ; then
+  for i in $dirlist; do
+    if test -f $ac_cv_c_tkconfig/$i/generic/tk.h ; then
+      ac_cv_c_tkh=`(cd $ac_cv_c_tkconfig/$i/generic; pwd)`
+      break
+    fi
+  done
+fi
+
+dnl next check in private source directory
+dnl since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tkh}" = x ; then
+    dnl find the top level Tk source directory
+    for i in $dirlist; do
+        if test -n "`ls -dr $srcdir/$i/tk* 2>/dev/null`" ; then
+           tkpath=$srcdir/$i
+           break
+       fi
+    done
+
+    dnl find the exact Tk source dir. We do it this way, cause there
+    dnl might be multiple version of Tk, and we want the most recent one.
+    for i in `ls -dr $tkpath/tk* 2>/dev/null ` ; do
+        if test -f $i/generic/tk.h ; then
+          ac_cv_c_tkh=`(cd $i/generic; pwd)`
+          break
+        fi
+    done
+fi
+
+dnl see if one is installed
+if test x"${ac_cv_c_tkh}" = x ; then
+    AC_MSG_RESULT(none)
+    dnl Get the path to the compiler. We do it this way instead of using
+    dnl AC_CHECK_HEADER, cause this doesn't depend in having X configured.
+    ccpath=`which ${CC}  | sed -e 's:/bin/.*::'`/include
+    if test -f $ccpath/tk.h; then
+       ac_cv_c_tkh=$ccpath
+    fi
+else
+   AC_MSG_RESULT(${ac_cv_c_tkh})
+fi
+])
+  TKHDIR=""
+if test x"${ac_cv_c_tkh}" = x ; then
+    AC_MSG_ERROR([Can't find any Tk headers])
+fi
+if test x"${ac_cv_c_tkh}" != x ; then
+    no_tk=""
+    if test x"${ac_cv_c_tkh}" != x"installed" ; then
+       if test x"${CC}" = xcl ; then
+           tmp="`cygpath --windows ${ac_cv_c_tkh}`"
+           ac_cv_c_tkh="`echo $tmp | sed -e s#\\\\\\\\#/#g`"
+       fi
+        AC_MSG_RESULT([found in ${ac_cv_c_tkh}])
+        TKHDIR="-I${ac_cv_c_tkh}"
+    fi
+fi
+
+AC_SUBST(TKHDIR)
+])
+
+AC_DEFUN(CYG_AC_PATH_TKCONFIG, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+dnl First, look for one uninstalled.  
+dnl the alternative search directory is invoked by --with-tkconfig
+if test x"${no_tk}" = x ; then
+  dnl we reset no_tk in case something fails here
+    no_tk=true
+    AC_ARG_WITH(tkconfig, [  --with-tkconfig           directory containing tk configuration (tkConfig.sh)],
+         with_tkconfig=${withval})
+    AC_MSG_CHECKING([for Tk configuration script])
+    AC_CACHE_VAL(ac_cv_c_tkconfig,[
+
+    dnl First check to see if --with-tkconfig was specified.
+    if test x"${with_tkconfig}" != x ; then
+        if test -f "${with_tkconfig}/tkConfig.sh" ; then
+            ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
+        else
+            AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
+        fi
+    fi
+
+    dnl next check if it came with Tk configuration file in the source tree
+    if test x"${ac_cv_c_tkconfig}" = x ; then
+        for i in $dirlist; do
+            if test -f $srcdir/$i/unix/tkConfig.sh ; then
+                ac_cv_c_tkconfig=`(cd $srcdir/$i/unix; pwd)`
+               break
+            fi
+        done
+    fi
+    dnl check in a few other locations
+    if test x"${ac_cv_c_tkconfig}" = x ; then
+        dnl find the top level Tk source directory
+        for i in $dirlist; do
+            if test -n "`ls -dr $i/tk* 2>/dev/null`" ; then
+               tkconfpath=$i
+               break
+           fi
+        done
+
+        dnl find the exact Tk dir. We do it this way, cause there
+        dnl might be multiple version of Tk, and we want the most recent one.
+        for i in `ls -dr $tkconfpath/tk* 2>/dev/null ` ; do
+            if test -f $i/unix/tkConfig.sh ; then
+                ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
+                break
+            fi
+        done
+    fi
+
+    dnl Check to see if it's installed. We have to look in the $CC path
+    dnl to find it, cause our $prefix may not match the compilers.
+    if test x"${ac_cv_c_tkconfig}" = x ; then
+        dnl Get the path to the compiler
+       ccpath=`which ${CC}  | sed -e 's:/bin/.*::'`/lib
+        if test -f $ccpath/tkConfig.sh; then
+           ac_cv_c_tkconfig=$ccpath
+        fi
+    fi
+    ]) dnl end of cache_val
+
+    if test x"${ac_cv_c_tkconfig}" = x ; then
+        TKCONFIG=""
+        AC_MSG_WARN(Can't find Tk configuration definitions)
+    else
+        no_tk=""
+        TKCONFIG=${ac_cv_c_tkconfig}/tkConfig.sh
+        AC_MSG_RESULT(${TKCONFIG})
+     fi
+fi
+AC_SUBST(TKCONFIG)
+])
+
+dnl Defined as a separate macro so we don't have to cache the values
+dnl from PATH_TKCONFIG (because this can also be cached).
+AC_DEFUN(CYG_AC_LOAD_TKCONFIG, [
+    if test -f "$TKCONFIG" ; then
+      . $TKCONFIG
+    fi
+
+    AC_SUBST(TK_VERSION)
+dnl not actually used, don't export to save symbols
+dnl    AC_SUBST(TK_MAJOR_VERSION)
+dnl    AC_SUBST(TK_MINOR_VERSION)
+    AC_SUBST(TK_DEFS)
+
+dnl not used, don't export to save symbols
+    AC_SUBST(TK_LIB_FILE)
+    AC_SUBST(TK_LIB_FULL_PATH)
+    AC_SUBST(TK_LIBS)
+dnl not used, don't export to save symbols
+dnl    AC_SUBST(TK_PREFIX)
+
+dnl not used, don't export to save symbols
+dnl    AC_SUBST(TK_EXEC_PREFIX)
+    AC_SUBST(TK_BUILD_INCLUDES)
+    AC_SUBST(TK_XINCLUDES)
+    AC_SUBST(TK_XLIBSW)
+    AC_SUBST(TK_BUILD_LIB_SPEC)
+    AC_SUBST(TK_LIB_SPEC)
+])
+
+dnl ====================================================================
+dnl Ok, lets find the itcl source trees so we can use the headers
+dnl the alternative search directory is involked by --with-itclinclude
+AC_DEFUN(CYG_AC_PATH_ITCL, [
+    CYG_AC_PATH_ITCLH
+    CYG_AC_PATH_ITCLLIB
+    CYG_AC_PATH_ITCLSH
+    CYG_AC_PATH_ITCLMKIDX
+])
+AC_DEFUN(CYG_AC_PATH_ITCLH, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+no_itcl=true
+AC_MSG_CHECKING(for Itcl headers in the source tree)
+AC_ARG_WITH(itclinclude, [  --with-itclinclude       directory where itcl headers are], with_itclinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_itclh,[
+dnl first check to see if --with-itclinclude was specified
+if test x"${with_itclinclude}" != x ; then
+  if test -f ${with_itclinclude}/itcl.h ; then
+    ac_cv_c_itclh=`(cd ${with_itclinclude}; pwd)`
+  elif test -f ${with_itclinclude}/src/itcl.h ; then
+    ac_cv_c_itclh=`(cd ${with_itclinclude}/src; pwd)`
+  else
+    AC_MSG_ERROR([${with_itclinclude} directory doesn't contain headers])
+  fi
+fi
+
+dnl next check if it came with Itcl configuration file
+if test x"${ac_cv_c_itclconfig}" != x ; then
+  for i in $dirlist; do
+    if test -f $ac_cv_c_itclconfig/$i/src/itcl.h ; then
+      ac_cv_c_itclh=`(cd $ac_cv_c_itclconfig/$i/src; pwd)`
+      break
+    fi
+  done
+fi
+
+dnl next check in private source directory
+dnl since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_itclh}" = x ; then
+    dnl find the top level Itcl source directory
+    for i in $dirlist; do
+        if test -n "`ls -dr $srcdir/$i/itcl* 2>/dev/null`" ; then
+           itclpath=$srcdir/$i
+           break
+       fi
+    done
+
+    dnl find the exact Itcl source dir. We do it this way, cause there
+    dnl might be multiple version of Itcl, and we want the most recent one.
+    for i in `ls -dr $itclpath/itcl* 2>/dev/null ` ; do
+        if test -f $i/src/itcl.h ; then
+          ac_cv_c_itclh=`(cd $i/src; pwd)`
+          break
+        fi
+    done
+fi
+
+dnl see if one is installed
+if test x"${ac_cv_c_itclh}" = x ; then
+   AC_MSG_RESULT(none)
+   AC_CHECK_HEADER(itcl.h, ac_cv_c_itclh=installed, ac_cv_c_itclh="")
+else
+   AC_MSG_RESULT(${ac_cv_c_itclh})
+fi
+])
+  ITCLHDIR=""
+if test x"${ac_cv_c_itclh}" = x ; then
+    AC_MSG_ERROR([Can't find any Itcl headers])
+fi
+if test x"${ac_cv_c_itclh}" != x ; then
+    no_itcl=""
+    if test x"${ac_cv_c_itclh}" != x"installed" ; then
+        AC_MSG_RESULT(${ac_cv_c_itclh})
+        ITCLHDIR="-I${ac_cv_c_itclh}"
+    fi
+fi
+
+AC_SUBST(ITCLHDIR)
+])
+
+dnl Ok, lets find the itcl library
+dnl First, look for one uninstalled.  
+dnl the alternative search directory is invoked by --with-itcllib
+AC_DEFUN(CYG_AC_PATH_ITCLLIB, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+if test x"${no_itcl}" = x ; then
+    dnl we reset no_itcl incase something fails here
+    no_itcl=true
+    AC_ARG_WITH(itcllib,
+       [  --with-itcllib           directory where the itcl library is],
+        with_itcllib=${withval})
+    AC_MSG_CHECKING([for Itcl library])
+    AC_CACHE_VAL(ac_cv_c_itcllib,[
+    dnl First check to see if --with-itcllib was specified.
+    if test x"${with_itcllib}" != x ; then
+        if test -f "${with_itcllib}/libitcl$TCL_SHARED_LIB_SUFFIX" ; then
+            ac_cv_c_itcllib=`(cd ${with_itcllib}; pwd)`/libitcl$TCL_SHARED_LIB_SUFFIX
+       else
+           if test -f "${with_itcllib}/libitcl$TCL_UNSHARED_LIB_SUFFIX"; then
+               ac_cv_c_itcllib=`(cd ${with_itcllib}; pwd)`/libitcl$TCL_UNSHARED_LIB_SUFFIX
+           fi
+       fi
+    fi
+    dnl then check for a  Itcl library. Since these are uninstalled,
+    dnl use the simple lib name root. 
+    if test x"${ac_cv_c_itcllib}" = x ; then
+        dnl find the top level Itcl build directory
+        for i in $dirlist; do
+            if test -n "`ls -dr $i/itcl* 2>/dev/null`" ; then
+               itclpath=$i/itcl
+               break
+           fi
+        done
+        dnl Itcl 7.5 and greater puts library in subdir.  Look there first.
+        if test -f "$itclpath/src/libitcl.$TCL_SHLIB_SUFFIX" ; then
+            ac_cv_c_itcllib=`(cd $itclpath/src; pwd)`
+        elif test -f "$itclpath/src/libitcl.a"; then
+            ac_cv_c_itcllib=`(cd $itclpath/src; pwd)`
+       fi
+    fi
+    dnl check in a few other private locations
+    if test x"${ac_cv_c_itcllib}" = x ; then
+        for i in ${dirlist}; do
+            if test -n "`ls -dr ${srcdir}/$i/itcl* 2>/dev/null`" ; then
+               itclpath=${srcdir}/$i
+               break
+           fi
+        done
+        for i in `ls -dr ${itclpath}/itcl* 2>/dev/null` ; do
+            dnl Itcl 7.5 and greater puts library in subdir.  Look there first.
+            if test -f "$i/src/libitcl$TCL_SHLIB_SUFFIX" ; then
+               ac_cv_c_itcllib=`(cd $i/src; pwd)`
+               break
+            elif test -f "$i/src/libitcl.a"; then
+               ac_cv_c_itcllib=`(cd $i/src; pwd)`
+               break
+           fi  
+        done
+    fi
+
+    dnl see if one is conveniently installed with the compiler
+    if test x"${ac_cv_c_itcllib}" = x ; then
+        dnl Get the path to the compiler
+       ccpath=`which ${CC}  | sed -e 's:/bin/.*::'`/lib
+        dnl Itcl 7.5 and greater puts library in subdir.  Look there first.
+        if test -f "${ccpath}/libitcl$TCL_SHLIB_SUFFIX" ; then
+           ac_cv_c_itcllib=`(cd ${ccpath}; pwd)`
+        elif test -f "${ccpath}/libitcl.a"; then
+           ac_cv_c_itcllib=`(cd ${ccpath}; pwd)`
+        fi
+    fi
+    ])
+    if test x"${ac_cv_c_itcllib}" = x ; then
+        ITCLLIB=""
+        AC_MSG_WARN(Can't find Itcl library)
+    else
+        ITCLLIB="-L${ac_cv_c_itcllib}"
+        AC_MSG_RESULT(${ac_cv_c_itcllib})
+        no_itcl=""
+    fi
+fi
+
+AC_PROVIDE([$0])
+AC_SUBST(ITCLLIB)
+])
+
+
+dnl ====================================================================
+dnl Ok, lets find the itcl source trees so we can use the itcl_sh script
+dnl the alternative search directory is involked by --with-itclinclude
+AC_DEFUN(CYG_AC_PATH_ITCLSH, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+no_itcl=true
+AC_MSG_CHECKING(for the itcl_sh script)
+AC_ARG_WITH(itclinclude, [  --with-itclinclude       directory where itcl headers are], with_itclinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_itclsh,[
+dnl first check to see if --with-itclinclude was specified
+if test x"${with_itclinclude}" != x ; then
+  if test -f ${with_itclinclude}/itcl_sh ; then
+    ac_cv_c_itclsh=`(cd ${with_itclinclude}; pwd)`
+  elif test -f ${with_itclinclude}/src/itcl_sh ; then
+    ac_cv_c_itclsh=`(cd ${with_itclinclude}/src; pwd)`
+  else
+    AC_MSG_ERROR([${with_itclinclude} directory doesn't contain itcl_sh])
+  fi
+fi
+
+dnl next check in private source directory
+dnl since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_itclsh}" = x ; then
+    dnl find the top level Itcl source directory
+    for i in $dirlist; do
+        if test -n "`ls -dr $srcdir/$i/itcl* 2>/dev/null`" ; then
+           itclpath=$srcdir/$i
+           break
+       fi
+    done
+
+    dnl find the exact Itcl source dir. We do it this way, cause there
+    dnl might be multiple version of Itcl, and we want the most recent one.
+    for i in `ls -dr $itclpath/itcl* 2>/dev/null ` ; do
+        if test -f $i/src/itcl_sh ; then
+          ac_cv_c_itclsh=`(cd $i/src; pwd)`/itcl_sh
+          break
+        fi
+    done
+fi
+
+dnl see if one is installed
+if test x"${ac_cv_c_itclsh}" = x ; then
+   AC_MSG_RESULT(none)
+   AC_PATH_PROG(ac_cv_c_itclsh, itcl_sh)
+else
+   AC_MSG_RESULT(${ac_cv_c_itclsh})
+fi
+])
+
+if test x"${ac_cv_c_itclsh}" = x ; then
+    AC_MSG_ERROR([Can't find the itcl_sh script])
+fi
+if test x"${ac_cv_c_itclsh}" != x ; then
+    no_itcl=""
+    AC_MSG_RESULT(${ac_cv_c_itclsh})
+    ITCLSH="${ac_cv_c_itclsh}"
+fi
+AC_SUBST(ITCLSH)
+])
+
+
+dnl ====================================================================
+dnl Ok, lets find the itcl source trees so we can use the itcl_sh script
+dnl the alternative search directory is involked by --with-itclinclude
+AC_DEFUN(CYG_AC_PATH_ITCLMKIDX, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+no_itcl=true
+AC_MSG_CHECKING(for itcl_mkindex.tcl script)
+AC_ARG_WITH(itclinclude, [  --with-itclinclude       directory where itcl headers are], with_itclinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_itclmkidx,[
+dnl first check to see if --with-itclinclude was specified
+if test x"${with_itclinclude}" != x ; then
+  if test -f ${with_itclinclude}/itcl_sh ; then
+    ac_cv_c_itclmkidx=`(cd ${with_itclinclude}; pwd)`
+  elif test -f ${with_itclinclude}/src/itcl_sh ; then
+    ac_cv_c_itclmkidx=`(cd ${with_itclinclude}/src; pwd)`
+  else
+    AC_MSG_ERROR([${with_itclinclude} directory doesn't contain itcl_sh])
+  fi
+fi
+
+dnl next check in private source directory
+dnl since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_itclmkidx}" = x ; then
+    dnl find the top level Itcl source directory
+    for i in $dirlist; do
+        if test -n "`ls -dr $srcdir/$i/itcl* 2>/dev/null`" ; then
+           itclpath=$srcdir/$i
+           break
+       fi
+    done
+
+    dnl find the exact Itcl source dir. We do it this way, cause there
+    dnl might be multiple version of Itcl, and we want the most recent one.
+    for i in `ls -dr $itclpath/itcl* 2>/dev/null ` ; do
+        if test -f $i/library/itcl_mkindex.tcl ; then
+          ac_cv_c_itclmkidx=`(cd $i/library; pwd)`/itcl_mkindex.tcl
+          break
+        fi
+    done
+fi
+if test x"${ac_cv_c_itclmkidx}" = x ; then
+    dnl Get the path to the compiler
+    ccpath=`which ${CC}  | sed -e 's:/bin/.*::'`/share
+    dnl Itcl 7.5 and greater puts library in subdir.  Look there first.
+    for i in `ls -dr $ccpath/itcl* 2>/dev/null ` ; do
+        if test -f $i/itcl_mkindex.tcl ; then
+            ac_cv_c_itclmkidx=`(cd $i; pwd)`/itcl_mkindex.tcl
+            break
+        fi
+    done
+fi
+])
+
+if test x"${ac_cv_c_itclmkidx}" = x ; then
+    AC_MSG_ERROR([Can't find the itcl_mkindex.tcl script])
+fi
+if test x"${ac_cv_c_itclmkidx}" != x ; then
+    no_itcl=""
+    AC_MSG_RESULT(${ac_cv_c_itclmkidx})
+    ITCLMKIDX="${ac_cv_c_itclmkidx}"
+else
+   AC_MSG_RESULT(none)
+fi
+AC_SUBST(ITCLMKIDX)
+])
+
+dnl ====================================================================
+dnl Ok, lets find the tix source trees so we can use the headers
+dnl the alternative search directory is involked by --with-tixinclude
+AC_DEFUN(CYG_AC_PATH_TIX, [
+    CYG_AC_PATH_TIXH
+    CYG_AC_PATH_TIXLIB
+])
+AC_DEFUN(CYG_AC_PATH_TIXH, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+no_tix=true
+AC_MSG_CHECKING(for Tix headers in the source tree)
+AC_ARG_WITH(tixinclude, [  --with-tixinclude       directory where tix headers are], with_tixinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tixh,[
+dnl first check to see if --with-tixinclude was specified
+if test x"${with_tixinclude}" != x ; then
+  if test -f ${with_tixinclude}/tix.h ; then
+    ac_cv_c_tixh=`(cd ${with_tixinclude}; pwd)`
+  elif test -f ${with_tixinclude}/generic/tix.h ; then
+    ac_cv_c_tixh=`(cd ${with_tixinclude}/generic; pwd)`
+  else
+    AC_MSG_ERROR([${with_tixinclude} directory doesn't contain headers])
+  fi
+fi
+
+dnl next check if it came with Tix configuration file
+if test x"${ac_cv_c_tixconfig}" != x ; then
+  for i in $dirlist; do
+    if test -f $ac_cv_c_tixconfig/$i/generic/tix.h ; then
+      ac_cv_c_tixh=`(cd $ac_cv_c_tixconfig/$i/generic; pwd)`
+      break
+    fi
+  done
+fi
+
+dnl next check in private source directory
+dnl since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tixh}" = x ; then
+    dnl find the top level Tix source directory
+    for i in $dirlist; do
+        if test -n "`ls -dr $srcdir/$i/tix* 2>/dev/null`" ; then
+           tixpath=$srcdir/$i
+           break
+       fi
+    done
+
+    dnl find the exact Tix source dir. We do it this way, cause there
+    dnl might be multiple version of Tix, and we want the most recent one.
+    for i in `ls -dr $tixpath/tix* 2>/dev/null ` ; do
+        if test -f $i/generic/tix.h ; then
+          ac_cv_c_tixh=`(cd $i/generic; pwd)`
+          break
+        fi
+    done
+fi
+
+dnl see if one is installed
+if test x"${ac_cv_c_tixh}" = x ; then
+    AC_MSG_RESULT(none)
+    dnl Get the path to the compiler
+
+   dnl Get the path to the compiler. We do it this way instead of using
+    dnl AC_CHECK_HEADER, cause this doesn't depend in having X configured.
+    ccpath=`which ${CC}  | sed -e 's:/bin/.*::'`/include
+    if test -f $ccpath/tix.h; then
+       ac_cv_c_tixh=installed
+    fi
+else
+   AC_MSG_RESULT(${ac_cv_c_tixh})
+fi
+])
+if test x"${ac_cv_c_tixh}" = x ; then
+    AC_MSG_ERROR([Can't find any Tix headers])
+fi
+if test x"${ac_cv_c_tixh}" != x ; then
+    no_tix=""
+    AC_MSG_RESULT(${ac_cv_c_tixh})
+    if test x"${ac_cv_c_tixh}" != x"installed" ; then
+        TIXHDIR="-I${ac_cv_c_tixh}"
+    fi
+fi
+
+AC_SUBST(TIXHDIR)
+])
+
+AC_DEFUN(CYG_AC_PATH_TIXCONFIG, [
+#
+# Ok, lets find the tix configuration
+# First, look for one uninstalled.  
+# the alternative search directory is invoked by --with-tixconfig
+#
+
+if test x"${no_tix}" = x ; then
+  # we reset no_tix in case something fails here
+  no_tix=true
+  AC_ARG_WITH(tixconfig, [  --with-tixconfig           directory containing tix configuration (tixConfig.sh)],
+         with_tixconfig=${withval})
+  AC_MSG_CHECKING([for Tix configuration])
+  AC_CACHE_VAL(ac_cv_c_tixconfig,[
+
+  # First check to see if --with-tixconfig was specified.
+  if test x"${with_tixconfig}" != x ; then
+    if test -f "${with_tixconfig}/tixConfig.sh" ; then
+      ac_cv_c_tixconfig=`(cd ${with_tixconfig}; pwd)`
+    else
+      AC_MSG_ERROR([${with_tixconfig} directory doesn't contain tixConfig.sh])
+    fi
+  fi
+
+  # then check for a private Tix library
+  if test x"${ac_cv_c_tixconfig}" = x ; then
+    for i in \
+               ../tix \
+               `ls -dr ../tix[[4]]* 2>/dev/null` \
+               ../../tix \
+               `ls -dr ../../tix[[4]]* 2>/dev/null` \
+               ../../../tix \
+               `ls -dr ../../../tix[[4]]* 2>/dev/null` ; do
+      if test -f "$i/tixConfig.sh" ; then
+        ac_cv_c_tixconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  # check in a few common install locations
+  if test x"${ac_cv_c_tixconfig}" = x ; then
+    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+      if test -f "$i/tixConfig.sh" ; then
+        ac_cv_c_tkconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  # check in a few other private locations
+  if test x"${ac_cv_c_tixconfig}" = x ; then
+    for i in \
+               ${srcdir}/../tix \
+               `ls -dr ${srcdir}/../tix[[4-9]]* 2>/dev/null` ; do
+      if test -f "$i/tixConfig.sh" ; then
+        ac_cv_c_tixconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  ])
+  if test x"${ac_cv_c_tixconfig}" = x ; then
+    TIXCONFIG="# no Tix configs found"
+    AC_MSG_WARN(Can't find Tix configuration definitions)
+  else
+    no_tix=
+    TIXCONFIG=${ac_cv_c_tixconfig}/tixConfig.sh
+    AC_MSG_RESULT(found $TIXCONFIG)
+  fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_TIXCONFIG (because this can also be cached).
+AC_DEFUN(CYG_AC_LOAD_TIXCONFIG, [
+    if test -f "$TIXCONFIG" ; then
+      . $TIXCONFIG
+    fi
+
+    AC_SUBST(TIX_BUILD_LIB_SPEC)
+    AC_SUBST(TIX_LIB_FULL_PATH)
+])
+
+AC_DEFUN(CYG_AC_PATH_ITCLCONFIG, [
+#
+# Ok, lets find the itcl configuration
+# First, look for one uninstalled.  
+# the alternative search directory is invoked by --with-itclconfig
+#
+
+if test x"${no_itcl}" = x ; then
+  # we reset no_itcl in case something fails here
+  no_itcl=true
+  AC_ARG_WITH(itclconfig, [  --with-itclconfig           directory containing itcl configuration (itclConfig.sh)],
+         with_itclconfig=${withval})
+  AC_MSG_CHECKING([for Itcl configuration])
+  AC_CACHE_VAL(ac_cv_c_itclconfig,[
+
+  # First check to see if --with-itclconfig was specified.
+  if test x"${with_itclconfig}" != x ; then
+    if test -f "${with_itclconfig}/itclConfig.sh" ; then
+      ac_cv_c_itclconfig=`(cd ${with_itclconfig}; pwd)`
+    else
+      AC_MSG_ERROR([${with_itclconfig} directory doesn't contain itclConfig.sh])
+    fi
+  fi
+
+  # then check for a private itcl library
+  if test x"${ac_cv_c_itclconfig}" = x ; then
+    for i in \
+               ../itcl/itcl \
+               `ls -dr ../itcl/itcl[[3]]* 2>/dev/null` \
+               ../../itcl/itcl \
+               `ls -dr ../../itcl/itcl[[3]]* 2>/dev/null` \
+               ../../../itcl/itcl \
+               `ls -dr ../../../itcl/itcl[[3]]* 2>/dev/null` ; do
+      if test -f "$i/itclConfig.sh" ; then
+        ac_cv_c_itclconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  # check in a few common install locations
+  if test x"${ac_cv_c_itclconfig}" = x ; then
+    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+      if test -f "$i/itclConfig.sh" ; then
+        ac_cv_c_itclconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  # check in a few other private locations
+  if test x"${ac_cv_c_itclconfig}" = x ; then
+    for i in \
+               ${srcdir}/../itcl/itcl \
+               `ls -dr ${srcdir}/../itcl/itcl[[3]]* 2>/dev/null` ; do
+      if test -f "$i/itcl/itclConfig.sh" ; then
+        ac_cv_c_itclconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  ])
+  if test x"${ac_cv_c_itclconfig}" = x ; then
+    ITCLCONFIG="# no itcl configs found"
+    AC_MSG_WARN(Can't find itcl configuration definitions)
+  else
+    no_itcl=
+    ITCLCONFIG=${ac_cv_c_itclconfig}/itclConfig.sh
+    AC_MSG_RESULT(found $ITCLCONFIG)
+  fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_ITCLCONFIG (because this can also be cached).
+AC_DEFUN(CYG_AC_LOAD_ITCLCONFIG, [
+    if test -f "$ITCLCONFIG" ; then
+      . $ITCLCONFIG
+    fi
+
+    AC_SUBST(ITCL_BUILD_LIB_SPEC)
+    AC_SUBST(ITCL_SH)
+    AC_SUBST(ITCL_LIB_FILE)
+    AC_SUBST(ITCL_LIB_FULL_PATH)
+
+])
+
+
+AC_DEFUN(CYG_AC_PATH_ITKCONFIG, [
+#
+# Ok, lets find the itk configuration
+# First, look for one uninstalled.  
+# the alternative search directory is invoked by --with-itkconfig
+#
+
+if test x"${no_itk}" = x ; then
+  # we reset no_itk in case something fails here
+  no_itk=true
+  AC_ARG_WITH(itkconfig, [  --with-itkconfig           directory containing itk configuration (itkConfig.sh)],
+         with_itkconfig=${withval})
+  AC_MSG_CHECKING([for Itk configuration])
+  AC_CACHE_VAL(ac_cv_c_itkconfig,[
+
+  # First check to see if --with-itkconfig was specified.
+  if test x"${with_itkconfig}" != x ; then
+    if test -f "${with_itkconfig}/itkConfig.sh" ; then
+      ac_cv_c_itkconfig=`(cd ${with_itkconfig}; pwd)`
+    else
+      AC_MSG_ERROR([${with_itkconfig} directory doesn't contain itkConfig.sh])
+    fi
+  fi
+
+  # then check for a private itk library
+  if test x"${ac_cv_c_itkconfig}" = x ; then
+    for i in \
+               ../itcl/itk \
+               `ls -dr ../itcl/itk[[3]]* 2>/dev/null` \
+               ../../itcl/itk \
+               `ls -dr ../../itcl/itk[[3]]* 2>/dev/null` \
+               ../../../itcl/itk \
+               `ls -dr ../../../itcl/itk[[3]]* 2>/dev/null` ; do
+      if test -f "$i/itkConfig.sh" ; then
+        ac_cv_c_itkconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  # check in a few common install locations
+  if test x"${ac_cv_c_itkconfig}" = x ; then
+    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+      if test -f "$i/itcl/itkConfig.sh" ; then
+        ac_cv_c_itkconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  # check in a few other private locations
+  if test x"${ac_cv_c_itkconfig}" = x ; then
+    for i in \
+               ${srcdir}/../itcl/itk \
+               `ls -dr ${srcdir}/../itcl/itk[[3]]* 2>/dev/null` ; do
+      if test -f "$i/itkConfig.sh" ; then
+        ac_cv_c_itkconfig=`(cd $i; pwd)`
+       break
+      fi
+    done
+  fi
+  ])
+  if test x"${ac_cv_c_itkconfig}" = x ; then
+    ITCLCONFIG="# no itk configs found"
+    AC_MSG_WARN(Can't find itk configuration definitions)
+  else
+    no_itk=
+    ITKCONFIG=${ac_cv_c_itkconfig}/itkConfig.sh
+    AC_MSG_RESULT(found $ITKCONFIG)
+  fi
+fi
+
+])
+
+# Defined as a separate macro so we don't have to cache the values
+# from PATH_ITKCONFIG (because this can also be cached).
+AC_DEFUN(CYG_AC_LOAD_ITKCONFIG, [
+    if test -f "$ITKCONFIG" ; then
+      . $ITKCONFIG
+    fi
+
+    AC_SUBST(ITK_BUILD_LIB_SPEC)
+    AC_SUBST(ITK_LIB_FILE)
+    AC_SUBST(ITK_LIB_FULL_PATH)
+])
+
+
+dnl ====================================================================
+dnl Ok, lets find the libgui source trees so we can use the headers
+dnl the alternative search directory is involked by --with-libguiinclude
+AC_DEFUN(CYG_AC_PATH_LIBGUI, [
+    CYG_AC_PATH_LIBGUIH
+    CYG_AC_PATH_LIBGUILIB
+])
+AC_DEFUN(CYG_AC_PATH_LIBGUIH, [
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../..../../../../../../../../../../.."
+no_libgui=true
+AC_MSG_CHECKING(for Libgui headers in the source tree)
+AC_ARG_WITH(libguiinclude, [  --with-libguiinclude       directory where libgui headers are], with_libguiinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_libguih,[
+dnl first check to see if --with-libguiinclude was specified
+if test x"${with_libguiinclude}" != x ; then
+  if test -f ${with_libguiinclude}/guitcl.h ; then
+    ac_cv_c_libguih=`(cd ${with_libguiinclude}; pwd)`
+  elif test -f ${with_libguiinclude}/src/guitcl.h ; then
+    ac_cv_c_libguih=`(cd ${with_libguiinclude}/src; pwd)`
+  else
+    AC_MSG_ERROR([${with_libguiinclude} directory doesn't contain headers])
+  fi
+fi
+
+dnl next check if it came with Libgui configuration file
+if test x"${ac_cv_c_libguiconfig}" != x ; then
+  for i in $dirlist; do
+    if test -f $ac_cv_c_libguiconfig/$i/src/guitcl.h ; then
+      ac_cv_c_libguih=`(cd $ac_cv_c_libguiconfig/$i/src; pwd)`
+      break
+    fi
+  done
+fi
+
+dnl next check in private source directory
+dnl since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_libguih}" = x ; then
+    dnl find the top level Libgui source directory
+    for i in $dirlist; do
+        if test -n "`ls -dr $srcdir/$i/libgui* 2>/dev/null`" ; then
+           libguipath=$srcdir/$i
+           break
+       fi
+    done
+
+    dnl find the exact Libgui source dir. We do it this way, cause there
+    dnl might be multiple version of Libgui, and we want the most recent one.
+    for i in `ls -dr $libguipath/libgui* 2>/dev/null ` ; do
+        if test -f $i/src/guitcl.h ; then
+          ac_cv_c_libguih=`(cd $i/src; pwd)`
+          break
+        fi
+    done
+fi
+
+dnl see if one is installed
+if test x"${ac_cv_c_libguih}" = x ; then
+   AC_MSG_RESULT(none)
+   AC_CHECK_HEADER(guitcl.h, ac_cv_c_libguih=installed, ac_cv_c_libguih="")
+fi
+])
+LIBGUIHDIR=""
+if test x"${ac_cv_c_libguih}" = x ; then
+    AC_MSG_WARN([Can't find any Libgui headers])
+fi
+if test x"${ac_cv_c_libguih}" != x ; then
+    no_libgui=""
+    if test x"${ac_cv_c_libguih}" != x"installed" ; then
+        LIBGUIHDIR="-I${ac_cv_c_libguih}"
+    fi
+fi
+AC_MSG_RESULT(${ac_cv_c_libguih})
+AC_SUBST(LIBGUIHDIR)
+])
+
+dnl ====================================================================
+dnl find the GUI library
+AC_DEFUN(CYG_AC_PATH_LIBGUILIB, [
+AC_MSG_CHECKING(for GUI library  in the build tree)
+dirlist=".. ../../ ../../../ ../../../../ ../../../../../ ../../../../../../ ../../../../../../.. ../../../../../../../.. ../../../../../../../../.. ../../../../../../../../../.."
+dnl look for the library
+AC_MSG_CHECKING(for GUI library)
+AC_CACHE_VAL(ac_cv_c_libguilib,[
+if test x"${ac_cv_c_libguilib}" = x ; then
+    for i in $dirlist; do
+      if test -f "$i/libgui/src/Makefile" ; then
+        ac_cv_c_libguilib=`(cd $i/libgui/src; pwd)`
+        break
+      fi
+    done
+fi
+]) 
+if test x"${ac_cv_c_libguilib}" != x ; then
+     GUILIB="${GUILIB} -L${ac_cv_c_libguilib}"
+     LIBGUILIB="-lgui"
+     AC_MSG_RESULT(${ac_cv_c_libguilib})
+else
+     AC_MSG_RESULT(none)
+fi
+
+AC_SUBST(GUILIB)
+AC_SUBST(LIBGUILIB)
+])
diff --git a/config/mh-a68bsd b/config/mh-a68bsd
new file mode 100644 (file)
index 0000000..c991289
--- /dev/null
@@ -0,0 +1,12 @@
+RANLIB=true
+
+#None of the Apollo compilers can compile gas or binutils.  The preprocessor
+# chokes on bfd, the compiler won't let you assign integers to enums, and
+# other problems.  Defining CC to gcc is a questionable way to say "don't use
+# the apollo compiler" (the preferred version of GCC could be called cc,
+# or whatever), but I'm not sure leaving CC as cc is any better...
+
+#CC=cc -A ansi -A runtype,any -A systype,any -U__STDC__ -DNO_STDARG
+CC=gcc
+
+BISON=yacc
diff --git a/config/mh-aix386 b/config/mh-aix386
new file mode 100644 (file)
index 0000000..4accd1c
--- /dev/null
@@ -0,0 +1 @@
+RANLIB = @:
diff --git a/config/mh-aix43 b/config/mh-aix43
new file mode 100644 (file)
index 0000000..9eb750c
--- /dev/null
@@ -0,0 +1,4 @@
+# AIX 4.3 and above requires -X32_64 flag to all ar and nm commands
+# to handle both 32-bit and 64-bit objects.
+AR_FOR_TARGET=ar -X32_64
+NM_FOR_TARGET=nm -X32_64
diff --git a/config/mh-apollo68 b/config/mh-apollo68
new file mode 100644 (file)
index 0000000..4497ed9
--- /dev/null
@@ -0,0 +1,3 @@
+HDEFINES = -DUSG
+RANLIB=true
+CC= cc -A ansi -A runtype,any -A systype,any -U__STDC__ -DUSG
diff --git a/config/mh-armpic b/config/mh-armpic
new file mode 100644 (file)
index 0000000..35cf2c8
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG=-fPIC
diff --git a/config/mh-cxux b/config/mh-cxux
new file mode 100644 (file)
index 0000000..54b2a16
--- /dev/null
@@ -0,0 +1,14 @@
+# Configuration for Harris CX/UX 7 (and maybe 6), based on sysv4 configuration.
+
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV -DSVR4
+RANLIB = true
+
+# C++ debugging is not yet supported under SVR4 (DWARF)
+CXXFLAGS=-O
+
+# The l flag generates a warning from the SVR4 archiver, remove it.
+AR_FLAGS = cq
+
+# Under CX/UX, we want to tell the compiler to use ANSI mode.
+CC=cc -Xa
diff --git a/config/mh-cygwin b/config/mh-cygwin
new file mode 100644 (file)
index 0000000..241027f
--- /dev/null
@@ -0,0 +1,6 @@
+EXTRA_TARGET_HOST_ALL_MODULES=all-libtermcap
+EXTRA_TARGET_HOST_INSTALL_MODULES=install-libtermcap
+
+all-gdb: all-libtermcap
+
+install-gdb: all-libtermcap
diff --git a/config/mh-decstation b/config/mh-decstation
new file mode 100644 (file)
index 0000000..3720192
--- /dev/null
@@ -0,0 +1,5 @@
+CC = cc -Wf,-XNg1000
+
+# for X11, since the native DECwindows include files are really broken when
+# it comes to function prototypes.  
+X11_EXTRA_CFLAGS = "-DNeedFunctionPrototypes=0"
diff --git a/config/mh-delta88 b/config/mh-delta88
new file mode 100644 (file)
index 0000000..bc9c453
--- /dev/null
@@ -0,0 +1,4 @@
+RANLIB = true
+
+
+
diff --git a/config/mh-dgux b/config/mh-dgux
new file mode 100644 (file)
index 0000000..e7d85d6
--- /dev/null
@@ -0,0 +1,4 @@
+HDEFINES=-DHOST_SYS=DGUX_SYS
+CC=gcc -Wall -ansi -D__using_DGUX
+RANLIB=true
+
diff --git a/config/mh-dgux386 b/config/mh-dgux386
new file mode 100644 (file)
index 0000000..15885c3
--- /dev/null
@@ -0,0 +1,22 @@
+# from mh-dgux
+HDEFINES=-DHOST_SYS=DGUX_SYS
+CC=gcc -Wall -ansi -D__using_DGUX
+RANLIB = true
+
+# from mh-sysv4
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV -DSVR4
+RANLIB = true
+
+# C++ debugging is not yet supported under SVR4 (DWARF)
+CXXFLAGS=-O
+
+# The l flag generates a warning from the SVR4 archiver, remove it.
+AR_FLAGS = cr
+
+X11_EXTRA_LIBS = -lnsl
+
+# from angela
+# no debugging due to broken compiler, use BSD style timeofday
+CFLAGS=-O -D_BSD_TIMEOFDAY_FLAVOR
+
diff --git a/config/mh-djgpp b/config/mh-djgpp
new file mode 100644 (file)
index 0000000..f12007b
--- /dev/null
@@ -0,0 +1,4 @@
+# We don't want to use debugging information on DOS.  Unfortunately,
+# this requires that we set CFLAGS.
+# This used to set -fno-omit-frame-pointer.
+CFLAGS=-O2
diff --git a/config/mh-elfalphapic b/config/mh-elfalphapic
new file mode 100644 (file)
index 0000000..35cf2c8
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG=-fPIC
diff --git a/config/mh-hp300 b/config/mh-hp300
new file mode 100644 (file)
index 0000000..761724d
--- /dev/null
@@ -0,0 +1,13 @@
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV
+# Avoid "too much defining" errors from HPUX compiler.
+CC = cc -Wp,-H256000
+# If "ar" in $PATH is GNU ar, the symbol table may need rebuilding.
+# If it's HP/UX ar, this should be harmless.
+RANLIB = ar ts
+
+# Native cc can't bootstrap gcc with -g.  Defining CFLAGS here loses (a)
+# for non-gcc directories, (b) if we are compiling with gcc, not
+# native cc.  Neither (a) nor (b) has a trivial fix though.
+
+CFLAGS =
diff --git a/config/mh-hpux b/config/mh-hpux
new file mode 100644 (file)
index 0000000..4d71c9d
--- /dev/null
@@ -0,0 +1,4 @@
+# Define SYSV as -DSYSV if you are using a System V operating system.
+CC = cc -Wp,-H256000
+SYSV = -DSYSV
+RANLIB = true
diff --git a/config/mh-hpux8 b/config/mh-hpux8
new file mode 100644 (file)
index 0000000..4d71c9d
--- /dev/null
@@ -0,0 +1,4 @@
+# Define SYSV as -DSYSV if you are using a System V operating system.
+CC = cc -Wp,-H256000
+SYSV = -DSYSV
+RANLIB = true
diff --git a/config/mh-interix b/config/mh-interix
new file mode 100644 (file)
index 0000000..19b8ecf
--- /dev/null
@@ -0,0 +1,14 @@
+# The shell may not be in /bin. 
+SHELL = sh
+RANLIB = true
+
+# We don't want debugging info in Interix-hosted toolchains.
+# Accomplish this by overriding CFLAGS. This is also a workaround
+# for LD crash when building shared libstdc++.
+CFLAGS=-O2
+CXXFLAGS=-O2
+
+# We also need to override LIBGCC2_DEBUG_CFLAGS so libgcc2 will be
+# built without debugging information
+
+LIBGCC2_DEBUG_CFLAGS=
diff --git a/config/mh-irix4 b/config/mh-irix4
new file mode 100644 (file)
index 0000000..6872145
--- /dev/null
@@ -0,0 +1,7 @@
+# Makefile changes for SGI's running IRIX-4.x.
+# Tell compiler to use K&R C.  We can't compile under the SGI Ansi
+# environment.  Also bump switch table size so that cp-parse will
+# compile.  Bump string length limit so linker builds.
+
+CC = cc -cckr -Wf,-XNg1500 -Wf,-XNk1000 -Wf,-XNh2000 -Wf,-XNl8192
+SYSV = -DSYSV
diff --git a/config/mh-irix5 b/config/mh-irix5
new file mode 100644 (file)
index 0000000..8bd7c99
--- /dev/null
@@ -0,0 +1,3 @@
+# Makefile changes for SGI's running IRIX-5.x.
+SYSV = -DSYSV
+RANLIB = true
diff --git a/config/mh-irix6 b/config/mh-irix6
new file mode 100644 (file)
index 0000000..6d25c16
--- /dev/null
@@ -0,0 +1,7 @@
+# Makefile changes for SGI's running IRIX-6.x.
+SYSV = -DSYSV
+RANLIB = true
+# Specify the ABI, to ensure that all Irix 6 systems will behave the same.
+# Also, using -32 avoids bugs that exist in the n32/n64 support in some
+# versions of the SGI compiler.
+CC = cc -32
diff --git a/config/mh-lynxos b/config/mh-lynxos
new file mode 100644 (file)
index 0000000..9afcb79
--- /dev/null
@@ -0,0 +1,2 @@
+# /bin/cc is less than useful for our purposes.  Always use GCC
+CC = /bin/gcc
diff --git a/config/mh-lynxrs6k b/config/mh-lynxrs6k
new file mode 100644 (file)
index 0000000..b279399
--- /dev/null
@@ -0,0 +1,8 @@
+# LynxOS running on the rs6000 doesn't have ranlib
+RANLIB = true
+
+# /bin/cc is less than useful for our purposes.  Always use GCC
+CC = /usr/cygnus/progressive/bin/gcc
+
+# /bin/sh is too buggy, so use /bin/bash instead.
+SHELL = /bin/bash
diff --git a/config/mh-m68kpic b/config/mh-m68kpic
new file mode 100644 (file)
index 0000000..92e48d9
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG=-fpic
diff --git a/config/mh-mingw32 b/config/mh-mingw32
new file mode 100644 (file)
index 0000000..8c4839d
--- /dev/null
@@ -0,0 +1,12 @@
+# We don't want debugging info in Win32-hosted toolchains.
+# Accomplish this by overriding CFLAGS.
+CFLAGS=-O2
+CXXFLAGS=-O2
+
+# We also need to override LIBGCC2_DEBUG_CFLAGS so libgcc2 will be
+# built without debugging information
+
+LIBGCC2_DEBUG_CFLAGS=
+
+# custom installation rules for mingw32 (append .exe to binaries, etc.)
+# INSTALL_DOSREL=install-dosrel
diff --git a/config/mh-ncr3000 b/config/mh-ncr3000
new file mode 100644 (file)
index 0000000..5bbd803
--- /dev/null
@@ -0,0 +1,17 @@
+# Host configuration file for an NCR 3000 (i486/SVR4) system.
+
+# The NCR 3000 ships with a MetaWare compiler installed as /bin/cc.
+# This compiler not only emits obnoxious copyright messages every time
+# you run it, but it chokes and dies on a whole bunch of GNU source
+# files.  Default to using the AT&T compiler installed in /usr/ccs/ATT/cc.
+# Unfortunately though, the AT&T compiler sometimes generates code that
+# the assembler barfs on if -g is used, so disable it by default as well.
+CC = /usr/ccs/ATT/cc
+CFLAGS =
+
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV -DSVR4
+RANLIB = true
+
+# The l flag generates a warning from the SVR4 archiver, remove it.
+AR_FLAGS = cq
diff --git a/config/mh-ncrsvr43 b/config/mh-ncrsvr43
new file mode 100644 (file)
index 0000000..43b0991
--- /dev/null
@@ -0,0 +1,9 @@
+# Host configuration file for an NCR 3000 (i486/SVR43) system.
+
+# The MetaWare compiler will generate a copyright message unless you
+# turn it off by adding the -Hnocopyr flag.
+CC = cc -Hnocopyr
+
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV -DSVR4
+RANLIB = true
diff --git a/config/mh-necv4 b/config/mh-necv4
new file mode 100644 (file)
index 0000000..e887736
--- /dev/null
@@ -0,0 +1,11 @@
+# Host Makefile fragment for NEC MIPS SVR4.
+
+# The C compiler on NEC MIPS SVR4 needs bigger tables.
+CC = cc -ZXNd=5000 -ZXNg=1000
+
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV -DSVR4
+RANLIB = true
+
+# NEC -lX11 needs some other libraries.
+X11_EXTRA_LIBS = -lsocket -lnsl
diff --git a/config/mh-papic b/config/mh-papic
new file mode 100644 (file)
index 0000000..35cf2c8
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG=-fPIC
diff --git a/config/mh-ppcpic b/config/mh-ppcpic
new file mode 100644 (file)
index 0000000..35cf2c8
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG=-fPIC
diff --git a/config/mh-riscos b/config/mh-riscos
new file mode 100644 (file)
index 0000000..e586b30
--- /dev/null
@@ -0,0 +1,15 @@
+# This is for a MIPS running RISC/os 4.52C.
+
+# This is needed for GDB, but needs to be in the top-level make because
+# if a library is compiled with the bsd headers and gets linked with the
+# sysv system libraries all hell can break loose (e.g. a jmp_buf might be
+# a different size).
+# ptrace(2) apparently has problems in the BSD environment.  No workaround is
+# known except to select the sysv environment.  Could we use /proc instead?
+# These "sysv environments" and "bsd environments" often end up being a pain.
+#
+# This is not part of CFLAGS because perhaps not all C compilers have this
+# option.
+CC= cc -systype sysv
+
+RANLIB = true
diff --git a/config/mh-sco b/config/mh-sco
new file mode 100644 (file)
index 0000000..cc337c9
--- /dev/null
@@ -0,0 +1,10 @@
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV
+RANLIB = true
+# You may need this if you don't have bison.
+# BISON = yacc -Sm10400
+# The native C compiler botches some simple uses of const.  Unfortunately,
+# it doesn't defined anything like "__sco__" for us to test for in ansidecl.h.
+CC = cc -Dconst=
+
+X11_EXTRA_LIBS = -lsocket -lm -lintl -lmalloc
diff --git a/config/mh-solaris b/config/mh-solaris
new file mode 100644 (file)
index 0000000..ddbea54
--- /dev/null
@@ -0,0 +1,6 @@
+# Makefile changes for Suns running Solaris 2
+
+SYSV = -DSYSV
+RANLIB = true
+
+X11_EXTRA_LIBS = -lnsl -lsocket
diff --git a/config/mh-sparcpic b/config/mh-sparcpic
new file mode 100644 (file)
index 0000000..f6dbc22
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG=`case "${LIBCFLAGS} ${LIBCXXFLAGS}" in *-fpic* ) echo -fpic ;; * ) echo -fPIC ;; esac`
diff --git a/config/mh-sun3 b/config/mh-sun3
new file mode 100644 (file)
index 0000000..dcd5155
--- /dev/null
@@ -0,0 +1,3 @@
+# Sun's C compiler needs the -J flag to be able to compile cp-parse.c
+# without overflowing the jump tables (-J says to use a 32 bit table)
+CC = cc -J
diff --git a/config/mh-sysv b/config/mh-sysv
new file mode 100644 (file)
index 0000000..16b1187
--- /dev/null
@@ -0,0 +1,3 @@
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV
+RANLIB = true
diff --git a/config/mh-sysv4 b/config/mh-sysv4
new file mode 100644 (file)
index 0000000..8106651
--- /dev/null
@@ -0,0 +1,11 @@
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV -DSVR4
+RANLIB = true
+
+# C++ debugging is not yet supported under SVR4 (DWARF)
+CXXFLAGS=-O
+
+# The l flag generates a warning from the SVR4 archiver, remove it.
+AR_FLAGS = cr
+
+X11_EXTRA_LIBS = -lnsl
diff --git a/config/mh-sysv5 b/config/mh-sysv5
new file mode 100644 (file)
index 0000000..1fa38e5
--- /dev/null
@@ -0,0 +1,8 @@
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV -DSVR4 -DSVR5
+RANLIB = true
+
+# The l flag generates a warning from the SVR4 archiver, remove it.
+AR_FLAGS = cr
+
+X11_EXTRA_LIBS = -lnsl
diff --git a/config/mh-vaxult2 b/config/mh-vaxult2
new file mode 100644 (file)
index 0000000..3de2dc8
--- /dev/null
@@ -0,0 +1,2 @@
+# The old BSD pcc isn't up to compiling parts of gdb so use gcc
+CC = gcc
diff --git a/config/mh-x86pic b/config/mh-x86pic
new file mode 100644 (file)
index 0000000..92e48d9
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG=-fpic
diff --git a/config/mpw-mh-mpw b/config/mpw-mh-mpw
new file mode 100644 (file)
index 0000000..543ef4f
--- /dev/null
@@ -0,0 +1,157 @@
+# This is an MPW makefile fragment.
+
+# Since there are a multiplicity of Mac compilers and two different
+# processors, this file is primarily a library of options for each
+# compiler.  Somebody else (such as a configure or build script) will
+# make the actual choice.
+
+# Compiler to use for compiling.
+
+CC_MPW_C = C -d MPW_C -d ALMOST_STDC -d ANSI_PROTOTYPES -d MPW -mc68020 -model far -b -w
+
+CC_SC = SC -d ALMOST_STDC -d ANSI_PROTOTYPES -d MPW -mc68020 -model far -b -i '' -i :
+
+CC_MWC68K = MWC68K -d MPW -enum int -mpw_chars -sym on -w off -mc68020 -model far
+
+CC_PPCC = PPCC -d powerc=1 -d pascal= -d ALMOST_STDC -d ANSI_PROTOTYPES -d MPW -w
+
+CC_MRC = MrC -d powerc=1 -d pascal= -d ALMOST_STDC -d ANSI_PROTOTYPES -d MPW -i '' -i : -jm
+
+CC_SMrC = SMrC -d MPW
+
+# "-mpw_chars" is necessary because GNU sources often mix signed and
+# unsigned casually.
+# "-w off" is not a great idea, but CW7 is complaining about enum
+# assignments.
+# "-opt global,peep,l4,speed" is sometimes good, and sometimes bad.
+# We must use {CIncludes} so that MPW tools will work; {MWCIncludes}
+# defines stdout, islower, etc, in ways that are incompatible with MPW's
+# runtime.  However, this cannot be done via  -i "{CIncludes}", since
+# that does not affect how <>-type includes happen; instead, the variable
+# MWCIncludes must be set to point at {CIncludes}.
+
+CC_MWCPPC = MWCPPC -d MPW -enum int -mpw_chars -sym on -w off
+
+# Note that GCC does *not* wire in a definition of "pascal", so that
+# it can be handled in another way if desired.
+
+CC_68K_GCC = gC -Dpascal= -DANSI_PROTOTYPES -DMPW
+
+CC_PPC_GCC = gC -Dpowerc=1 -Dpascal= -DANSI_PROTOTYPES -DMPW
+
+# Nothing for the default CFLAGS.
+
+CFLAGS = 
+
+# Tool to use for making libraries/archives.
+
+AR_LIB = Lib
+
+AR_MWLINK68K = MWLink68K -xm library
+
+AR_PPCLINK = PPCLink -xm library
+
+AR_MWLINKPPC = MWLinkPPC -xm library
+
+AR_AR = ar
+
+AR_FLAGS = -o
+
+RANLIB_NULL = null-command
+
+RANLIB_RANLIB = ranlib
+
+# Compiler and/or linker to use for linking.
+
+CC_LD_LINK = Link -w -d -model far {CC_LD_TOOL_FLAGS}
+
+CC_LD_MWLINK68K = MWLink68K -w {CC_LD_TOOL_FLAGS} -sym on -model far
+
+CC_LD_PPCLINK = PPCLink -main __start -outputformat xcoff
+
+CC_LD_MWLINKPPC = MWLinkPPC -w {CC_LD_TOOL_FLAGS} -sym on
+
+CC_LD_GLD = gC
+
+# Extension for linker output.
+
+PROG_EXT_68K =
+
+PROG_EXT_XCOFF = .xcoff
+
+# Nothing for the default LDFLAGS.
+
+LDFLAGS = -w
+
+CC_LD_TOOL_FLAGS = -c 'MPS ' -t MPST
+
+# Libraries to link against.
+
+# It would appear that the math libraries are not
+# needed except to provide a definition for scalb,
+# which is called from ldexp, which is referenced
+# in the m68k opcodes library.
+
+EXTRALIBS_C = \Option-d
+       "{CLibraries}"StdClib.o \Option-d
+       "{CLibraries}"Math.o \Option-d
+       "{CLibraries}"CSANELib.o \Option-d
+       "{Libraries}"Stubs.o \Option-d
+       "{Libraries}"Runtime.o \Option-d
+       "{Libraries}"Interface.o \Option-d
+       "{Libraries}"ToolLibs.o
+
+EXTRALIBS_MWC68K = \Option-d
+       "{CLibraries}"StdClib.o \Option-d
+       "{CLibraries}"Math.o \Option-d
+       "{CLibraries}"CSANELib.o \Option-d
+       "{Libraries}"Stubs.o \Option-d
+       "{Libraries}"Runtime.o \Option-d
+       "{Libraries}"Interface.o \Option-d
+       "{Libraries}"ToolLibs.o \Option-d
+       "{MW68KLibraries}MPW ANSI (4i) C.68K.Lib"
+
+EXTRALIBS_PPC_XCOFF = \Option-d
+       "{PPCLibraries}"StdCRuntime.o \Option-d
+       "{PPCLibraries}"InterfaceLib.xcoff \Option-d
+       "{PPCLibraries}"MathLib.xcoff \Option-d
+       "{PPCLibraries}"StdCLib.xcoff \Option-d
+       "{PPCLibraries}"PPCToolLibs.o \Option-d
+       "{PPCLibraries}"PPCCRuntime.o \Option-d
+       "{GCCPPCLibraries}"libgcc.xcoff
+
+EXTRALIBS_PPC = \Option-d
+       "{PPCLibraries}"StdCRuntime.o \Option-d
+       "{SharedLibraries}"InterfaceLib \Option-d
+       "{SharedLibraries}"MathLib \Option-d
+       "{SharedLibraries}"StdCLib \Option-d
+       "{PPCLibraries}"PPCToolLibs.o \Option-d
+       "{PPCLibraries}"PPCCRuntime.o \Option-d
+       "{GCCPPCLibraries}"libgcc.xcoff
+
+EXTRALIBS_MWCPPC = \Option-d
+       "{MWPPCLibraries}"MWStdCRuntime.Lib \Option-d
+       "{MWPPCLibraries}"InterfaceLib \Option-d
+       "{MWPPCLibraries}"StdCLib \Option-d
+       "{MWPPCLibraries}"MathLib \Option-d
+       "{MWPPCLibraries}"PPCToolLibs.o
+
+# Tool to make PEF with, if needed.
+
+MAKEPEF_NULL = null-command
+
+MAKEPEF_PPC = MakePEF
+
+MAKEPEF_FLAGS = \Option-d
+       -l InterfaceLib.xcoff=InterfaceLib \Option-d
+       -l MathLib.xcoff=MathLib \Option-d
+       -l StdCLib.xcoff=StdCLib
+
+MAKEPEF_TOOL_FLAGS = -ft MPST -fc 'MPS '
+
+# Resource compiler to use.
+
+REZ_68K = Rez
+
+REZ_PPC = Rez -d WANT_CFRG
+
diff --git a/config/mpw/ChangeLog b/config/mpw/ChangeLog
new file mode 100644 (file)
index 0000000..3cdefbf
--- /dev/null
@@ -0,0 +1,53 @@
+Tue Nov 26 12:34:12 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * g-mpw-make.sed: Fix some comments.
+
+Mon Sep 16 14:42:52 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * g-mpw-make.sed (HLDENV): Edit out all references.
+
+Thu Aug 15 19:49:23 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * true: New script, identical to mpw-true.
+       * g-mpw-make.sed: Add @DASH_C_FLAG@ and @SEGMENT_FLAG()@
+       to the editors for compile commands.
+
+Thu Aug  1 15:01:42 1996  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * mpw-true, mpw-touch, null-command: New scripts.
+       * README: Describe usage in more detail.
+
+Tue Dec 12 14:51:51 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * g-mpw-make.sed: Don't edit out "version=" occurrences.
+
+Fri Dec  1 11:46:18 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * g-mpw-make.sed (bindir, libdir): Edit the positions of
+       pathname separators to work with other pathnames better.
+
+Tue Nov  7 15:08:07 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * g-mpw-make.sed: Add comment about Duplicate vs Catenate,
+       add additional pattern for editing link-compile commands.
+
+Tue Oct 24 14:28:51 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * g-mpw-make.sed: Add handling for *.tab.[hc] files.
+       (CHILL_FOR_TARGET, CHILL_LIB): Edit out tricky definitions
+       of these.
+
+Thu Sep 28 21:05:10 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * g-mpw-make.sed: New file, generic sed commands to translate
+       Unix makefiles into MPW makefile syntax.
+
+Fri Mar 17 11:51:20 1995  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * README: Clarify instructions.
+       * fi: Remove.
+
+Wed Dec 21 15:45:53 1994  Stan Shebs  <shebs@andros.cygnus.com>
+
+       * MoveIfChange, README, fi, forward-include, open-brace,
+        tr-7to8-src: New files.
diff --git a/config/mpw/MoveIfChange b/config/mpw/MoveIfChange
new file mode 100644 (file)
index 0000000..0dbc125
--- /dev/null
@@ -0,0 +1,19 @@
+# Rename a file only if it is different from a previously existing
+# file of the same name.  This is useful for keeping make from doing
+# too much work if the contents of a file haven't changed.
+
+# This is an MPW translation of the standard GNU sh script move-if-change.
+
+Set exit 0
+
+If "`exists -f "{2}"`"
+  Compare "{1}" "{2}" >dev:null
+  If {status} != 0
+    Rename -y "{1}" "{2}"
+  Else
+    Echo "{2}" is unchanged
+    Delete -i -y "{1}"
+  End
+Else
+  Rename -y "{1}" "{2}"
+End
diff --git a/config/mpw/README b/config/mpw/README
new file mode 100644 (file)
index 0000000..554700a
--- /dev/null
@@ -0,0 +1,23 @@
+This directory contains MPW scripts and related files that are needed to
+build Cygnus GNU tools for MPW.  The scripts should be somewhere on the
+command path; our usual practice has been to have a separate directory
+for the scripts, and put the tools (byacc, flex, and sed at least) there
+also; then it's easier to drag the support bits around as a group, or to
+upgrade MPW versions.  The complete package of scripts and tool binaries
+is usually available as pub/mac/buildtools.cpt.hqx on ftp.cygnus.com.
+
+"tr-7to8-src" is actually the source to an MPW script that transforms
+sequences like "\Option-d" into the actual 8-bit chars that MPW needs.
+It's only the source because it can't itself include any 8-bit chars.
+It *can* be processed into a genuine "tr-7to8" by using itself:
+
+       tr-7to8 tr-7to8-src | sed -e 's/Src//' >new-tr-7to8
+
+Use this to verify:
+
+       compare tr-7to8 new-tr-7to8
+
+If you don't have a working tr-7to8, then you will have to manually
+replace all occurrences of "\Option-d" with real Option-d (which looks
+like a delta), then do similarly with all the other "\Option-..."
+strings, and then change "\SrcOption-d" into the string "\Option-d".
diff --git a/config/mpw/forward-include b/config/mpw/forward-include
new file mode 100644 (file)
index 0000000..ddd6bd7
--- /dev/null
@@ -0,0 +1,3 @@
+Echo '#include' Â¶""{1}"¶" >"{2}".tem
+MoveIfChange "{2}".tem "{2}"
+
diff --git a/config/mpw/g-mpw-make.sed b/config/mpw/g-mpw-make.sed
new file mode 100644 (file)
index 0000000..e7d3c77
--- /dev/null
@@ -0,0 +1,293 @@
+# Sed commands to translate Unix makefiles into MPW makefiles.
+# These are nominally generic, but work best on the makefiles used
+# for GNU programs.
+
+# Whack out any commented-out lines that are probably commands;
+# they can only cause trouble later on.
+/^#    /d
+
+# Change dependency char.
+/:$/s/:/ \\Option-f/g
+/^[^   :#][^:]*:/s/\([         ]*\):\([        ]*\)/ \\Option-f /g
+
+# Change syntax of Makefile vars.
+/\$/s/\${\([a-zA-Z0-9_-]*\)}/{\1}/g
+/\$/s/\$(\([a-zA-Z0-9_-]*\))/{\1}/g
+/ $@/s/ $@/ {Targ}/
+
+# Double-$ are literals to Unix but not to MPW make.
+/\$\$/s/\$\$/$/g
+
+# Change pathname syntax.
+/\//s,\.\./\/\.\./,:::,g
+/\//s,\.\./,::,g
+/\.\//s,\./,:,g
+/\//s,/,:,g
+# Undo excess changes.
+/and/s,and:or$,and/or,
+/and/s,and:or ,and/or ,
+/want/s,want:need,want/need,
+# Fixing up sed commands.
+/-e/s_":\([^:]*\):d"_"/\1/d"_g
+/-e/s_":\([^:]*\):,:\([^:]*\):d"_"/\1/,/\2/d"_g
+
+/=/s/ = \.$/ = :/
+
+# Make these go away so that later edits not confused.
+/HLDENV/s/{HLDENV}//
+
+# Comment out any explicit srcdir setting.
+/srcdir/s/^srcdir/# srcdir/
+
+/BASEDIR/s/^BASEDIR =.*$/BASEDIR = "{srcroot}"/
+/{BASEDIR}:/s/{BASEDIR}:/{BASEDIR}/g
+/{srcdir}:/s/{srcdir}:/"{srcdir}"/g
+/"{srcdir}":/s/"{srcdir}":/"{srcdir}"/g
+
+# Tweak some conventions that are backwards for the Mac.
+/bindir/s/{exec_prefix}:bin/{exec_prefix}bin:/
+/libdir/s/{exec_prefix}:lib/{exec_prefix}lib:/
+
+# Comment out settings of anything set by mpw host config.
+/CC/s/^CC *=/#CC =/
+/CFLAGS/s/^CFLAGS *=/#CFLAGS =/
+/AR/s/^AR *=/#AR =/
+/AR_FLAGS/s/^AR_FLAGS *=/#AR_FLAGS =/
+/RANLIB/s/^RANLIB *=/#RANLIB =/
+/CC_LD/s/^CC_LD *=/#CC_LD =/
+/LDFLAGS/s/^LDFLAGS *=/#LDFLAGS =/
+
+# Change -I usages.
+/-I/s/-I\./-i :/g
+/-I/s/-I::bfd/-i ::bfd:/g
+/-I/s/-I::include/-i ::include:/g
+/-I/s/-I/-i /g
+
+# Change -D usage.
+/-D/s/\([ =]\)-D\([^ ]*\)/\1-d \2/g
+
+# Change continuation char.
+/\\$/s/\\$/\\Option-d/
+
+# Change wildcard char.
+/\*/s/\*/\\Option-x/g
+
+# Change path of various types of source files.  This rule does not allow
+# for file names with multiple dots in the name.
+/\.[chly]/s/\([        ><=]\)\([-a-zA-Z0-9_${}:"]*\)\.\([chly]\)/\1"{s}"\2.\3/g
+/\.[chly]/s/^\([-a-zA-Z0-9_${}:"]*\)\.\([chly]\)/"{s}"\1.\2/
+# Allow files named *.tab.[ch] as a special case.
+/\.tab\.[ch]/s/\([     ><=]\)\([-a-zA-Z0-9_${}:"]*\.tab\)\.\([ch]\)/\1"{s}"\2.\3/g
+/\.tab\.[ch]/s/^\([-a-zA-Z0-9_${}:"]*\.tab\)\.\([ch]\)/"{s}"\1.\2/
+# Fix some overenthusiasms.
+/{s}/s/"{s}""{srcdir}"/"{srcdir}"/g
+/{s}/s/"{s}"{\([a-zA-Z0-9_]*\)dir}/"{\1dir}"/g
+/{s}/s/"{s}"{\([a-zA-Z0-9_]*\)DIR}/"{\1DIR}"/g
+/{s}/s/"{s}""{\([a-zA-Z0-9_]*\)dir}"/"{\1dir}"/g
+/{s}/s/"{s}""{\([a-zA-Z0-9_]*\)DIR}"/"{\1DIR}"/g
+/{s}/s/"{s}":/:/g
+/{s}/s/^"{s}"//g
+/{s}/s/"{s}""{s}"/"{s}"/g
+/{s}/s/"{s}""{srcdir}"/"{s}"/g
+/{s}/s/"{srcdir}""{s}"/"{s}"/g
+
+# The .def files are also typically source files.
+/\.def/s/\([   ><]\)\([-a-zA-Z0-9_${}:"]*\)\.def/\1"{s}"\2.def/g
+/\.def/s/^\([-a-zA-Z0-9_${}:"]*\)\.def/"{s}"\1.def/g
+
+# Change extension and path of objects.
+/\.o/s/\([     =]\)\([-a-zA-Z0-9_${}:"]*\)\.o/\1"{o}"\2.c.o/g
+/\.o/s/^\([-a-zA-Z0-9_${}:"]*\)\.o/"{o}"\1.c.o/
+# Allow *.tab.o files as a special case of a 2-dot-name file.
+/\.o/s/\([     =]\)\([-a-zA-Z0-9_${}:"]*\)\.tab\.o/\1"{o}"\2.tab.c.o/g
+/\.o/s/^\([-a-zA-Z0-9_${}:"]*\)\.tab\.o/"{o}"\1.tab.c.o/
+# Clean up.
+/"{o}"/s/"{o}""{o}"/"{o}"/g
+/"{o}"/s/^"{o}"\([a-zA-Z0-9_]*\)=/\1=/
+
+# Change extension of libs.
+/\.a/s/lib\([a-z]*\)\.a/lib\1.o/g
+
+# Remove non-fail option.
+/-/s/^\([      ]*\)-/\1/
+# Fix overeagernesses - assumes no one-letter commands.
+/^[    ]*[a-z] /s/^\([         ]*\)\([a-z]\) /\1-\2 /
+
+# Remove non-echo option. (watch out for autoconf things)
+/@/s/^\([      ]*\)@/\1/
+
+# Change cp to Duplicate.
+# Catenate is perhaps more accurate, but the pattern would have to
+# identify the output file and add a '>' redirection into it.
+/cp/s/^\([     ]*\)cp /\1Duplicate -d -y /
+# Change mv to Rename.
+/mv/s/^\([     ]*\)mv /\1Rename -y /
+/Rename/s/^\([         ]*\)Rename -y -f/\1Rename -y/
+# Change rm to Delete.
+/rm -rf/s/^\([         ]*\)rm -rf /\1Delete -i -y /
+/rm -f/s/^\([  ]*\)rm -f /\1Delete -i -y /
+/rm/s/^\([     ]*\)rm /\1Delete -i -y /
+# Note that we don't mess with ln - directory-specific scripts
+# must decide what to do with symlinks.
+# Change cat to Catenate.
+/cat/s/^\([    ]*\)cat /\1Catenate /
+# Change touch to mpw-touch.
+/touch/s/^\([  ]*\)touch /\1mpw-touch /
+# Change mkdir to NewFolder.
+/mkdir/s/^\([  ]*\)mkdir /\1NewFolder /
+# Change var setting to Set.
+/=/s/^\([      ]*\)\([-a-zA-Z0-9_]*\)=\([^;]*\); \\Option-d/\1Set \2 \3/
+
+# Change tests.
+/if /s/if \[ *-f \([^ ]*\) ] *; *\\Option-d/If "`Exists "\1"`" != ""/
+/if /s/if \[ *-f \([^ ]*\) ] *; *then *\\Option-d/If "`Exists "\1"`" != ""/
+/if /s/if \[ ! *-f \([^ ]*\) ] *; *\\Option-d/If "`Exists "\1"`" == ""/
+/if /s/if \[ ! *-f \([^ ]*\) ] *; *then \\Option-d/If "`Exists "\1"`" == ""/
+
+/if /s/if \[ *-d \([^ ]*\) ] *; *\\Option-d/If "`Exists "\1"`" != ""/
+/if /s/if \[ *-d \([^ ]*\) ] *; *then *\\Option-d/If "`Exists "\1"`" != ""/
+/if /s/if \[ ! *-d \([^ ]*\) ] *; *\\Option-d/If "`Exists "\1"`" == ""/
+/if /s/if \[ ! *-d \([^ ]*\) ] *; *then *\\Option-d/If "`Exists "\1"`" == ""/
+
+/if /s/if \[ -d \([^ ]*\) ] *; then true *; else mkdir \([^ ;]*\) *; fi/If "`Exists "\1"`" != "" NewFolder \2 End If/
+
+/if /s/if \[ \([^ ]*\) = \([^ ]*\) ] *; *\\Option-d/If "\1" == "\2"/
+/if /s/if \[ \([^ ]*\) = \([^ ]*\) ] *; *then *\\Option-d/If "\1" == "\2"/
+
+/if /s/if \[ \([^ ]*\) != \([^ ]*\) ] *; *\\Option-d/If "\1" != "\2"/
+/if /s/if \[ \([^ ]*\) != \([^ ]*\) ] *; *then *\\Option-d/If "\1" != "\2"/
+
+/if /s/if \[ \([^ ]*\) -eq \([^ ]*\) ] *; *\\Option-d/If "\1" != "\2"/
+/if /s/if \[ \([^ ]*\) -eq \([^ ]*\) ] *; *then *\\Option-d/If "\1" != "\2"/
+
+/^[    ]*else true$/c\
+       Else\
+               mpw-true\
+
+
+/else/s/^\([   ]*\)else[       ]*$/\1Else/
+/else/s/^\([   ]*\)else[;      ]*\\Option-d$/\1Else/
+
+/^[    ]*else[         ]*true[         ]*$/c\
+       Else\
+               mpw-true
+
+/^[    ]*else[         ]*true[;        ]*fi$/c\
+       Else\
+               mpw-true\
+       End If
+
+/fi/s/^\([     ]*\)fi *$/\1End/
+/fi/s/^\([     ]*\)fi *; *\\Option-d/\1End/
+
+# Change looping.
+/for/s/^\([    ]*\)for \([-a-zA-Z0-9_]*\) in \([^;]*\); *do *\\Option-d/\1For \2 In \3/
+/^\([  ]*\)do *\\Option-d/d
+/done/s/^\([   ]*\)done *; *\\Option-d/\1End/
+/done/s/^\([   ]*\)done$/\1End/
+
+# Trailing semicolons and continued lines are unneeded sh syntax.
+/; \\Option-d/s/; \\Option-d//
+
+# Change move-if-change to MoveIfChange.
+/move-if-change/s/\([^         ]*\)move-if-change/MoveIfChange/g
+
+# Change $(SHELL) to the script name by itself.
+/SHELL/s/^\([  ]*\){SHELL} /\1/
+
+# Change syntax of default rule dependency.
+/^\.c\.o/s/^\.c\.o \\Option-f$/.c.o \\Option-f .c/
+
+# Change default rule's action.
+/{CC} -c/s/{CC} -c \(.*\) \$<$/{CC} @DASH_C_FLAG@ {DepDir}{Default}.c \1 @SEGMENT_FLAG({Default})@ -o {TargDir}{Default}.c.o/
+
+# This is pretty disgusting, but I can't seem to detect empty rules.
+/Option-f$/s/Option-f$/Option-f _oldest/g
+
+# Remove -c from explicit compiler calls. (but should not if GCC)
+# Handle the case of a source file that is "{xxx}"file.c.
+/ -c /s/{\([A-Z_]*\)CC}\(.*\) -c \(.*\)"\([^"]*\)"\([-a-z_]*\)\.c/{\1CC}\2 @DASH_C_FLAG@ \3"\4"\5.c -o "{o}"\5.c.o/
+# Handle the case of a source file that is "{xxx}"dir:file.c.
+/ -c /s/{\([A-Z_]*\)CC}\(.*\) -c \(.*\)"\([^"]*\)"\([-a-z_]*\):\([-a-z_]*\)\.c/{\1CC}\2 @DASH_C_FLAG@ \3"\4"\5:\6.c -o "{o}"\6.c.o/
+
+# Change linking cc to linking sequence.
+/-o/s/^\([     ]*\){CC} \(.*\){\([A-Z_]*\)CFLAGS} \(.*\){LDFLAGS} \(.*\)-o \([^ ]*\) \(.*\)$/\1{CC_LD} \2 {\3CFLAGS} \4 {LDFLAGS} \5 -o \6{PROG_EXT} \7\
+\1{MAKEPEF} \6{PROG_EXT} -o \6 {MAKEPEF_TOOL_FLAGS} {MAKEPEF_FLAGS}\
+\1{REZ} "{s}"\6.r -o \6 -append -d PROG_NAME='"'\6'"' -d VERSION_STRING='"'{version}'"'/
+/-o/s/^\([     ]*\){CC} \(.*\){\([A-Z_]*\)CFLAGS} \(.*\)-o \([^ ]*\) \(.*\){LDFLAGS} \(.*\)$/\1{CC_LD} \2 {\3CFLAGS} \4 {LDFLAGS} \6 -o \5{PROG_EXT} \7\
+\1{MAKEPEF} \5{PROG_EXT} -o \5 {MAKEPEF_TOOL_FLAGS} {MAKEPEF_FLAGS}\
+\1{REZ} "{s}"\5.r -o \5 -append -d PROG_NAME='"'\5'"' -d VERSION_STRING='"'{version}'"'/
+/-o/s/^\([     ]*\){HOST_CC} \(.*\)-o \([^ ]*\) \(.*\)$/\1{HOST_CC_LD} \2 -o \3{PROG_EXT} \4\
+\1{MAKEPEF} \3{PROG_EXT} -o \3 {MAKEPEF_TOOL_FLAGS} {MAKEPEF_FLAGS}\
+\1{REZ} "{s}"\3.r -o \3 -append -d PROG_NAME='"'\3'"' -d VERSION_STRING='"'{version}'"'/
+
+# Comment out .NOEXPORT rules.
+/\.NOEXPORT/s/^\.NOEXPORT/#\.NOEXPORT/
+# Comment out .PHONY rules.
+/\.PHONY/s/^\.PHONY/#\.PHONY/
+# Comment out .PRECIOUS rules.
+/\.PRECIOUS/s/^\.PRECIOUS/#\.PRECIOUS/
+# Comment out .SUFFIXES rules.
+/\.SUFFIXES/s/^\.SUFFIXES/#\.SUFFIXES/
+
+# Set the install program appropriately.
+/INSTALL/s/^INSTALL *= *`.*`:install.sh -c/INSTALL = Duplicate -y/
+
+# Don't try to decide whether to use the tree's own tools.
+/bison/s/`.*bison:bison.*`/bison -y/
+/byacc/s/`.*byacc:byacc.*`/byacc/
+/flex/s/`.*flex:flex.*`/flex/
+
+# Turn transformed C comments in echo commands back into comments.
+/echo/s,echo '\(.*\):\\Option-x\(.*\)\\Option-x:\(.*\)',echo '\1/*\2*/\3',
+
+# Whack out various clever expressions that search for tools, since
+# the clever code is too /bin/sh specific.
+
+/^AR_FOR_TARGET = `/,/`$/c\
+AR_FOR_TARGET = ::binutils:ar\
+
+
+/^RANLIB_FOR_TARGET = `/,/`$/c\
+RANLIB_FOR_TARGET = ::binutils:ranlib\
+
+
+/^RANLIB_TEST_FOR_TARGET = /,/ranlib ] )$/c\
+RANLIB_TEST_FOR_TARGET = \
+
+
+/^EXPECT = `/,/`$/c\
+EXPECT = \
+
+
+/^RUNTEST = `/,/`$/c\
+RUNTEST = \
+
+
+/^CC_FOR_TARGET = `/,/`$/c\
+CC_FOR_TARGET = \
+
+
+/^CXX_FOR_TARGET = `/,/`$/c\
+CXX_FOR_TARGET = \
+
+
+/^CHILL_FOR_TARGET = `/,/`$/c\
+CHILL_FOR_TARGET = \
+
+
+/^CHILL_LIB = `/,/`$/c\
+CHILL_LIB = \
+
+/sanit/s/{start-sanit...-[a-z0-9]*}//
+/sanit/s/{end-sanit...-[a-z0-9]*}//
+
+# Add standard defines and default rules.
+/^# srcdir/a\
+\
+s = "{srcdir}"\
+\
+o = :\
+\
+"{o}" \\Option-f : "{s}"
+
diff --git a/config/mpw/mpw-touch b/config/mpw/mpw-touch
new file mode 100644 (file)
index 0000000..c743a51
--- /dev/null
@@ -0,0 +1,7 @@
+# "Touch" command.
+
+If "`Exists "{1}"`" != ""
+       SetFile -m . "{1}"
+Else
+       Echo ' ' > "{1}"
+End If
diff --git a/config/mpw/mpw-true b/config/mpw/mpw-true
new file mode 100644 (file)
index 0000000..0506530
--- /dev/null
@@ -0,0 +1 @@
+Exit 0
diff --git a/config/mpw/null-command b/config/mpw/null-command
new file mode 100644 (file)
index 0000000..4844c8e
--- /dev/null
@@ -0,0 +1 @@
+# This command does nothing.
diff --git a/config/mpw/open-brace b/config/mpw/open-brace
new file mode 100644 (file)
index 0000000..58465dc
--- /dev/null
@@ -0,0 +1,4 @@
+# MPW makefiles seem not to have any way to get a literal open
+# brace into a rule anywhere, so this does the job.
+
+Echo '{'
diff --git a/config/mpw/tr-7to8-src b/config/mpw/tr-7to8-src
new file mode 100644 (file)
index 0000000..b20b649
--- /dev/null
@@ -0,0 +1,9 @@
+StreamEdit -e \Option-d
+  '/\Option-x/ \Option-d
+    Replace /\Option-d\SrcOption-d/ "\Option-d\Option-d" -c \Option-5 ; \Option-d
+    Replace /\Option-d\SrcOption-f/ "\Option-d\Option-f" -c \Option-5 ; \Option-d
+       Replace /\Option-d\SrcOption-8/ "\Option-d\Option-8" -c \Option-5 ; \Option-d
+       Replace /\Option-d\SrcOption-5/ "\Option-d\Option-5" -c \Option-5 ; \Option-d
+       Replace /\Option-d\SrcOption-x/ "\Option-d\Option-x" -c \Option-5 ; \Option-d
+       Replace /\Option-d\SrcOption-r/ "\Option-d\Option-r" -c \Option-5'  \Option-d
+  "{1}"
diff --git a/config/mpw/true b/config/mpw/true
new file mode 100644 (file)
index 0000000..0506530
--- /dev/null
@@ -0,0 +1 @@
+Exit 0
diff --git a/config/mt-armpic b/config/mt-armpic
new file mode 100644 (file)
index 0000000..35b8c9e
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG_FOR_TARGET=-fPIC
diff --git a/config/mt-d30v b/config/mt-d30v
new file mode 100644 (file)
index 0000000..d34b774
--- /dev/null
@@ -0,0 +1,4 @@
+# Build libraries optimizing for space, not speed.
+# Turn off warnings about symbols named the same as registers
+ CFLAGS_FOR_TARGET = -g -Os -Wa,-C
+ CXXFLAGS_FOR_TARGET = -g -Os -Wa,-C
diff --git a/config/mt-elfalphapic b/config/mt-elfalphapic
new file mode 100644 (file)
index 0000000..35b8c9e
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG_FOR_TARGET=-fPIC
diff --git a/config/mt-linux b/config/mt-linux
new file mode 100644 (file)
index 0000000..a09e6f1
--- /dev/null
@@ -0,0 +1,2 @@
+# When using glibc 2 on Linux we must always use vtable thunks.
+CXXFLAGS_FOR_TARGET = $(CXXFLAGS) -fvtable-thunks -D_GNU_SOURCE
diff --git a/config/mt-m68kpic b/config/mt-m68kpic
new file mode 100644 (file)
index 0000000..ff98727
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG_FOR_TARGET=-fpic
diff --git a/config/mt-netware b/config/mt-netware
new file mode 100644 (file)
index 0000000..9482f9b
--- /dev/null
@@ -0,0 +1 @@
+GDB_NLM_DEPS = all-gcc all-ld
diff --git a/config/mt-ospace b/config/mt-ospace
new file mode 100644 (file)
index 0000000..7f09104
--- /dev/null
@@ -0,0 +1,3 @@
+# Build libraries optimizing for space, not speed.
+ CFLAGS_FOR_TARGET = -g -Os
+ CXXFLAGS_FOR_TARGET = -g -Os
diff --git a/config/mt-papic b/config/mt-papic
new file mode 100644 (file)
index 0000000..35b8c9e
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG_FOR_TARGET=-fPIC
diff --git a/config/mt-ppcpic b/config/mt-ppcpic
new file mode 100644 (file)
index 0000000..35b8c9e
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG_FOR_TARGET=-fPIC
diff --git a/config/mt-sparcpic b/config/mt-sparcpic
new file mode 100644 (file)
index 0000000..fd0ec27
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG_FOR_TARGET=`case "${LIBCFLAGS} ${LIBCXXFLAGS}" in *-fpic* ) echo -fpic ;; * ) echo -fPIC ;; esac`
diff --git a/config/mt-v810 b/config/mt-v810
new file mode 100644 (file)
index 0000000..97da6c2
--- /dev/null
@@ -0,0 +1,4 @@
+CC_FOR_TARGET = ca732 -ansi
+AS_FOR_TARGET = as732
+AR_FOR_TARGET = ar732
+RANLIB_FOR_TARGET = true
diff --git a/config/mt-x86pic b/config/mt-x86pic
new file mode 100644 (file)
index 0000000..ff98727
--- /dev/null
@@ -0,0 +1 @@
+PICFLAG_FOR_TARGET=-fpic
diff --git a/etc/ChangeLog b/etc/ChangeLog
new file mode 100644 (file)
index 0000000..0453a3e
--- /dev/null
@@ -0,0 +1,507 @@
+1999-04-01  Jim Blandy  <jimb@zwingli.cygnus.com>
+
+       * add-log.el, add-log.vi: New files.
+
+Wed Jan 20 01:33:50 1999  Angela Marie Thomas (angela@cygnus.com)
+
+       * comp-tools-verify: Remove some checks that are no longer valid.
+
+1998-12-03  Nick Clifton  <nickc@cygnus.com>
+
+       * targetdoc/fr30.texi: New document.
+       
+Thu Oct  1 21:15:59 1998  Angela Marie Thomas (angela@cygnus.com)
+
+       * comp-tools-fix, cross-tools-fix: Replace /usr/include
+       with ${FIXINCDIR}.
+
+Tue Aug 11 19:22:11 1998  Doug Evans  <devans@canuck.cygnus.com>
+
+       * make-rel-sym-tree (version): Update calculation.
+
+Fri Jun 12 21:34:01 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.texi: Various additions.
+       * Makefile.in (TEXI2HTML, DVIPS): New variables.
+       (standards.ps): New target.
+       (configure.dvi): Copy .tin files in as well.
+       (configure.ps, configure.html): New targets.
+       (clean): Remove configdev.jpg and configbuild.jpg.
+       * configdev.fig: New file.
+       * configdev.ein: New file (EPS version of configdev.fig).
+       * configdev.jin: New file (JPEG version of configdev.fig).
+       * configbuild.fig: New file.
+       * configbuild.ein: New file (EPS version of configbuild.fig).
+       * configbuild.jin: New file (JPEG version of configbuild.fig).
+
+Wed Jun 10 14:41:25 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.texi: New file.
+       * configdev.tin: New file.
+       * configbuild.tin: New file.
+       * Makefile.in (MAKEINFO): Use makeinfo from texinfo directory if
+       it exists.
+       (TEXI2DVI): Likewise for texi2dvi.
+       (INFOFILES): Add configure.info.
+       (DVIFILES): Add configure.dvi.
+       (info): Only build info files if the source files exist.
+       (install-info): Only install info files if they exist.
+       (dvi): Only build DVI files if the sources files exist.
+       (configure.info): New target.
+       (configure.dvi): New target.
+       (clean): Remove configdev and configbuild derived files.
+
+       Remove obsolete documentation.
+       * intro.texi: Remove.
+       * install.texi: Remove.
+       * config-names.texi: Remove.
+       * screen1.eps: Remove.
+       * screen1.obj: Remove.
+       * screen2.eps: Remove.
+       * screen2.obj: Remove.
+       * Makefile.in: Remove references to the above.
+
+Thu May 21 14:34:51 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * targetdoc/arm-interwork.texi: Add note about ignoring linker
+       warning message when using --support-old-code.
+
+Mon May 18 14:27:37 1998  Angela Marie Thomas (angela@cygnus.com)
+
+       * Install.in, comp-tools-fix, comp-tools-verify, cross-tools-fix:
+       Use $GCCvn rather than substitute everywhere.
+
+Thu May 14 14:43:10 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * targetdoc/arm-interwork.texi: Document dlltool support of
+       interworking. 
+
+Thu May  7 16:49:38 1998  Jason Molenda  (crash@bugshack.cygnus.com)
+
+       * Install.in: Remove references to TCL_LIBRARY, TK_LIBRARY,
+       and GDBTK_FILENAME.
+
+Wed Apr  1 17:11:44 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * targetdoc/arm-interwork.texi: Document ARM/thumb interworking. 
+
+Tue Mar 31 15:28:20 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * standards.texi, make-stds.texi: Update to current FSF versions.
+       * Makefile.in (standards.info): Depend upon make-std.texi.
+
+Tue Mar 24 16:13:26 1998  Stu Grossman  <grossman@bhuna.cygnus.co.uk>
+
+       * configure:  Regenerate with autoconf 2.12.1 to fix shell issues
+       for NT native builds. 
+
+Mon Mar  9 16:41:04 1998  Doug Evans  <devans@canuck.cygnus.com>
+
+       * make-rel-sym-tree (binprogs): Add objcopy.
+
+Tue Feb 24 18:11:58 1998  Doug Evans  <devans@canuck.cygnus.com>
+
+       * make-rel-sym-tree: as.new -> as-new, ld.new -> ld-new
+       nm.new -> nm-new.  Make symlinks to crt*.o.
+
+Fri Nov 21 12:54:58 1997  Manfred Hollstein <manfred@s-direktnet.de>
+
+       * Makefile.in: Add --no-split argument to avoid creating files
+       with names longer than 14 characters.
+
+Thu Sep 25 13:13:11 1997  Jason Molenda  (crash@pern.cygnus.com)
+
+       * intro.texi: Add closing ifset.
+
+Mon Sep  1 10:31:32 1997  Angela Marie Thomas (angela@cygnus.com)
+
+       * Install.in: Move setting HOST and TARGET to the beginning
+       of the file for editing convenience.
+
+Mon Sep  1 10:28:37 1997  Angela Marie Thomas (angela@cygnus.com)
+
+       * Install.in.: More friendly options/messages when extracting
+       from a file instead of a tape device.
+
+Tue Jun 17 15:50:23 1997  Angela Marie Thomas (angela@cygnus.com)
+
+       * Install.in: Add /usr/bsd to PATH for Irix (home of compress)
+
+Thu Jun 12 13:47:00 1997  Angela Marie Thomas (angela@cygnus.com)
+
+        * Install.in (show_exec_prefix_msg): fix quoting
+
+Wed Jun  4 15:31:43 1997  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * rebuilding.texi: Removed.
+
+Sat May 24 18:02:20 1997  Angela Marie Thomas (angela@cygnus.com)
+
+       * cross-tools-fix:  Remove host check since it doesn't matter
+       for this case.
+       * Install.in (guess_system): clean up more unused hosts.
+       * Install.in, cross-tools-fix, comp-tools-fix, comp-tools-verify:
+       Hack for host check to not warn the user for certain cases.
+
+Fri May 23 23:46:10 1997  Angela Marie Thomas (angela@cygnus.com)
+
+       * subst-strings: Remove a lot of unused code
+       * Install.in: Remove reference to TAPEdflt, use variables instead of
+       string substitution when able.
+
+Fri Apr 11 17:25:52 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Change file named in AC_INIT to Makefile.in.
+       * configure: Rebuild.
+
+Fri Apr 11 18:12:42 1997  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * Install.in (guess_system): Back out change to INSTALLHOST to
+       call all IRIX systems "mips-sgi-irix4"
+
+       * Makefile.in: Remove references to configure.texi and cfg-paper.texi.
+
+Thu Apr 10 23:26:45 1997  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * srctree.texi, emacs-relnotes.texi, cfg-paper.texi: Remove.
+       * Install.in: Remove Ultrix-specific hacks.
+       Update Cygnus phone numbers.
+       (guess_system): Remove some old systems (Ultrix, OSF1 v1 & 2,
+       m68k-HPUX, m68k SunOS, etc.)
+       (show_gnu_root_msg): Remove.
+       Removed all the remove option code.
+
+Thu Apr 10 23:23:33 1997  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * configure.man, configure.texi: Remote.
+
+Mon Apr  7 18:15:00 1997  Brendan Kehoe <brendan@cygnus.com>
+
+        * Fix the version string for OSF1 4.0 to recognize either
+        V4.* or X4.*
+
+Mon Apr  7 15:34:47 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * standards.texi, make-stds.texi: Update to current FSF versions.
+
+Tue Nov 19 15:36:14 1996  Doug Evans  <dje@canuck.cygnus.com>
+
+       * make-rel-sym-tree: New file.
+
+Wed Oct 23 00:34:07 1996  Angela Marie Thomas (angela@cygnus.com)
+
+       * Lots of patches from progressive...
+       * Install.in: restore DDOPTS for AIX 4.x
+       * Install.in, subst-strings: add case for DG Aviion
+       * subst-strings: fix typo in INSTALLdir var setting
+       * comp-tools-verify: set SHLIB_PATH for shared libs
+       * Install.in, subst-strings:  add case for solaris2.5
+       * Install.in: fix regression for hppa1.1 check
+       * comp-tools-fix: set LD_LIBRARY_PATH
+       * comp-tools-fix: If fixincludes fixes /usr/include/limits.h,
+       install it as syslimits.h.
+
+Wed Oct 16 19:20:42 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * Install.in (guess_system): Treat powerpc-ibm-aix4.1 the same as
+       rs6000-ibm-aix4.1, since the compiler now uses common mode by
+       default.
+
+Wed Oct  2 15:39:07 1996  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * configure.in (AC_PROG_INSTALL): Added.
+       * Makefile.in (distclean): Remove config.cache.
+
+Wed Oct  2 14:33:58 1996  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * configure.in: Switch to autoconf configure.in.
+       * configure: New.
+       * Makefile.in: Use autoconf-substituted values.
+
+Tue Jun 25 18:56:08 1996  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * Makefile.in (datadir): Changed to $(prefix)/share.
+
+Fri Mar 29 11:38:01 1996  J.T. Conklin  (jtc@lisa.cygnus.com)
+
+       * configure.man: Changed to be recognized by catman -w on Solaris.
+
+Wed Dec  6 15:40:28 1995  Doug Evans  <dje@canuck.cygnus.com>
+
+       * comp-tools-fix (fixincludes): Define FIXPROTO_DEFINES from
+       .../install-tools/fixproto-defines.
+
+Sun Nov 12 19:31:27 1995  Jason Molenda  (crash@phydeaux.cygnus.com)
+
+       * comp-tools-verify (verify_cxx_initializers): delete argv,
+       argc declarations, add -static to compile line.
+       (verify_cxx_hello_world): delete argv, argc declarations, add
+       -static to compile line.
+
+Wed Sep 20 13:21:52 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (maintainer-clean): New target, synonym for
+       realclean.
+
+Mon Aug 28 17:25:49 1995  Jason Molenda  (crash@phydeaux.cygnus.com)
+
+       * Install.in (PATH):  add /usr/ucb to $PATH (for SunOS 4.1.x).
+
+Tue Aug 15 21:51:58 1995  Jason Molenda  (crash@phydeaux.cygnus.com)
+
+       * Install.in (guess_system): Match OSF/1 v3.x as the same as 
+        v2.x--v2.x binaries are upward compatible.
+
+Tue Aug 15 21:46:54 1995  Jason Molenda  (crash@phydeaux.cygnus.com)
+
+       * Install.in (guess_system): recognize HP 9000/800 systems as the
+       same as HP 9000/700 systems.
+
+Tue Aug  8 13:11:56 1995  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * Install.in: For emacs, run show_emacs_alternate_msg and exit.
+       (show_emacs_alternate_msg): New message saying how emacs can't be
+       installed in an alternate prefix.
+
+Thu Jun  8 00:42:56 1995  Angela Marie Thomas  <angela@cirdan.cygnus.com>
+
+        * subst-strings: change du commands to $BINDIR/. & $SRCDIR/. just
+        in case they are symlinks.
+
+Tue Apr 18 14:23:10 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * cdk-fix: Extracted table of targets that don't need their
+         headers fixed from gcc's configure script.
+
+       * cdk-fix, cdk-verify: Use ${HOST} instead of ||HOSTstr||
+
+       * cdk-fix, cdk-verify: New files, install script fragments used
+         for Cygnus Developer's Kit.
+
+       * Install.in (do_mkdir): New function.
+
+       * Install.in: Added support for --with and --without options.
+         Changed so that tape commands are not run when extracting 
+         from a file.
+         (do_mt): Changed to take only one argument.
+
+Wed Mar 29 11:16:38 1995  Jason Molenda (crash@phydeaux.cygnus.com)
+
+       * Install.in: catch UNAME==alpha-dec-osf2.x and correct entry for
+       alpha-dec-osf1.x
+       
+Fri Jan 27 12:04:29 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * subst-strings (mips-sgi-irix5): New entry in table.
+
+Thu Jan 19 12:15:44 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * Install.in: Major rewrite, bundle dependent code (for example,
+         fixincludes for comp-tools) will be inserted into the Install
+         script when it is generated.
+
+Tue Jan 17 16:51:32 1995  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * Makefile.in (Makefile): Rebuild using $(SHELL).
+
+Thu Nov  3 19:30:33 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in (install-info): Depend on info.
+
+Fri Aug 19 16:16:38 1994  Jason Molenda     (crash@phydeaux.cygnus.com)
+
+       * Install.in: set $FIX_HEADER so fixproto can find fix-header.
+
+Fri May  6 16:18:58 1994  Jason Molenda     (crash@sendai.cygnus.com)
+
+       * Makefile.in (install-info): add a semicolon in the if statement.
+
+Fri Apr 29 16:56:07 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * cfg-paper.texi: Update some outdated information.
+
+       * Makefile.in (install-info): Pass file, not directory, as last
+       arg to INSTALL_DATA.
+       (uninstall): New target.
+
+Thu Apr 28 14:42:22 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * configure.texi: Comment out @smallbook.
+
+       * Makefile.in: Define TEXI2DVI and TEXIDIR, and use the latter.
+       Remove info files in realclean, not clean, per coding standards.
+       Remove TeX output in clean.
+
+Tue Apr 26 17:18:03 1994  Jason Molenda (crash@sendai.cygnus.com)
+
+        * Install.in:  fixincludes output is actually put in fixincludes.log,
+        but echo'ed messages claim it is fixinc.log.  This is the same
+       messages as I logged in March 4 1994, but for some reason we found
+       the change hadn't been done.  I'll have to dig through the logs
+       and find out what I really did do that day. :)
+
+Mon Apr 25 20:28:19 1994  Jason Molenda   (crash@sendai.cygnus.com)
+
+       * Install.in:  use eval to call do_mt() for Ultrix brokenness.
+
+Mon Apr 25 20:00:00 1994  Jason Molenda   (crash@sendai.cygnus.com)
+
+       * Install.in(do_mt): exit with error status 1 if # of parameters
+       != 3.
+
+Mon Apr 25 19:42:36 1994  Jason Molenda   (crash@sendai.cygnus.com)
+
+       * Install.in:  lose TAPE_FORWARD and TAPE_REWIND, add do_mt()
+       to do all tape movement operations.  Currently untested.  Addresses
+       PR # 4886 from bull.
+
+       * Install.in: add 1994 to the copyright thing.
+
+Fri Apr 22 19:05:13 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * standards.texi: Update from FSF.
+
+Fri Apr 22 15:46:10 1994  Jason Molenda (crash@cygnus.com)
+
+       * Install.in: Add $DDOPTS, has ``bs=124b'' for all systems except
+       AIX (some versions of AIX don't understand bs=124b.  Silly OS).
+
+Mon Apr  4 22:55:05 1994  Jason Molenda (crash@sendai.cygnus.com)
+
+       * Install.in: null out $TOOLS before adding stuff to it
+       non-destructively.
+
+Wed Mar 30 21:45:35 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * standards.texi: Fix typo.
+
+       * configure.texi, configure.man: Document --disable-.
+
+Mon Mar 28 13:22:15 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * standards.texi: Update from FSF.
+
+Sat Mar 26 09:21:44 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * standards.texi, make-stds.texi: Update from FSF.
+
+Fri Mar 25 22:59:45 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
+
+       * configure.texi, configure.man: Document --enable-* options.
+
+Wed Mar 23 23:38:24 1994  Jason Molenda  (crash@sendai.cygnus.com)
+
+       * Install.in: set CPP to be gcc -E for fixincludes.
+
+Wed Mar 23 13:42:48 1994  Jason Molenda  (crash@sendai.cygnus.com)
+
+        * Install.in: set PATH to $PATH:/bin:/usr/bin so we can pick
+        up native tools even if the user doesn't have them in his
+        path.
+
+        * Install.in: ``hppa-1.1-hp-hpux'' -> ``hppa1.1-hp-hpux''.
+
+Tue Mar 15 22:09:20 1994  Jason Molenda  (crash@sendai.cygnus.com)
+        
+        * Install.in: TAPE_REWIND and TAPE_FORWARD variables for Unixunaware,
+        added switch statement to detect if system is Unixunaware.
+
+Fri Mar  4 12:10:30 1994  Jason Molenda (crash@sendai.cygnus.com)
+
+        * Install.in:  fixincludes output is actually put in fixincludes.log,
+        but echo'ed messages claim it is fixinc.log.
+
+Wed Nov  3 02:58:02 1993  Jeffrey Osier  (jeffrey@thepub.cygnus.com)
+
+       * subst-strings:  output TEXBUNDLE for more install notes matching
+       * install-texi.in:  PRMS info now exists
+
+Tue Oct 26 16:57:12 1993  K. Richard Pixley  (rich@sendai.cygnus.com)
+
+       * subst-strings: match solaris*.  Also, add default case to catch
+         and error out for unrecognized systems.
+
+Thu Aug 19 18:21:31 1993  david d `zoo' zuhn  (zoo@rtl.cygnus.com)
+
+       * Install.in: handle the new fixproto work
+
+Mon Jul 19 12:05:41 1993  david d `zoo' zuhn  (zoo@cirdan.cygnus.com)
+
+       * Install.in: remove "MT=tctl" for AIX (not needed, and barely
+       worked anyway)
+
+Mon Jun 14 19:09:22 1993  Jeffrey Osier  (jeffrey@cygnus.com)
+
+       * subst-strings: changed HOST to recognize Solaris for install notes
+
+Thu Jun 10 16:01:25 1993  Jeffrey Osier  (jeffrey@cygnus.com)
+
+       * dos-inst.texi:  new file.
+
+Wed Jun  9 19:23:59 1993  Jeffrey Osier  (jeffrey@rtl.cygnus.com)
+
+        * install-texi.in:        added conditionals (nearly complete)
+                                  cleaned up
+                                  added support for other releases (not done)
+
+Wed Jun  9 15:53:58 1993  Jim Kingdon  (kingdon@cygnus.com)
+
+       * Makefile.in (install-info): Use INSTALL_DATA.
+       ({dist,real}clean): Also delete Makefile and config.status.
+
+Fri Jun  4 17:09:56 1993  Jeffrey Osier  (jeffrey@cygnus.com)
+
+       * subst-strings:  added data for OS_STRING
+
+       * subst-strings:  added support for OS_STRING
+
+Thu Jun  3 00:37:01 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Install.in: pull COPYING and COPYING.LIB off of the tape 
+
+Tue Jun  1 16:52:08 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * subst-strings: replace RELEASE_DIR too
+
+Mon Mar 22 23:55:27 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: add installcheck target
+
+Wed Mar 17 02:21:15 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Install.in: fix 'source only' extraction bug where it looked for
+       the src dir under H-<host>/src instead of src; also remove stray
+       reference to EMACSHIBIN
+
+Mon Mar 15 01:25:45 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * make-stds.texi: added 'installcheck' to the standard targets
+
+Tue Mar  9 19:48:28 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * standards.texi: added INFO-DIR-ENTRY, updated version from the FSF
+
+Tue Feb  9 12:40:23 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in (standards.info): Added -I$(srcdir) to find
+       make-stds.texi.
+
+Mon Feb  1 16:32:56 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * standards.texi: updated to latest FSF version, which includes:
+
+       * make-stds.texi: new file
+
+Mon Nov 30 01:31:40 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * install-texi.in, relnotes.texi, intro.texi: changed Cygnus phone
+       numbers from the old Palo Alto ones to the new Mtn. View numbers
+
+Mon Nov 16 16:50:43 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: define $(RM) to "rm -f"
+
+Sun Oct 11 16:05:48 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * intro.texi: added INFO-DIR-ENTRY
+
diff --git a/etc/Makefile.in b/etc/Makefile.in
new file mode 100644 (file)
index 0000000..eedc8c9
--- /dev/null
@@ -0,0 +1,156 @@
+# 
+# Makefile.in for etc
+#
+
+prefix                 = @prefix@
+exec_prefix    = @exec_prefix@
+
+srcdir  = @srcdir@
+VPATH  = @srcdir@
+
+bindir  = @bindir@
+libdir  = @libdir@
+tooldir = $(libdir)
+datadir = @datadir@
+
+mandir  = @mandir@
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = @infodir@
+
+SHELL = /bin/sh
+
+INSTALL        = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA    = @INSTALL_DATA@
+
+MAKEINFO = `if [ -f ../texinfo/makeinfo/makeinfo ]; \
+       then echo ../texinfo/makeinfo/makeinfo; \
+       else echo makeinfo; fi`
+TEXI2DVI = `if [ -f ../texinfo/util/texi2dvi ]; \
+       then echo ../texinfo/util/texi2dvi; \
+       else echo texi2dvi; fi`
+TEXI2HTML = texi2html
+DVIPS = dvips
+
+# Where to find texinfo.tex to format documentation with TeX.
+TEXIDIR = $(srcdir)/../texinfo
+
+#### Host, target, and site specific Makefile fragments come in here.
+###
+
+INFOFILES = standards.info configure.info
+DVIFILES = standards.dvi configure.dvi
+
+all:
+
+install:
+
+uninstall:
+
+info:
+       for f in $(INFOFILES); do \
+         if test -f $(srcdir)/`echo $$f | sed -e 's/.info$$/.texi/'`; then \
+           if $(MAKE) "MAKEINFO=$(MAKEINFO)" $$f; then \
+             true; \
+           else \
+             exit 1; \
+           fi; \
+         fi; \
+       done
+
+install-info: info
+       $(SHELL) $(srcdir)/../mkinstalldirs $(infodir)
+       if test ! -f standards.info; then cd $(srcdir); fi; \
+       if test -f standards.info; then \
+         for i in standards.info*; do \
+           $(INSTALL_DATA) $$i $(infodir)/$$i; \
+         done; \
+       fi
+       if test ! -f configure.info; then cd $(srcdir); fi; \
+       if test -f configure.info; then \
+         for i in configure.info*; do \
+           $(INSTALL_DATA) $$i $(infodir)/$$i; \
+         done; \
+       fi
+
+dvi:
+       for f in $(DVIFILES); do \
+         if test -f $(srcdir)/`echo $$f | sed -e 's/.dvi$$/.texi/'`; then \
+           if $(MAKE) "TEXI2DVI=$(TEXI2DVI)" $$f; then \
+             true; \
+           else \
+             exit 1; \
+           fi; \
+         fi; \
+       done
+
+standards.info: $(srcdir)/standards.texi $(srcdir)/make-stds.texi
+       $(MAKEINFO) --no-split -I$(srcdir) -o standards.info $(srcdir)/standards.texi
+
+standards.dvi: $(srcdir)/standards.texi
+       TEXINPUTS=$(TEXIDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/standards.texi
+
+standards.ps: standards.dvi
+       $(DVIPS) standards.dvi -o standards.ps
+
+# makeinfo requires images to be in the current directory.
+configure.info: $(srcdir)/configure.texi $(srcdir)/configdev.tin $(srcdir)/configbuild.tin
+       rm -f configdev.txt configbuild.txt
+       cp $(srcdir)/configdev.tin configdev.txt
+       cp $(srcdir)/configbuild.tin configbuild.txt
+       $(MAKEINFO) -I$(srcdir) -o configure.info $(srcdir)/configure.texi
+       rm -f configdev.txt configbuild.txt
+
+# texi2dvi wants both the .txt and the .eps files.
+configure.dvi: $(srcdir)/configure.texi $(srcdir)/configdev.tin $(srcdir)/configbuild.tin $(srcdir)/configdev.ein $(srcdir)/configbuild.ein
+       rm -f configdev.txt configbuild.txt
+       cp $(srcdir)/configdev.tin configdev.txt
+       cp $(srcdir)/configbuild.tin configbuild.txt
+       rm -f configdev.eps configbuild.eps
+       cp $(srcdir)/configdev.ein configdev.eps
+       cp $(srcdir)/configbuild.ein configbuild.eps
+       TEXINPUTS=$(TEXIDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/configure.texi
+       rm -f configdev.txt configbuild.txt
+       rm -f configdev.eps configbuild.eps
+
+# dvips requires images to be in the current directory
+configure.ps: configure.dvi $(srcdir)/configdev.ein $(srcdir)/configbuild.ein
+       rm -f configdev.eps configbuild.eps
+       cp $(srcdir)/configdev.ein configdev.eps
+       cp $(srcdir)/configbuild.ein configbuild.eps
+       $(DVIPS) configure.dvi -o configure.ps
+       rm -f configdev.eps configbuild.eps
+
+configure.html: $(srcdir)/configure.texi
+       $(TEXI2HTML) -split_chapter $(srcdir)/configure.texi
+
+clean:
+       rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
+       rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs
+       rm -f configdev.txt configbuild.txt configdev.eps configbuild.eps
+       rm -f configdev.jpg configbuild.jpg
+
+mostlyclean: clean
+
+distclean:   clean
+       rm -f Makefile config.status config.cache
+
+maintainer-clean realclean:   distclean
+       rm -f *.info*
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+       $(SHELL) ./config.status
+
+## these last targets are for standards.texi conformance
+dist:
+check:
+installcheck:
+TAGS:
diff --git a/etc/add-log.el b/etc/add-log.el
new file mode 100644 (file)
index 0000000..60c88e8
--- /dev/null
@@ -0,0 +1,573 @@
+;;; ============ NOTE WELL! =============
+;;;
+;;; You only need to use this file if you're using a version of Emacs
+;;; prior to 20.1 to work on GDB.  The only difference between this
+;;; and the standard add-log.el provided with 19.34 is that it
+;;; generates dates using the terser format used by Emacs 20.  This is
+;;; the format recommended for use in GDB ChangeLogs.
+;;;
+;;; To use this code, you should create a directory `~/elisp', save the code
+;;; below in `~/elisp/add-log.el', and then put something like this in
+;;; your `~/.emacs' file, to tell Emacs where to find it:
+;;; 
+;;; (setq load-path
+;;;       (cons (expand-file-name "~/elisp")
+;;;             load-path))
+;;; 
+;;; If you want, you can also byte-compile it --- it'll run a little
+;;; faster, and use a little less memory.  (Not that those matter much for
+;;; this file.)  To do that, after you've saved the text as
+;;; ~/elisp/add-log.el, bring it up in Emacs, and type
+;;; 
+;;;     C-u M-x byte-compile-file
+;;;
+;;; --- Jim Blandy
+
+;;; add-log.el --- change log maintenance commands for Emacs
+
+;; Copyright (C) 1985, 1986, 1988, 1993, 1994 Free Software Foundation, Inc.
+
+;; Keywords: maint
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This facility is documented in the Emacs Manual.
+
+;;; Code:
+
+(defvar change-log-default-name nil
+  "*Name of a change log file for \\[add-change-log-entry].")
+
+(defvar add-log-current-defun-function nil
+  "\
+*If non-nil, function to guess name of current function from surrounding text.
+\\[add-change-log-entry] calls this function (if nil, `add-log-current-defun'
+instead) with no arguments.  It returns a string or nil if it cannot guess.")
+
+;;;###autoload
+(defvar add-log-full-name nil
+  "*Full name of user, for inclusion in ChangeLog daily headers.
+This defaults to the value returned by the `user-full-name' function.")
+
+;;;###autoload
+(defvar add-log-mailing-address nil
+  "*Electronic mail address of user, for inclusion in ChangeLog daily headers.
+This defaults to the value of `user-mail-address'.")
+
+(defvar change-log-font-lock-keywords
+  '(("^[SMTWF].+" . font-lock-function-name-face)      ; Date line.
+    ("^\t\\* \\([^ :\n]+\\)" 1 font-lock-comment-face) ; File name.
+    ("(\\([^)\n]+\\)):" 1 font-lock-keyword-face))     ; Function name.
+  "Additional expressions to highlight in Change Log mode.")
+
+(defvar change-log-mode-map nil
+  "Keymap for Change Log major mode.")
+(if change-log-mode-map
+    nil
+  (setq change-log-mode-map (make-sparse-keymap))
+  (define-key change-log-mode-map "\M-q" 'change-log-fill-paragraph))
+
+(defun change-log-name ()
+  (or change-log-default-name
+      (if (eq system-type 'vax-vms) 
+         "$CHANGE_LOG$.TXT" 
+       (if (or (eq system-type 'ms-dos) (eq system-type 'windows-nt))
+           "changelo"
+         "ChangeLog"))))
+
+;;;###autoload
+(defun prompt-for-change-log-name ()
+  "Prompt for a change log name."
+  (let* ((default (change-log-name))
+        (name (expand-file-name
+               (read-file-name (format "Log file (default %s): " default)
+                               nil default))))
+    ;; Handle something that is syntactically a directory name.
+    ;; Look for ChangeLog or whatever in that directory.
+    (if (string= (file-name-nondirectory name) "")
+       (expand-file-name (file-name-nondirectory default)
+                         name)
+      ;; Handle specifying a file that is a directory.
+      (if (file-directory-p name)
+         (expand-file-name (file-name-nondirectory default)
+                           (file-name-as-directory name))
+       name))))
+
+;;;###autoload
+(defun find-change-log (&optional file-name)
+  "Find a change log file for \\[add-change-log-entry] and return the name.
+
+Optional arg FILE-NAME specifies the file to use.
+If FILE-NAME is nil, use the value of `change-log-default-name'.
+If 'change-log-default-name' is nil, behave as though it were 'ChangeLog'
+\(or whatever we use on this operating system).
+
+If 'change-log-default-name' contains a leading directory component, then
+simply find it in the current directory.  Otherwise, search in the current 
+directory and its successive parents for a file so named.
+
+Once a file is found, `change-log-default-name' is set locally in the
+current buffer to the complete file name."
+  ;; If user specified a file name or if this buffer knows which one to use,
+  ;; just use that.
+  (or file-name
+      (setq file-name (and change-log-default-name
+                          (file-name-directory change-log-default-name)
+                          change-log-default-name))
+      (progn
+       ;; Chase links in the source file
+       ;; and use the change log in the dir where it points.
+       (setq file-name (or (and buffer-file-name
+                                (file-name-directory
+                                 (file-chase-links buffer-file-name)))
+                           default-directory))
+       (if (file-directory-p file-name)
+           (setq file-name (expand-file-name (change-log-name) file-name)))
+       ;; Chase links before visiting the file.
+       ;; This makes it easier to use a single change log file
+       ;; for several related directories.
+       (setq file-name (file-chase-links file-name))
+       (setq file-name (expand-file-name file-name))
+       ;; Move up in the dir hierarchy till we find a change log file.
+       (let ((file1 file-name)
+             parent-dir)
+         (while (and (not (or (get-file-buffer file1) (file-exists-p file1)))
+                     (progn (setq parent-dir
+                                  (file-name-directory
+                                   (directory-file-name
+                                    (file-name-directory file1))))
+                            ;; Give up if we are already at the root dir.
+                            (not (string= (file-name-directory file1)
+                                          parent-dir))))
+           ;; Move up to the parent dir and try again.
+           (setq file1 (expand-file-name 
+                        (file-name-nondirectory (change-log-name))
+                        parent-dir)))
+         ;; If we found a change log in a parent, use that.
+         (if (or (get-file-buffer file1) (file-exists-p file1))
+             (setq file-name file1)))))
+  ;; Make a local variable in this buffer so we needn't search again.
+  (set (make-local-variable 'change-log-default-name) file-name)
+  file-name)
+
+;;;###autoload
+(defun add-change-log-entry (&optional whoami file-name other-window new-entry)
+  "Find change log file and add an entry for today.
+Optional arg (interactive prefix) non-nil means prompt for user name and site.
+Second arg is file name of change log.  If nil, uses `change-log-default-name'.
+Third arg OTHER-WINDOW non-nil means visit in other window.
+Fourth arg NEW-ENTRY non-nil means always create a new entry at the front;
+never append to an existing entry."
+  (interactive (list current-prefix-arg
+                    (prompt-for-change-log-name)))
+  (or add-log-full-name
+      (setq add-log-full-name (user-full-name)))
+  (or add-log-mailing-address
+      (setq add-log-mailing-address user-mail-address))
+  (if whoami
+      (progn
+       (setq add-log-full-name (read-input "Full name: " add-log-full-name))
+        ;; Note that some sites have room and phone number fields in
+        ;; full name which look silly when inserted.  Rather than do
+        ;; anything about that here, let user give prefix argument so that
+        ;; s/he can edit the full name field in prompter if s/he wants.
+       (setq add-log-mailing-address
+             (read-input "Mailing address: " add-log-mailing-address))))
+  (let ((defun (funcall (or add-log-current-defun-function
+                           'add-log-current-defun)))
+       paragraph-end entry)
+
+    (setq file-name (expand-file-name (find-change-log file-name)))
+
+    ;; Set ENTRY to the file name to use in the new entry.
+    (and buffer-file-name
+        ;; Never want to add a change log entry for the ChangeLog file itself.
+        (not (string= buffer-file-name file-name))
+        (setq entry (if (string-match
+                         (concat "^" (regexp-quote (file-name-directory
+                                                    file-name)))
+                         buffer-file-name)
+                        (substring buffer-file-name (match-end 0))
+                      (file-name-nondirectory buffer-file-name))))
+
+    (if (and other-window (not (equal file-name buffer-file-name)))
+       (find-file-other-window file-name)
+      (find-file file-name))
+    (or (eq major-mode 'change-log-mode)
+       (change-log-mode))
+    (undo-boundary)
+    (goto-char (point-min))
+    (let ((heading (format "%s  %s  <%s>"
+                          (format-time-string "%Y-%m-%d")
+                          add-log-full-name
+                          add-log-mailing-address)))
+      (if (looking-at (regexp-quote heading))
+         (forward-line 1)
+       (insert heading "\n\n")))
+
+    ;; Search only within the first paragraph.
+    (if (looking-at "\n*[^\n* \t]")
+       (skip-chars-forward "\n")
+      (forward-paragraph 1))
+    (setq paragraph-end (point))
+    (goto-char (point-min))
+
+    ;; Now insert the new line for this entry.
+    (cond ((re-search-forward "^\\s *\\*\\s *$" paragraph-end t)
+          ;; Put this file name into the existing empty entry.
+          (if entry
+              (insert entry)))
+         ((and (not new-entry)
+               (let (case-fold-search)
+                 (re-search-forward
+                  (concat (regexp-quote (concat "* " entry))
+                          ;; Don't accept `foo.bar' when
+                          ;; looking for `foo':
+                          "\\(\\s \\|[(),:]\\)")
+                  paragraph-end t)))
+          ;; Add to the existing entry for the same file.
+          (re-search-forward "^\\s *$\\|^\\s \\*")
+          (goto-char (match-beginning 0))
+          ;; Delete excess empty lines; make just 2.
+          (while (and (not (eobp)) (looking-at "^\\s *$"))
+            (delete-region (point) (save-excursion (forward-line 1) (point))))
+          (insert "\n\n")
+          (forward-line -2)
+          (indent-relative-maybe))
+         (t
+          ;; Make a new entry.
+          (forward-line 1)
+          (while (looking-at "\\sW")
+            (forward-line 1))
+          (while (and (not (eobp)) (looking-at "^\\s *$"))
+            (delete-region (point) (save-excursion (forward-line 1) (point))))
+          (insert "\n\n\n")
+          (forward-line -2)
+          (indent-to left-margin)
+          (insert "* " (or entry ""))))
+    ;; Now insert the function name, if we have one.
+    ;; Point is at the entry for this file,
+    ;; either at the end of the line or at the first blank line.
+    (if defun
+       (progn
+         ;; Make it easy to get rid of the function name.
+         (undo-boundary)
+         (insert (if (save-excursion
+                       (beginning-of-line 1)
+                       (looking-at "\\s *$")) 
+                     ""
+                   " ")
+                 "(" defun "): "))
+      ;; No function name, so put in a colon unless we have just a star.
+      (if (not (save-excursion
+                (beginning-of-line 1)
+                (looking-at "\\s *\\(\\*\\s *\\)?$")))
+         (insert ": ")))))
+
+;;;###autoload
+(defun add-change-log-entry-other-window (&optional whoami file-name)
+  "Find change log file in other window and add an entry for today.
+Optional arg (interactive prefix) non-nil means prompt for user name and site.
+Second arg is file name of change log.  \
+If nil, uses `change-log-default-name'."
+  (interactive (if current-prefix-arg
+                  (list current-prefix-arg
+                        (prompt-for-change-log-name))))
+  (add-change-log-entry whoami file-name t))
+;;;###autoload (define-key ctl-x-4-map "a" 'add-change-log-entry-other-window)
+
+;;;###autoload
+(defun change-log-mode ()
+  "Major mode for editing change logs; like Indented Text Mode.
+Prevents numeric backups and sets `left-margin' to 8 and `fill-column' to 74.
+New log entries are usually made with \\[add-change-log-entry] or \\[add-change-log-entry-other-window].
+Each entry behaves as a paragraph, and the entries for one day as a page.
+Runs `change-log-mode-hook'."
+  (interactive)
+  (kill-all-local-variables)
+  (indented-text-mode)
+  (setq major-mode 'change-log-mode
+       mode-name "Change Log"
+       left-margin 8
+       fill-column 74
+    indent-tabs-mode t
+    tab-width 8)
+  (use-local-map change-log-mode-map)
+  ;; Let each entry behave as one paragraph:
+  ;; We really do want "^" in paragraph-start below: it is only the lines that
+  ;; begin at column 0 (despite the left-margin of 8) that we are looking for.
+  (set (make-local-variable 'paragraph-start) "\\s *$\\|\f\\|^\\sw")
+  (set (make-local-variable 'paragraph-separate) "\\s *$\\|\f\\|^\\sw")
+  ;; Let all entries for one day behave as one page.
+  ;; Match null string on the date-line so that the date-line
+  ;; is grouped with what follows.
+  (set (make-local-variable 'page-delimiter) "^\\<\\|^\f")
+  (set (make-local-variable 'version-control) 'never)
+  (set (make-local-variable 'adaptive-fill-regexp) "\\s *")
+  (set (make-local-variable 'font-lock-defaults)
+       '(change-log-font-lock-keywords t))
+  (run-hooks 'change-log-mode-hook))
+
+;; It might be nice to have a general feature to replace this.  The idea I
+;; have is a variable giving a regexp matching text which should not be
+;; moved from bol by filling.  change-log-mode would set this to "^\\s *\\s(".
+;; But I don't feel up to implementing that today.
+(defun change-log-fill-paragraph (&optional justify)
+  "Fill the paragraph, but preserve open parentheses at beginning of lines.
+Prefix arg means justify as well."
+  (interactive "P")
+  (let ((end (save-excursion (forward-paragraph) (point)))
+       (beg (save-excursion (backward-paragraph)(point)))
+       (paragraph-start (concat paragraph-start "\\|\\s *\\s(")))
+    (fill-region beg end justify)))
+\f
+(defvar add-log-current-defun-header-regexp
+  "^\\([A-Z][A-Z_ ]*[A-Z_]\\|[-_a-zA-Z]+\\)[ \t]*[:=]"
+  "*Heuristic regexp used by `add-log-current-defun' for unknown major modes.")
+
+;;;###autoload
+(defun add-log-current-defun ()
+  "Return name of function definition point is in, or nil.
+
+Understands C, Lisp, LaTeX (\"functions\" are chapters, sections, ...),
+Texinfo (@node titles), Perl, and Fortran.
+
+Other modes are handled by a heuristic that looks in the 10K before
+point for uppercase headings starting in the first column or
+identifiers followed by `:' or `=', see variable
+`add-log-current-defun-header-regexp'.
+
+Has a preference of looking backwards."
+  (condition-case nil
+      (save-excursion
+       (let ((location (point)))
+         (cond ((memq major-mode '(emacs-lisp-mode lisp-mode scheme-mode
+                                                   lisp-interaction-mode))
+                ;; If we are now precisely at the beginning of a defun,
+                ;; make sure beginning-of-defun finds that one
+                ;; rather than the previous one.
+                (or (eobp) (forward-char 1))
+                (beginning-of-defun)
+                ;; Make sure we are really inside the defun found, not after it.
+                (if (and (looking-at "\\s(")
+                         (progn (end-of-defun)
+                                (< location (point)))
+                         (progn (forward-sexp -1)
+                                (>= location (point))))
+                    (progn
+                      (if (looking-at "\\s(")
+                          (forward-char 1))
+                      (forward-sexp 1)
+                      (skip-chars-forward " '")
+                      (buffer-substring (point)
+                                        (progn (forward-sexp 1) (point))))))
+               ((and (memq major-mode '(c-mode c++-mode c++-c-mode objc-mode))
+                     (save-excursion (beginning-of-line)
+                                     ;; Use eq instead of = here to avoid
+                                     ;; error when at bob and char-after
+                                     ;; returns nil.
+                                     (while (eq (char-after (- (point) 2)) ?\\)
+                                       (forward-line -1))
+                                     (looking-at "[ \t]*#[ \t]*define[ \t]")))
+                ;; Handle a C macro definition.
+                (beginning-of-line)
+                (while (eq (char-after (- (point) 2)) ?\\) ;not =; note above
+                  (forward-line -1))
+                (search-forward "define")
+                (skip-chars-forward " \t")
+                (buffer-substring (point)
+                                  (progn (forward-sexp 1) (point))))
+               ((memq major-mode '(c-mode c++-mode c++-c-mode objc-mode))
+                (beginning-of-line)
+                ;; See if we are in the beginning part of a function,
+                ;; before the open brace.  If so, advance forward.
+                (while (not (looking-at "{\\|\\(\\s *$\\)"))
+                  (forward-line 1))
+                (or (eobp)
+                    (forward-char 1))
+                (beginning-of-defun)
+                (if (progn (end-of-defun)
+                           (< location (point)))
+                    (progn
+                      (backward-sexp 1)
+                      (let (beg tem)
+
+                        (forward-line -1)
+                        ;; Skip back over typedefs of arglist.
+                        (while (and (not (bobp))
+                                    (looking-at "[ \t\n]"))
+                          (forward-line -1))
+                        ;; See if this is using the DEFUN macro used in Emacs,
+                        ;; or the DEFUN macro used by the C library.
+                        (if (condition-case nil
+                                (and (save-excursion
+                                       (end-of-line)
+                                       (while (= (preceding-char) ?\\)
+                                         (end-of-line 2))
+                                       (backward-sexp 1)
+                                       (beginning-of-line)
+                                       (setq tem (point))
+                                       (looking-at "DEFUN\\b"))
+                                     (>= location tem))
+                              (error nil))
+                            (progn
+                              (goto-char tem)
+                              (down-list 1)
+                              (if (= (char-after (point)) ?\")
+                                  (progn
+                                    (forward-sexp 1)
+                                    (skip-chars-forward " ,")))
+                              (buffer-substring (point)
+                                                (progn (forward-sexp 1) (point))))
+                           (if (looking-at "^[+-]")
+                               (get-method-definition)
+                             ;; Ordinary C function syntax.
+                             (setq beg (point))
+                             (if (and (condition-case nil
+                                         ;; Protect against "Unbalanced parens" error.
+                                         (progn
+                                           (down-list 1) ; into arglist
+                                           (backward-up-list 1)
+                                           (skip-chars-backward " \t")
+                                           t)
+                                       (error nil))
+                                     ;; Verify initial pos was after
+                                     ;; real start of function.
+                                     (save-excursion
+                                       (goto-char beg)
+                                       ;; For this purpose, include the line
+                                       ;; that has the decl keywords.  This
+                                       ;; may also include some of the
+                                       ;; comments before the function.
+                                       (while (and (not (bobp))
+                                                   (save-excursion
+                                                     (forward-line -1)
+                                                     (looking-at "[^\n\f]")))
+                                         (forward-line -1))
+                                       (>= location (point)))
+                                          ;; Consistency check: going down and up
+                                          ;; shouldn't take us back before BEG.
+                                          (> (point) beg))
+                                (let (end middle)
+                                  ;; Don't include any final newline
+                                  ;; in the name we use.
+                                  (if (= (preceding-char) ?\n)
+                                      (forward-char -1))
+                                  (setq end (point))
+                                  (backward-sexp 1)
+                                  ;; Now find the right beginning of the name.
+                                  ;; Include certain keywords if they
+                                  ;; precede the name.
+                                  (setq middle (point))
+                                  (forward-word -1)
+                                  ;; Ignore these subparts of a class decl
+                                  ;; and move back to the class name itself.
+                                  (while (looking-at "public \\|private ")
+                                    (skip-chars-backward " \t:")
+                                    (setq end (point))
+                                    (backward-sexp 1)
+                                    (setq middle (point))
+                                    (forward-word -1))
+                                  (and (bolp)
+                                       (looking-at "struct \\|union \\|class ")
+                                       (setq middle (point)))
+                                  (buffer-substring middle end)))))))))
+               ((memq major-mode
+                      '(TeX-mode plain-TeX-mode LaTeX-mode;; tex-mode.el
+                                 plain-tex-mode latex-mode;; cmutex.el
+                                 ))
+                (if (re-search-backward
+                     "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)" nil t)
+                    (progn
+                      (goto-char (match-beginning 0))
+                      (buffer-substring (1+ (point));; without initial backslash
+                                        (progn
+                                          (end-of-line)
+                                          (point))))))
+               ((eq major-mode 'texinfo-mode)
+                (if (re-search-backward "^@node[ \t]+\\([^,\n]+\\)" nil t)
+                    (buffer-substring (match-beginning 1)
+                                      (match-end 1))))
+               ((eq major-mode 'perl-mode)
+                (if (re-search-backward "^sub[ \t]+\\([^ \t\n]+\\)" nil t)
+                    (buffer-substring (match-beginning 1)
+                                      (match-end 1))))
+                ((eq major-mode 'fortran-mode)
+                 ;; must be inside function body for this to work
+                 (beginning-of-fortran-subprogram)
+                 (let ((case-fold-search t)) ; case-insensitive
+                   ;; search for fortran subprogram start
+                   (if (re-search-forward
+                        "^[ \t]*\\(program\\|subroutine\\|function\
+\\|[ \ta-z0-9*]*[ \t]+function\\)"
+                        nil t)
+                       (progn
+                         ;; move to EOL or before first left paren
+                         (if (re-search-forward "[(\n]" nil t)
+                            (progn (forward-char -1)
+                                   (skip-chars-backward " \t"))
+                          (end-of-line))
+                        ;; Use the name preceding that.
+                         (buffer-substring (point)
+                                           (progn (forward-sexp -1)
+                                                  (point)))))))
+               (t
+                ;; If all else fails, try heuristics
+                (let (case-fold-search)
+                  (end-of-line)
+                  (if (re-search-backward add-log-current-defun-header-regexp
+                                          (- (point) 10000)
+                                          t)
+                      (buffer-substring (match-beginning 1)
+                                        (match-end 1))))))))
+    (error nil)))
+
+(defvar get-method-definition-md)
+
+;; Subroutine used within get-method-definition.
+;; Add the last match in the buffer to the end of `md',
+;; followed by the string END; move to the end of that match.
+(defun get-method-definition-1 (end)
+  (setq get-method-definition-md
+       (concat get-method-definition-md 
+               (buffer-substring (match-beginning 1) (match-end 1))
+               end))
+  (goto-char (match-end 0)))
+
+;; For objective C, return the method name if we are in a method.
+(defun get-method-definition ()
+  (let ((get-method-definition-md "["))
+    (save-excursion
+      (if (re-search-backward "^@implementation\\s-*\\([A-Za-z_]*\\)" nil t)
+         (get-method-definition-1 " ")))
+    (save-excursion
+      (cond
+       ((re-search-forward "^\\([-+]\\)[ \t\n\f\r]*\\(([^)]*)\\)?\\s-*" nil t)
+       (get-method-definition-1 "")
+       (while (not (looking-at "[{;]"))
+         (looking-at
+          "\\([A-Za-z_]*:?\\)\\s-*\\(([^)]*)\\)?[A-Za-z_]*[ \t\n\f\r]*")
+         (get-method-definition-1 ""))
+       (concat get-method-definition-md "]"))))))
+
+
+(provide 'add-log)
+
+;;; add-log.el ends here
diff --git a/etc/add-log.vi b/etc/add-log.vi
new file mode 100644 (file)
index 0000000..efb8c77
--- /dev/null
@@ -0,0 +1,11 @@
+Here is a vi macro to create entries in the recommended format for
+GDB's ChangeLogs.
+
+map \18 1GO\e:r !date '+\%Y-\%m-\%d'\e2GA  Jason Molenda  (\e:r !whoami\ekJxA@\e:r !hostname\eA)\ekJxkddjO\r     * \r\ek$
+
+It contains control and escape sequences, so don't just cut and paste it.
+You'll need to change the "Jason Molenda" bit, of course. :-)  Put this
+in your $HOME/.exrc and when you type control-X in move-around-mode,
+you'll have a changelog template inserted.
+
+--- Jason Molenda
diff --git a/etc/configbuild.ein b/etc/configbuild.ein
new file mode 100644 (file)
index 0000000..7a0e214
--- /dev/null
@@ -0,0 +1,149 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: configbuild.fig
+%%Creator: fig2dev Version 3.1 Patchlevel 1
+%%CreationDate: Fri Jun 12 20:13:16 1998
+%%For: ian@tito.cygnus.com (Ian Lance Taylor)
+%%Orientation: Portrait
+%%BoundingBox: 0 0 322 173
+%%Pages: 0
+%%BeginSetup
+%%IncludeFeature: *PageSize Letter
+%%EndSetup
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {} def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+-62.0 226.0 translate
+1 -1 scale
+
+/clp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+  bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+  4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+%%EndProlog
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+7.500 slw
+% Polyline
+n 1050 900 m 2100 900 l  2100 1425 l  1050 1425 l  clp  gs col-1 s gr 
+% Polyline
+n 1500 1425 m 1500 2100 l  gs col-1 s gr 
+n 1530.00 1980.00 m 1500.00 2100.00 l 1470.00 1980.00 l  1500.50 1980.50 l 1530.00 1980.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 1500 2625 m 1500 3300 l  gs col-1 s gr 
+n 1530.00 3180.00 m 1500.00 3300.00 l 1470.00 3180.00 l  1500.50 3180.50 l 1530.00 3180.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 2925 900 m 3825 900 l  3825 1425 l  2925 1425 l  clp  gs col-1 s gr 
+% Polyline
+n 1155 2100 m 1050 2100 1050 2520 105 arcto 4 {pop} repeat 1050 2625 2220 2625 105 arcto 4 {pop} repeat 2325 2625 2325 2205 105 arcto 4 {pop} repeat 2325 2100 1155 2100 105 arcto 4 {pop} repeat clp  gs col-1 s gr 
+% Polyline
+n 2850 2100 m 4125 2100 l  4125 2625 l  2850 2625 l  clp  gs col-1 s gr 
+% Polyline
+n 3375 1425 m 3375 2100 l  gs col-1 s gr 
+n 3405.00 1980.00 m 3375.00 2100.00 l 3345.00 1980.00 l  3375.50 1980.50 l 3405.00 1980.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 5100 900 m 6300 900 l  6300 1350 l  5100 1350 l  clp  gs col-1 s gr 
+% Polyline
+n 5625 1350 m 5625 2100 l  gs col-1 s gr 
+n 5655.00 1980.00 m 5625.00 2100.00 l 5595.00 1980.00 l  5625.50 1980.50 l 5655.00 1980.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 5205 2100 m 5100 2100 5100 2520 105 arcto 4 {pop} repeat 5100 2625 6270 2625 105 arcto 4 {pop} repeat 6375 2625 6375 2205 105 arcto 4 {pop} repeat 6375 2100 5205 2100 105 arcto 4 {pop} repeat clp  gs col-1 s gr 
+% Polyline
+n 5625 2625 m 5625 3300 l  gs col-1 s gr 
+n 5655.00 3180.00 m 5625.00 3300.00 l 5595.00 3180.00 l  5625.50 3180.50 l 5655.00 3180.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 5100 3300 m 6225 3300 l  6225 3750 l  5100 3750 l  clp  gs col-1 s gr 
+% Polyline
+       [1 50.0] 50.000000 setdash
+n 2850 2400 m 2325 2400 l  gs col-1 s gr       [] 0 setdash
+n 2445.00 2430.00 m 2325.00 2400.00 l 2445.00 2370.00 l  2445.50 2400.50 l 2445.00 2430.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+       [1 50.0] 50.000000 setdash
+n 4125 2400 m 5100 2400 l  gs col-1 s gr       [] 0 setdash
+n 4980.00 2370.00 m 5100.00 2400.00 l 4980.00 2430.00 l  4980.50 2400.50 l 4980.00 2370.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 1050 3300 m 1950 3300 l  1950 3750 l  1050 3750 l  clp  gs col-1 s gr 
+/Times-Roman findfont 180.00 scalefont setfont
+1200 1200 m
+gs 1 -1 sc (config.in) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+3000 1200 m
+gs 1 -1 sc (configure) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+3000 2400 m
+gs 1 -1 sc (config.status) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+1200 2400 m
+gs 1 -1 sc (config.status) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+1200 3600 m
+gs 1 -1 sc (config.h) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+5250 1200 m
+gs 1 -1 sc (Makefile.in) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+5250 2400 m
+gs 1 -1 sc (config.status) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+5250 3600 m
+gs 1 -1 sc (Makefile) col-1 show gr
+$F2psEnd
+restore
diff --git a/etc/configbuild.fig b/etc/configbuild.fig
new file mode 100644 (file)
index 0000000..747592d
--- /dev/null
@@ -0,0 +1,50 @@
+#FIG 3.1
+Portrait
+Center
+Inches
+1200 2
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        1050 900 2100 900 2100 1425 1050 1425 1050 900
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        1500 1425 1500 2100
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        1500 2625 1500 3300
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        2925 900 3825 900 3825 1425 2925 1425 2925 900
+2 4 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 5
+        2325 2625 2325 2100 1050 2100 1050 2625 2325 2625
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        2850 2100 4125 2100 4125 2625 2850 2625 2850 2100
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        3375 1425 3375 2100
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        5100 900 6300 900 6300 1350 5100 1350 5100 900
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        5625 1350 5625 2100
+2 4 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 5
+        6375 2625 6375 2100 5100 2100 5100 2625 6375 2625
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        5625 2625 5625 3300
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        5100 3300 6225 3300 6225 3750 5100 3750 5100 3300
+2 1 2 1 -1 7 0 0 -1 3.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        2850 2400 2325 2400
+2 1 2 1 -1 7 0 0 -1 3.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        4125 2400 5100 2400
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        1050 3300 1950 3300 1950 3750 1050 3750 1050 3300
+4 0 -1 0 0 0 12 0.0000000 4 180 645 1200 1200 config.in\001
+4 0 -1 0 0 0 12 0.0000000 4 180 705 3000 1200 configure\001
+4 0 -1 0 0 0 12 0.0000000 4 180 990 3000 2400 config.status\001
+4 0 -1 0 0 0 12 0.0000000 4 180 990 1200 2400 config.status\001
+4 0 -1 0 0 0 12 0.0000000 4 180 600 1200 3600 config.h\001
+4 0 -1 0 0 0 12 0.0000000 4 135 855 5250 1200 Makefile.in\001
+4 0 -1 0 0 0 12 0.0000000 4 180 990 5250 2400 config.status\001
+4 0 -1 0 0 0 12 0.0000000 4 135 675 5250 3600 Makefile\001
diff --git a/etc/configbuild.jin b/etc/configbuild.jin
new file mode 100644 (file)
index 0000000..44cd939
Binary files /dev/null and b/etc/configbuild.jin differ
diff --git a/etc/configbuild.tin b/etc/configbuild.tin
new file mode 100644 (file)
index 0000000..cfdd6fe
--- /dev/null
@@ -0,0 +1,9 @@
+   config.in        *configure*      Makefile.in
+      |                  |               |
+      |                  v               |
+      |             config.status        |
+      |                  |               |
+   *config.status*<======+==========>*config.status*
+      |                                  |
+      v                                  v
+   config.h                          Makefile
diff --git a/etc/configdev.ein b/etc/configdev.ein
new file mode 100644 (file)
index 0000000..7f83785
--- /dev/null
@@ -0,0 +1,185 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: configdev.fig
+%%Creator: fig2dev Version 3.1 Patchlevel 1
+%%CreationDate: Mon Jun 15 17:35:19 1998
+%%For: ian@tito.cygnus.com (Ian Lance Taylor)
+%%Orientation: Portrait
+%%BoundingBox: 0 0 344 317
+%%Pages: 0
+%%BeginSetup
+%%IncludeFeature: *PageSize Letter
+%%EndSetup
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {} def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+-62.0 370.0 translate
+1 -1 scale
+
+/clp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+  bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+  4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+%%EndProlog
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+7.500 slw
+% Polyline
+n 1050 900 m 2100 900 l  2100 1425 l  1050 1425 l  clp  gs col-1 s gr 
+% Polyline
+n 2925 900 m 3975 900 l  3975 1425 l  2925 1425 l  clp  gs col-1 s gr 
+% Polyline
+n 5550 900 m 6750 900 l  6750 1350 l  5550 1350 l  clp  gs col-1 s gr 
+% Polyline
+n 3750 1800 m 5025 1800 l  5025 2250 l  3750 2250 l  clp  gs col-1 s gr 
+% Polyline
+n 1155 2100 m 1050 2100 1050 2520 105 arcto 4 {pop} repeat 1050 2625 2070 2625 105 arcto 4 {pop} repeat 2175 2625 2175 2205 105 arcto 4 {pop} repeat 2175 2100 1155 2100 105 arcto 4 {pop} repeat clp  gs col-1 s gr 
+% Polyline
+n 5550 3300 m 6675 3300 l  6675 3750 l  5550 3750 l  clp  gs col-1 s gr 
+% Polyline
+n 5655 2100 m 5550 2100 5550 2520 105 arcto 4 {pop} repeat 5550 2625 6495 2625 105 arcto 4 {pop} repeat 6600 2625 6600 2205 105 arcto 4 {pop} repeat 6600 2100 5655 2100 105 arcto 4 {pop} repeat clp  gs col-1 s gr 
+% Polyline
+n 3750 3600 m 4875 3600 l  4875 4050 l  3750 4050 l  clp  gs col-1 s gr 
+% Polyline
+n 3855 2700 m 3750 2700 3750 3045 105 arcto 4 {pop} repeat 3750 3150 4545 3150 105 arcto 4 {pop} repeat 4650 3150 4650 2805 105 arcto 4 {pop} repeat 4650 2700 3855 2700 105 arcto 4 {pop} repeat clp  gs col-1 s gr 
+% Polyline
+n 2850 5700 m 3750 5700 l  3750 6150 l  2850 6150 l  clp  gs col-1 s gr 
+% Polyline
+n 3030 4800 m 2925 4800 2925 5145 105 arcto 4 {pop} repeat 2925 5250 3645 5250 105 arcto 4 {pop} repeat 3750 5250 3750 4905 105 arcto 4 {pop} repeat 3750 4800 3030 4800 105 arcto 4 {pop} repeat clp  gs col-1 s gr 
+% Polyline
+n 1500 1425 m 1500 2100 l  gs col-1 s gr 
+n 1530.00 1980.00 m 1500.00 2100.00 l 1470.00 1980.00 l  1500.50 1980.50 l 1530.00 1980.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 3300 1425 m 3300 4800 l  gs col-1 s gr 
+n 3330.00 4680.00 m 3300.00 4800.00 l 3270.00 4680.00 l  3300.50 4680.50 l 3330.00 4680.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 3300 1575 m 1875 1575 l  1875 2100 l  gs col-1 s gr 
+n 1905.00 1980.00 m 1875.00 2100.00 l 1845.00 1980.00 l  1875.50 1980.50 l 1905.00 1980.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 3300 1575 m 5700 1575 l  5700 2100 l  gs col-1 s gr 
+n 5730.00 1980.00 m 5700.00 2100.00 l 5670.00 1980.00 l  5700.50 1980.50 l 5730.00 1980.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 6225 1350 m 6225 2100 l  gs col-1 s gr 
+n 6255.00 1980.00 m 6225.00 2100.00 l 6195.00 1980.00 l  6225.50 1980.50 l 6255.00 1980.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 6075 2625 m 6075 3300 l  gs col-1 s gr 
+n 6105.00 3180.00 m 6075.00 3300.00 l 6045.00 3180.00 l  6075.50 3180.50 l 6105.00 3180.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 4200 2250 m 4200 2700 l  gs col-1 s gr 
+n 4230.00 2580.00 m 4200.00 2700.00 l 4170.00 2580.00 l  4200.50 2580.50 l 4230.00 2580.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 4200 3150 m 4200 3600 l  gs col-1 s gr 
+n 4230.00 3480.00 m 4200.00 3600.00 l 4170.00 3480.00 l  4200.50 3480.50 l 4230.00 3480.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 4200 4050 m 4200 4500 l  3675 4500 l  3675 4800 l  gs col-1 s gr 
+n 3705.00 4680.00 m 3675.00 4800.00 l 3645.00 4680.00 l  3675.50 4680.50 l 3705.00 4680.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 3375 5250 m 3375 5700 l  gs col-1 s gr 
+n 3405.00 5580.00 m 3375.00 5700.00 l 3345.00 5580.00 l  3375.50 5580.50 l 3405.00 5580.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 3300 2925 m 3750 2925 l  gs col-1 s gr 
+n 3630.00 2895.00 m 3750.00 2925.00 l 3630.00 2955.00 l  3630.50 2925.50 l 3630.00 2895.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 1500 2625 m 1500 3300 l  gs col-1 s gr 
+n 1530.00 3180.00 m 1500.00 3300.00 l 1470.00 3180.00 l  1500.50 3180.50 l 1530.00 3180.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+% Polyline
+n 1050 3300 m 2100 3300 l  2100 3750 l  1050 3750 l  clp  gs col-1 s gr 
+% Polyline
+n 4875 3825 m 5250 3825 l  5250 2400 l  5550 2400 l  gs col-1 s gr 
+n 5430.00 2370.00 m 5550.00 2400.00 l 5430.00 2430.00 l  5430.50 2400.50 l 5430.00 2370.00 l clp gs 0.00 setgray ef gr gs col-1 s gr
+/Times-Roman findfont 180.00 scalefont setfont
+1200 1200 m
+gs 1 -1 sc (acconfig.h) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+3000 1200 m
+gs 1 -1 sc (configure.in) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+5700 1200 m
+gs 1 -1 sc (Makefile.am) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+3900 2100 m
+gs 1 -1 sc (acinclude.m4) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+1200 2400 m
+gs 1 -1 sc (autoheader) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+1200 3600 m
+gs 1 -1 sc (config.in) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+5700 3600 m
+gs 1 -1 sc (Makefile.in) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+5700 2400 m
+gs 1 -1 sc (automake) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+3900 3900 m
+gs 1 -1 sc (aclocal.m4) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+3900 3000 m
+gs 1 -1 sc (aclocal) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+3000 6000 m
+gs 1 -1 sc (configure) col-1 show gr
+/Times-Roman findfont 180.00 scalefont setfont
+3000 5100 m
+gs 1 -1 sc (autoconf) col-1 show gr
+$F2psEnd
+restore
diff --git a/etc/configdev.fig b/etc/configdev.fig
new file mode 100644 (file)
index 0000000..4d386ec
--- /dev/null
@@ -0,0 +1,80 @@
+#FIG 3.1
+Portrait
+Center
+Inches
+1200 2
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        1050 900 2100 900 2100 1425 1050 1425 1050 900
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        2925 900 3975 900 3975 1425 2925 1425 2925 900
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        5550 900 6750 900 6750 1350 5550 1350 5550 900
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        3750 1800 5025 1800 5025 2250 3750 2250 3750 1800
+2 4 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 5
+        2175 2625 2175 2100 1050 2100 1050 2625 2175 2625
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        5550 3300 6675 3300 6675 3750 5550 3750 5550 3300
+2 4 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 5
+        6600 2625 6600 2100 5550 2100 5550 2625 6600 2625
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        3750 3600 4875 3600 4875 4050 3750 4050 3750 3600
+2 4 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 5
+        4650 3150 4650 2700 3750 2700 3750 3150 4650 3150
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        2850 5700 3750 5700 3750 6150 2850 6150 2850 5700
+2 4 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 5
+        3750 5250 3750 4800 2925 4800 2925 5250 3750 5250
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        1500 1425 1500 2100
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        3300 1425 3300 4800
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 3
+       1 1 1.00 60.00 120.00
+        3300 1575 1875 1575 1875 2100
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 3
+       1 1 1.00 60.00 120.00
+        3300 1575 5700 1575 5700 2100
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        6225 1350 6225 2100
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        6075 2625 6075 3300
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        4200 2250 4200 2700
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        4200 3150 4200 3600
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 4
+       1 1 1.00 60.00 120.00
+        4200 4050 4200 4500 3675 4500 3675 4800
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        3375 5250 3375 5700
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        3300 2925 3750 2925
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        1500 2625 1500 3300
+2 2 0 1 -1 7 0 0 -1 0.000 0 0 0 0 0 5
+        1050 3300 2100 3300 2100 3750 1050 3750 1050 3300
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 4
+       1 1 1.00 60.00 120.00
+        4875 3825 5250 3825 5250 2400 5550 2400
+4 0 -1 0 0 0 12 0.0000000 4 180 780 1200 1200 acconfig.h\001
+4 0 -1 0 0 0 12 0.0000000 4 180 885 3000 1200 configure.in\001
+4 0 -1 0 0 0 12 0.0000000 4 135 945 5700 1200 Makefile.am\001
+4 0 -1 0 0 0 12 0.0000000 4 135 990 3900 2100 acinclude.m4\001
+4 0 -1 0 0 0 12 0.0000000 4 135 840 1200 2400 autoheader\001
+4 0 -1 0 0 0 12 0.0000000 4 180 645 1200 3600 config.in\001
+4 0 -1 0 0 0 12 0.0000000 4 135 855 5700 3600 Makefile.in\001
+4 0 -1 0 0 0 12 0.0000000 4 135 735 5700 2400 automake\001
+4 0 -1 0 0 0 12 0.0000000 4 135 810 3900 3900 aclocal.m4\001
+4 0 -1 0 0 0 12 0.0000000 4 135 540 3900 3000 aclocal\001
+4 0 -1 0 0 0 12 0.0000000 4 180 705 3000 6000 configure\001
+4 0 -1 0 0 0 12 0.0000000 4 135 660 3000 5100 autoconf\001
diff --git a/etc/configdev.jin b/etc/configdev.jin
new file mode 100644 (file)
index 0000000..9b11a71
Binary files /dev/null and b/etc/configdev.jin differ
diff --git a/etc/configdev.tin b/etc/configdev.tin
new file mode 100644 (file)
index 0000000..c9b6f34
--- /dev/null
@@ -0,0 +1,17 @@
+   acconfig.h       configure.in                 Makefile.am
+       |                |                           |
+       |  --------------+----------------------     |
+       |  |             |                     |     |
+       v  v             |    acinclude.m4     |     |
+   *autoheader*         |         |           v     v
+       |                |         v      --->*automake* 
+       v                |--->*aclocal*   |       |      
+   config.in            |         |      |       v      
+                        |         v      |   Makefile.in
+                        |    aclocal.m4---
+                        |     |
+                        v     v
+                       *autoconf*
+                           |
+                           v
+                       configure
diff --git a/etc/configure b/etc/configure
new file mode 100755 (executable)
index 0000000..101fcef
--- /dev/null
@@ -0,0 +1,862 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.1 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.12.1"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=Makefile.in
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:555: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set) 2>&1 | grep ac_space` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[    `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.12.1"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/etc/configure.in b/etc/configure.in
new file mode 100644 (file)
index 0000000..b785068
--- /dev/null
@@ -0,0 +1,7 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.5)
+AC_INIT(Makefile.in)
+
+AC_PROG_INSTALL
+
+AC_OUTPUT(Makefile)
diff --git a/etc/configure.texi b/etc/configure.texi
new file mode 100644 (file)
index 0000000..9140167
--- /dev/null
@@ -0,0 +1,2644 @@
+\input texinfo
+@c %**start of header
+@setfilename configure.info
+@settitle The GNU configure and build system
+@setchapternewpage off
+@c %**end of header
+
+@dircategory GNU admin
+@direntry
+* configure: (configure).      The GNU configure and build system
+@end direntry
+
+@ifinfo
+This file documents the GNU configure and build system.
+
+Copyright (C) 1998 Cygnus Solutions.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@titlepage
+@title The GNU configure and build system
+@author Ian Lance Taylor
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1998 Cygnus Solutions
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
+@end titlepage
+
+@ifinfo
+@node Top
+@top GNU configure and build system
+
+The GNU configure and build system.
+
+@menu
+* Introduction::               Introduction.
+* Getting Started::            Getting Started.
+* Files::                      Files.
+* Configuration Names::                Configuration Names.
+* Cross Compilation Tools::    Cross Compilation Tools.
+* Canadian Cross::             Canadian Cross.
+* Cygnus Configure::           Cygnus Configure.
+* Multilibs::                  Multilibs.
+* FAQ::                                Frequently Asked Questions.
+* Index::                      Index.
+@end menu
+
+@end ifinfo
+
+@node Introduction
+@chapter Introduction
+
+This document describes the GNU configure and build systems.  It
+describes how autoconf, automake, libtool, and make fit together.  It
+also includes a discussion of the older Cygnus configure system.
+
+This document does not describe in detail how to use each of the tools;
+see the respective manuals for that.  Instead, it describes which files
+the developer must write, which files are machine generated and how they
+are generated, and where certain common problems should be addressed.
+
+@ifnothtml
+This document draws on several sources, including the autoconf manual by
+David MacKenzie (@pxref{Top, , autoconf overview, autoconf, Autoconf}),
+the automake manual by David MacKenzie and Tom Tromey (@pxref{Top, ,
+automake overview, automake, GNU Automake}), the libtool manual by
+Gordon Matzigkeit (@pxref{Top, , libtool overview, libtool, GNU
+libtool}), and the Cygnus configure manual by K. Richard Pixley.
+@end ifnothtml
+@ifhtml
+This document draws on several sources, including
+@uref{http://www.delorie.com/gnu/docs/autoconf/autoconf_toc.html, the
+autoconf manual} by David MacKenzie,
+@uref{http://www.delorie.com/gnu/docs/automake/automake_toc.html, the
+automake manual} by David MacKenzie and Tom Tromey,
+@uref{http://www.delorie.com/gnu/docs/libtool/libtool_toc.html, the
+libtool manual} by Gordon Matzigkeit, and the Cygnus configure manual by
+K. Richard Pixley.
+@end ifhtml
+
+@menu
+* Goals::                      Goals.
+* Tools::                      The tools.
+* History::                    History.
+* Building::                   Building.
+@end menu
+
+@node Goals
+@section Goals
+@cindex goals
+
+The GNU configure and build system has two main goals.
+
+The first is to simplify the development of portable programs.  The
+system permits the developer to concentrate on writing the program,
+simplifying many details of portability across Unix and even Windows
+systems, and permitting the developer to describe how to build the
+program using simple rules rather than complex Makefiles.
+
+The second is to simplify the building of programs distributed as source
+code.  All programs are built using a simple, standardized, two step
+process.  The program builder need not install any special tools in
+order to build the program.
+
+@node Tools
+@section Tools
+
+The GNU configure and build system is comprised of several different
+tools.  Program developers must build and install all of these tools.
+
+People who just want to build programs from distributed sources normally
+do not need any special tools beyond a Unix shell, a make program, and a
+C compiler.
+
+@table @asis
+@item autoconf
+provides a general portability framework, based on testing the features
+of the host system at build time.
+@item automake
+a system for describing how to build a program, permitting the developer
+to write a simplified @file{Makefile}.
+@item libtool
+a standardized approach to building shared libraries.
+@item gettext
+provides a framework for translation of text messages into other
+languages; not really discussed in this document.
+@item m4
+autoconf requires the GNU version of m4; the standard Unix m4 does not
+suffice.
+@item perl
+automake requires perl.
+@end table
+
+@node History
+@section History
+@cindex history
+
+This is a very brief and probably inaccurate history.
+
+As the number of Unix variants increased during the 1980s, it became
+harder to write programs which could run on all variants.  While it was
+often possible to use @code{#ifdef} to identify particular systems,
+developers frequently did not have access to every system, and the
+characteristics of some systems changed from version to version.
+
+By 1992, at least three different approaches had been developed:
+@itemize @bullet
+@item
+The Metaconfig program, by Larry Wall, Harlan Stenn, and Raphael
+Manfredi.
+@item
+The Cygnus configure script, by K. Richard Pixley, and the gcc configure
+script, by Richard Stallman.  These use essentially the same approach,
+and the developers communicated regularly.
+@item
+The autoconf program, by David MacKenzie.
+@end itemize
+
+The Metaconfig program is still used for Perl and a few other programs.
+It is part of the Dist package.  I do not know if it is being developed.
+
+In 1994, David MacKenzie and others modified autoconf to incorporate all
+the features of Cygnus configure.  Since then, there has been a slow but
+steady conversion of GNU programs from Cygnus configure to autoconf. gcc
+has been converted, eliminating the gcc configure script.
+
+GNU autoconf was regularly maintained until late 1996.  As of this
+writing in June, 1998, it has no public maintainer.
+
+Most programs are built using the make program, which requires the
+developer to write Makefiles describing how to build the programs.
+Since most programs are built in pretty much the same way, this led to a
+lot of duplication.
+
+The X Window system is built using the imake tool, which uses a database
+of rules to eliminate the duplication.  However, building a tool which
+was developed using imake requires that the builder have imake
+installed, violating one of the goals of the GNU system.
+
+The new BSD make provides a standard library of Makefile fragments,
+which permits developers to write very simple Makefiles.  However, this
+requires that the builder install the new BSD make program.
+
+In 1994, David MacKenzie wrote the first version of automake, which
+permitted writing a simple build description which was converted into a
+Makefile which could be used by the standard make program.  In 1995, Tom
+Tromey completely rewrote automake in Perl, and he continues to enhance
+it.
+
+Various free packages built libraries, and by around 1995 several
+included support to build shared libraries on various platforms.
+However, there was no consistent approach.  In early 1996, Gordon
+Matzigkeit began working on libtool, which provided a standardized
+approach to building shared libraries.  This was integrated into
+automake from the start.
+
+The development of automake and libtool was driven by the GNITS project,
+a group of GNU maintainers who designed standardized tools to help meet
+the GNU coding standards.
+
+@node Building
+@section Building
+
+Most readers of this document should already know how to build a tool by
+running @samp{configure} and @samp{make}.  This section may serve as a
+quick introduction or reminder.
+
+Building a tool is normally as simple as running @samp{configure}
+followed by @samp{make}.  You should normally run @samp{configure} from
+an empty directory, using some path to refer to the @samp{configure}
+script in the source directory.  The directory in which you run
+@samp{configure} is called the @dfn{object directory}.
+
+In order to use a object directory which is different from the source
+directory, you must be using the GNU version of @samp{make}, which has
+the required @samp{VPATH} support.  Despite this restriction, using a
+different object directory is highly recommended:
+@itemize @bullet
+@item
+It keeps the files generated during the build from cluttering up your
+sources.
+@item 
+It permits you to remove the built files by simply removing the entire
+build directory.
+@item
+It permits you to build from the same sources with several sets of
+configure options simultaneously.
+@end itemize
+
+If you don't have GNU @samp{make}, you will have to run @samp{configure}
+in the source directory.  All GNU packages should support this; in
+particular, GNU packages should not assume the presence of GNU
+@samp{make}.
+
+After running @samp{configure}, you can build the tools by running
+@samp{make}.
+
+To install the tools, run @samp{make install}.  Installing the tools
+will copy the programs and any required support files to the
+@dfn{installation directory}.  The location of the installation
+directory is controlled by @samp{configure} options, as described below.
+
+In the Cygnus tree at present, the info files are built and installed as
+a separate step.  To build them, run @samp{make info}.  To install them,
+run @samp{make install-info}.
+
+All @samp{configure} scripts support a wide variety of options.  The
+most interesting ones are @samp{--with} and @samp{--enable} options
+which are generally specific to particular tools.  You can usually use
+the @samp{--help} option to get a list of interesting options for a
+particular configure script.
+
+The only generic options you are likely to use are the @samp{--prefix}
+and @samp{--exec-prefix} options.  These options are used to specify the
+installation directory.
+
+The directory named by the @samp{--prefix} option will hold machine
+independent files such as info files.
+
+The directory named by the @samp{--exec-prefix} option, which is
+normally a subdirectory of the @samp{--prefix} directory, will hold
+machine dependent files such as executables.
+
+The default for @samp{--prefix} is @file{/usr/local}.  The default for
+@samp{--exec-prefix} is the value used for @samp{--prefix}.
+
+The convention used in Cygnus releases is to use a @samp{--prefix}
+option of @file{/usr/cygnus/@var{release}}, where @var{release} is the
+name of the release, and to use a @samp{--exec-prefix} option of
+@file{/usr/cygnus/@var{release}/H-@var{host}}, where @var{host} is the
+configuration name of the host system (@pxref{Configuration Names}).
+
+Do not use either the source or the object directory as the installation
+directory.  That will just lead to confusion.
+
+@node Getting Started
+@chapter Getting Started
+
+To start using the GNU configure and build system with your software
+package, you must write three files, and you must run some tools to
+manually generate additional files.
+
+@menu
+* Write configure.in::         Write configure.in.
+* Write Makefile.am::          Write Makefile.am.
+* Write acconfig.h::           Write acconfig.h.
+* Generate files::             Generate files.
+* Getting Started Example::    Example.
+@end menu
+
+@node Write configure.in
+@section Write configure.in
+@cindex @file{configure.in}, writing
+
+You must first write the file @file{configure.in}.  This is an autoconf
+input file, and the autoconf manual describes in detail what this file
+should look like.
+
+You will write tests in your @file{configure.in} file to check for
+conditions that may change from one system to another, such as the
+presence of particular header files or functions.
+
+For example, not all systems support the @samp{gettimeofday} function.
+If you want to use the @samp{gettimeofday} function when it is
+available, and to use some other function when it is not, you would
+check for this by putting @samp{AC_CHECK_FUNCS(gettimeofday)} in
+@file{configure.in}.
+
+When the configure script is run at build time, this will arrange to
+define the preprocessor macro @samp{HAVE_GETTIMEOFDAY} to the value 1 if
+the @samp{gettimeofday} function is available, and to not define the
+macro at all if the function is not available.  Your code can then use
+@samp{#ifdef} to test whether it is safe to call @samp{gettimeofday}.
+
+If you have an existing body of code, the @samp{autoscan} program may
+help identify potential portability problems, and hence configure tests
+that you will want to use.
+@ifnothtml
+@xref{Invoking autoscan, , , autoconf, the autoconf manual}.
+@end ifnothtml
+@ifhtml
+See @uref{http://www.delorie.com/gnu/docs/autoconf/autoconf_4.html, the
+autoscan documentation}.
+@end ifhtml
+
+Another handy tool for an existing body of code is @samp{ifnames}.  This
+will show you all the preprocessor conditionals that the code already
+uses.
+@ifnothtml
+@xref{Invoking ifnames, , , autoconf, the autoconf manual}.
+@end ifnothtml
+@ifhtml
+See @uref{http://www.delorie.com/gnu/docs/autoconf/autoconf_5.html, the
+ifnames documentation}.
+@end ifhtml
+
+Besides the portability tests which are specific to your particular
+package, every @file{configure.in} file should contain the following
+macros.
+
+@table @samp
+@item AC_INIT
+@cindex @samp{AC_INIT}
+This macro takes a single argument, which is the name of a file in your
+package.  For example, @samp{AC_INIT(foo.c)}.
+
+@item AC_PREREQ(@var{VERSION})
+@cindex @samp{AC_PREREQ}
+This macro is optional.  It may be used to indicate the version of
+@samp{autoconf} that you are using.  This will prevent users from
+running an earlier version of @samp{autoconf} and perhaps getting an
+invalid @file{configure} script.  For example, @samp{AC_PREREQ(2.12)}.
+
+@item AM_INIT_AUTOMAKE
+@cindex @samp{AM_INIT_AUTOMAKE}
+This macro takes two arguments: the name of the package, and a version
+number.  For example, @samp{AM_INIT_AUTOMAKE(foo, 1.0)}.  (This macro is
+not needed if you are not using automake).
+
+@item AM_CONFIG_HEADER
+@cindex @samp{AM_CONFIG_HEADER}
+This macro names the header file which will hold the preprocessor macro
+definitions at run time.  Normally this should be @file{config.h}.  Your
+sources would then use @samp{#include "config.h"} to include it.
+
+This macro may optionally name the input file for that header file; by
+default, this is @file{config.h.in}, but that file name works poorly on
+DOS filesystems.  Therefore, it is often better to name it explicitly as
+@file{config.in}.
+
+This is what you should normally put in @file{configure.in}:
+@example
+AM_CONFIG_HEADER(config.h:config.in)
+@end example
+
+@cindex @samp{AC_CONFIG_HEADER}
+(If you are not using automake, use @samp{AC_CONFIG_HEADER} rather than
+@samp{AM_CONFIG_HEADER}).
+
+@item AM_MAINTAINER_MODE
+@cindex @samp{AM_MAINTAINER_MODE}
+This macro always appears in Cygnus configure scripts.  Other programs
+may or may not use it.
+
+If this macro is used, the @samp{--enable-maintainer-mode} option is
+required to enable automatic rebuilding of generated files used by the
+configure system.  This of course requires that developers be aware of,
+and use, that option.
+
+If this macro is not used, then the generated files will always be
+rebuilt automatically.  This will cause problems if the wrong versions
+of autoconf, automake, or others are in the builder's @samp{PATH}.
+
+(If you are not using automake, you do not need to use this macro).
+
+@item AC_EXEEXT
+@cindex @samp{AC_EXEEXT}
+@cindex @samp{AM_EXEEXT}
+Either this macro or @samp{AM_EXEEXT} always appears in Cygnus configure
+files.  Other programs may or may not use one of them.
+
+This macro looks for the executable suffix used on the host system.  On
+Unix systems, this is the empty string.  On Windows systems, this is
+@samp{.exe}.  This macro directs automake to use the executable suffix
+as appropriate when creating programs.  This macro does not take any
+arguments.
+
+The @samp{AC_EXEEXT} form is new, and is part of a Cygnus patch to
+autoconf to support compiling with Visual C++.  Older programs use
+@samp{AM_EXEEXT} instead.
+
+(Programs which do not use automake use neither @samp{AC_EXEEXT} nor
+@samp{AM_EXEEXT}).
+
+@item AC_PROG_CC
+@cindex @samp{AC_PROG_CC}
+If you are writing C code, you will normally want to use this macro.  It
+locates the C compiler to use.  It does not take any arguments.
+
+However, if this @file{configure.in} file is for a library which is to
+be compiled by a cross compiler which may not fully work, then you will
+not want to use @samp{AC_PROG_CC}.  Instead, you will want to use a
+variant which does not call the macro @samp{AC_PROG_CC_WORKS}.  Examples
+can be found in various @file{configure.in} files for libraries that are
+compiled with cross compilers, such as libiberty or libgloss.  This is
+essentially a bug in autoconf, and there will probably be a better
+workaround at some point.
+
+@item AC_PROG_CXX
+@cindex @samp{AC_PROG_CXX}
+If you are writing C++ code, you will want to use this macro.  It
+locates the C++ compiler to use.  It does not take any arguments.  The
+same cross compiler comments apply as for @samp{AC_PROG_CC}.
+
+@item AM_PROG_LIBTOOL
+@cindex @samp{AM_PROG_LIBTOOL}
+If you want to build libraries, and you want to permit them to be
+shared, or you want to link against libraries which were built using
+libtool, then you will need this macro.  This macro is required in order
+to use libtool.
+
+@cindex @samp{AM_DISABLE_SHARED}
+By default, this will cause all libraries to be built as shared
+libraries.  To prevent this--to change the default--use
+@samp{AM_DISABLE_SHARED} before @samp{AM_PROG_LIBTOOL}.  The configure
+options @samp{--enable-shared} and @samp{--disable-shared} may be used
+to override the default at build time.
+
+@item AC_DEFINE(_GNU_SOURCE)
+@cindex @samp{_GNU_SOURCE}
+GNU packages should normally include this line before any other feature
+tests.  This defines the macro @samp{_GNU_SOURCE} when compiling, which
+directs the libc header files to provide the standard GNU system
+interfaces including all GNU extensions.  If this macro is not defined,
+certain GNU extensions may not be available.
+
+@item AC_OUTPUT
+@cindex @samp{AC_OUTPUT}
+This macro takes a list of file names which the configure process should
+produce.  This is normally a list of one or more @file{Makefile} files
+in different directories.  If your package lives entirely in a single
+directory, you would use simply @samp{AC_OUTPUT(Makefile)}.  If you also
+have, for example, a @file{lib} subdirectory, you would use
+@samp{AC_OUTPUT(Makefile lib/Makefile)}.
+@end table
+
+If you want to use locally defined macros in your @file{configure.in}
+file, then you will need to write a @file{acinclude.m4} file which
+defines them (if not using automake, this file is called
+@file{aclocal.m4}).  Alternatively, you can put separate macros in an
+@file{m4} subdirectory, and put @samp{ACLOCAL_AMFLAGS = -I m4} in your
+@file{Makefile.am} file so that the @samp{aclocal} program will be able
+to find them.
+
+The different macro prefixes indicate which tool defines the macro.
+Macros which start with @samp{AC_} are part of autoconf.  Macros which
+start with @samp{AM_} are provided by automake or libtool.
+
+@node Write Makefile.am
+@section Write Makefile.am
+@cindex @file{Makefile.am}, writing
+
+You must write the file @file{Makefile.am}.  This is an automake input
+file, and the automake manual describes in detail what this file should
+look like.
+
+The automake commands in @file{Makefile.am} mostly look like variable
+assignments in a @file{Makefile}.  automake recognizes special variable
+names, and automatically add make rules to the output as needed.
+
+There will be one @file{Makefile.am} file for each directory in your
+package.  For each directory with subdirectories, the @file{Makefile.am}
+file should contain the line
+@smallexample
+SUBDIRS = @var{dir} @var{dir} @dots{}
+@end smallexample
+@noindent
+where each @var{dir} is the name of a subdirectory.
+
+For each @file{Makefile.am}, there should be a corresponding
+@file{Makefile} in the @samp{AC_OUTPUT} macro in @file{configure.in}.
+
+Every @file{Makefile.am} written at Cygnus should contain the line
+@smallexample
+AUTOMAKE_OPTIONS = cygnus
+@end smallexample
+@noindent
+This puts automake into Cygnus mode.  See the automake manual for
+details.
+
+You may to include the version number of @samp{automake} that you are
+using on the @samp{AUTOMAKE_OPTIONS} line.  For example,
+@smallexample
+AUTOMAKE_OPTIONS = cygnus 1.3
+@end smallexample
+@noindent
+This will prevent users from running an earlier version of
+@samp{automake} and perhaps getting an invalid @file{Makefile.in}.
+
+If your package builds a program, then in the directory where that
+program is built you will normally want a line like
+@smallexample
+bin_PROGRAMS = @var{program}
+@end smallexample
+@noindent
+where @var{program} is the name of the program.  You will then want a
+line like
+@smallexample
+@var{program}_SOURCES = @var{file} @var{file} @dots{}
+@end smallexample
+@noindent
+where each @var{file} is the name of a source file to link into the
+program (e.g., @samp{foo.c}).
+
+If your package builds a library, and you do not want the library to
+ever be built as a shared library, then in the directory where that
+library is built you will normally want a line like
+@smallexample
+lib_LIBRARIES = lib@var{name}.a
+@end smallexample
+@noindent
+where @samp{lib@var{name}.a} is the name of the library.  You will then
+want a line like
+@smallexample
+lib@var{name}_a_SOURCES = @var{file} @var{file} @dots{}
+@end smallexample
+@noindent
+where each @var{file} is the name of a source file to add to the
+library.
+
+If your package builds a library, and you want to permit building the
+library as a shared library, then in the directory where that library is
+built you will normally want a line like
+@smallexample
+lib_LTLIBRARIES = lib@var{name}.la
+@end smallexample
+The use of @samp{LTLIBRARIES}, and the @samp{.la} extension, indicate a
+library to be built using libtool.  As usual, you will then want a line
+like
+@smallexample
+lib@var{name}_la_SOURCES = @var{file} @var{file} @dots{}
+@end smallexample
+
+The strings @samp{bin} and @samp{lib} that appear above in
+@samp{bin_PROGRAMS} and @samp{lib_LIBRARIES} are not arbitrary.  They
+refer to particular directories, which may be set by the @samp{--bindir}
+and @samp{--libdir} options to @file{configure}.  If those options are
+not used, the default values are based on the @samp{--prefix} or
+@samp{--exec-prefix} options to @file{configure}.  It is possible to use
+other names if the program or library should be installed in some other
+directory.
+
+The @file{Makefile.am} file may also contain almost anything that may
+appear in a normal @file{Makefile}.  automake also supports many other
+special variables, as well as conditionals.
+
+See the automake manual for more information.
+
+@node Write acconfig.h
+@section Write acconfig.h
+@cindex @file{acconfig.h}, writing
+
+If you are generating a portability header file, (i.e., you are using
+@samp{AM_CONFIG_HEADER} in @file{configure.in}), then you will have to
+write a @file{acconfig.h} file.  It will have to contain the following
+lines.
+
+@smallexample
+/* Name of package.  */
+#undef PACKAGE
+
+/* Version of package.  */
+#undef VERSION
+@end smallexample
+
+This requirement is really a bug in the system, and the requirement may
+be eliminated at some later date.
+
+The @file{acconfig.h} file will also similar comment and @samp{#undef}
+lines for any unusual macros in the @file{configure.in} file, including
+any macro which appears in a @samp{AC_DEFINE} macro.
+
+In particular, if you are writing a GNU package and therefore include
+@samp{AC_DEFINE(_GNU_SOURCE)} in @file{configure.in} as suggested above,
+you will need lines like this in @file{acconfig.h}:
+@smallexample
+/* Enable GNU extensions.  */
+#undef _GNU_SOURCE
+@end smallexample
+
+Normally the @samp{autoheader} program will inform you of any such
+requirements by printing an error message when it is run.  However, if
+you do anything particular odd in your @file{configure.in} file, you
+will have to make sure that the right entries appear in
+@file{acconfig.h}, since otherwise the results of the tests may not be
+available in the @file{config.h} file which your code will use.
+
+(Thee @samp{PACKAGE} and @samp{VERSION} lines are not required if you
+are not using automake, and in that case you may not need a
+@file{acconfig.h} file at all).
+
+@node Generate files
+@section Generate files
+
+Once you have written @file{configure.in}, @file{Makefile.am},
+@file{acconfig.h}, and possibly @file{acinclude.m4}, you must use
+autoconf and automake programs to produce the first versions of the
+generated files.  This is done by executing the following sequence of
+commands.
+
+@smallexample
+aclocal
+autoconf
+autoheader
+automake
+@end smallexample
+
+The @samp{aclocal} and @samp{automake} commands are part of the automake
+package, and the @samp{autoconf} and @samp{autoheader} commands are part
+of the autoconf package.
+
+If you are using a @file{m4} subdirectory for your macros, you will need
+to use the @samp{-I m4} option when you run @samp{aclocal}.
+
+If you are not using the Cygnus tree, use the @samp{-a} option when
+running @samp{automake} command in order to copy the required support
+files into your source directory.
+
+If you are using libtool, you must build and install the libtool package
+with the same @samp{--prefix} and @samp{--exec-prefix} options as you
+used with the autoconf and automake packages.  You must do this before
+running any of the above commands.  If you are not using the Cygnus
+tree, you will need to run the @samp{libtoolize} program to copy the
+libtool support files into your directory.
+
+Once you have managed to run these commands without getting any errors,
+you should create a new empty directory, and run the @samp{configure}
+script which will have been created by @samp{autoconf} with the
+@samp{--enable-maintainer-mode} option.  This will give you a set of
+Makefiles which will include rules to automatically rebuild all the
+generated files.
+
+After doing that, whenever you have changed some of the input files and
+want to regenerated the other files, go to your object directory and run
+@samp{make}.  Doing this is more reliable than trying to rebuild the
+files manually, because there are complex order dependencies and it is
+easy to forget something.
+
+@node Getting Started Example
+@section Example
+
+Let's consider a trivial example.
+
+Suppose we want to write a simple version of @samp{touch}.  Our program,
+which we will call @samp{poke}, will take a single file name argument,
+and use the @samp{utime} system call to set the modification and access
+times of the file to the current time.  We want this program to be
+highly portable.
+
+We'll first see what this looks like without using autoconf and
+automake, and then see what it looks like with them.
+
+@menu
+* Getting Started Example 1::          First Try.
+* Getting Started Example 2::          Second Try.
+* Getting Started Example 3::          Third Try.
+* Generate Files in Example::          Generate Files.
+@end menu
+
+@node Getting Started Example 1
+@subsection First Try
+
+Here is our first try at @samp{poke.c}.  Note that we've written it
+without ANSI/ISO C prototypes, since we want it to be highly portable.
+
+@example
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <utime.h>
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+@{
+  if (argc != 2)
+    @{
+      fprintf (stderr, "Usage: poke file\n");
+      exit (1);
+    @}
+
+  if (utime (argv[1], NULL) < 0)
+    @{
+      perror ("utime");
+      exit (1);
+    @}
+
+  exit (0);
+@}
+@end example
+
+We also write a simple @file{Makefile}.
+
+@example
+CC = gcc
+CFLAGS = -g -O2
+
+all: poke
+
+poke: poke.o
+       $(CC) -o poke $(CFLAGS) $(LDFLAGS) poke.o
+@end example
+
+So far, so good.
+
+Unfortunately, there are a few problems.
+
+On older Unix systems derived from BSD 4.3, the @samp{utime} system call
+does not accept a second argument of @samp{NULL}.  On those systems, we
+need to pass a pointer to @samp{struct utimbuf} structure.
+Unfortunately, even older systems don't define that structure; on those
+systems, we need to pass an array of two @samp{long} values.
+
+The header file @file{stdlib.h} was invented by ANSI C, and older
+systems don't have a copy.  We included it above to get a declaration of
+@samp{exit}.
+
+We can find some of these portability problems by running
+@samp{autoscan}, which will create a @file{configure.scan} file which we
+can use as a prototype for our @file{configure.in} file.  I won't show
+the output, but it will notice the potential problems with @samp{utime}
+and @file{stdlib.h}.
+
+In our @file{Makefile}, we don't provide any way to install the program.
+This doesn't matter much for such a simple example, but a real program
+will need an @samp{install} target.  For that matter, we will also want
+a @samp{clean} target.
+
+@node Getting Started Example 2
+@subsection Second Try
+
+Here is our second try at this program.
+
+We modify @file{poke.c} to use preprocessor macros to control what
+features are available.  (I've cheated a bit by using the same macro
+names which autoconf will use).
+
+@example
+#include <stdio.h>
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#ifndef HAVE_UTIME_NULL
+
+#include <time.h>
+
+#ifndef HAVE_STRUCT_UTIMBUF
+
+struct utimbuf
+@{
+  long actime;
+  long modtime;
+@};
+
+#endif
+
+static int
+utime_now (file)
+     char *file;
+@{
+  struct utimbuf now;
+
+  now.actime = now.modtime = time (NULL);
+  return utime (file, &now);
+@}
+
+#define utime(f, p) utime_now (f)
+
+#endif /* HAVE_UTIME_NULL  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+@{
+  if (argc != 2)
+    @{
+      fprintf (stderr, "Usage: poke file\n");
+      exit (1);
+    @}
+
+  if (utime (argv[1], NULL) < 0)
+    @{
+      perror ("utime");
+      exit (1);
+    @}
+
+  exit (0);
+@}
+@end example
+
+Here is the associated @file{Makefile}.  We've added support for the
+preprocessor flags we use.  We've also added @samp{install} and
+@samp{clean} targets.
+
+@example
+# Set this to your installation directory.
+bindir = /usr/local/bin
+
+# Uncomment this if you have the standard ANSI/ISO C header files.
+# STDC_HDRS = -DSTDC_HEADERS
+
+# Uncomment this if you have utime.h.
+# UTIME_H = -DHAVE_UTIME_H
+
+# Uncomment this if utime (FILE, NULL) works on your system.
+# UTIME_NULL = -DHAVE_UTIME_NULL
+
+# Uncomment this if struct utimbuf is defined in utime.h.
+# UTIMBUF = -DHAVE_STRUCT_UTIMBUF
+
+CC = gcc
+CFLAGS = -g -O2
+
+ALL_CFLAGS = $(STDC_HDRS) $(UTIME_H) $(UTIME_NULL) $(UTIMBUF) $(CFLAGS)
+
+all: poke
+
+poke: poke.o
+       $(CC) -o poke $(ALL_CFLAGS) $(LDFLAGS) poke.o
+
+.c.o:
+       $(CC) -c $(ALL_CFLAGS) poke.c
+
+install: poke
+       cp poke $(bindir)/poke
+
+clean:
+       rm poke poke.o
+@end example
+
+Some problems with this approach should be clear.
+
+Users who want to compile poke will have to know how @samp{utime} works
+on their systems, so that they can uncomment the @file{Makefile}
+correctly.
+
+The installation is done using @samp{cp}, but many systems have an
+@samp{install} program which may be used, and which supports optional
+features such as stripping debugging information out of the installed
+binary.
+
+The use of @file{Makefile} variables like @samp{CC}, @samp{CFLAGS} and
+@samp{LDFLAGS} follows the requirements of the GNU standards.  This is
+convenient for all packages, since it reduces surprises for users.
+However, it is easy to get the details wrong, and wind up with a
+slightly nonstandard distribution.
+
+@node Getting Started Example 3
+@subsection Third Try
+
+For our third try at this program, we will write a @file{configure.in}
+script to discover the configuration features on the host system, rather
+than requiring the user to edit the @file{Makefile}.  We will also write
+a @file{Makefile.am} rather than a @file{Makefile}.
+
+The only change to @file{poke.c} is to add a line at the start of the
+file:
+@smallexample
+#include "config.h"
+@end smallexample
+
+The new @file{configure.in} file is as follows.
+
+@example
+AC_INIT(poke.c)
+AM_INIT_AUTOMAKE(poke, 1.0)
+AM_CONFIG_HEADER(config.h:config.in)
+AC_PROG_CC
+AC_HEADER_STDC
+AC_CHECK_HEADERS(utime.h)
+AC_EGREP_HEADER(utimbuf, utime.h, AC_DEFINE(HAVE_STRUCT_UTIMBUF))
+AC_FUNC_UTIME_NULL
+AC_OUTPUT(Makefile)
+@end example
+
+The first four macros in this file, and the last one, were described
+above; see @ref{Write configure.in}.  If we omit these macros, then when
+we run @samp{automake} we will get a reminder that we need them.
+
+The other macros are standard autoconf macros.
+
+@table @samp
+@item AC_HEADER_STDC
+Check for standard C headers.
+@item AC_CHECK_HEADERS
+Check whether a particular header file exists.
+@item AC_EGREP_HEADER
+Check for a particular string in a particular header file, in this case
+checking for @samp{utimbuf} in @file{utime.h}.
+@item AC_FUNC_UTIME_NULL
+Check whether @samp{utime} accepts a NULL second argument to set the
+file change time to the current time.
+@end table
+
+See the autoconf manual for a more complete description.
+
+The new @file{Makefile.am} file is as follows.  Note how simple this is
+compared to our earlier @file{Makefile}.
+
+@example
+bin_PROGRAMS = poke
+
+poke_SOURCES = poke.c
+@end example
+
+This means that we should build a single program name @samp{poke}.  It
+should be installed in the binary directory, which we called
+@samp{bindir} earlier.  The program @samp{poke} is built from the source
+file @file{poke.c}.
+
+We must also write a @file{acconfig.h} file.  Besides @samp{PACKAGE} and
+@samp{VERSION}, which must be mentioned for all packages which use
+automake, we must include @samp{HAVE_STRUCT_UTIMBUF}, since we mentioned
+it in an @samp{AC_DEFINE}.
+
+@example
+/* Name of package.  */
+#undef PACKAGE
+
+/* Version of package.  */
+#undef VERSION
+
+/* Whether utime.h defines struct utimbuf.  */
+#undef HAVE_STRUCT_UTIMBUF
+@end example
+
+@node Generate Files in Example
+@subsection Generate Files
+
+We must now generate the other files, using the following commands.
+
+@smallexample
+aclocal
+autoconf
+autoheader
+automake
+@end smallexample
+
+When we run @samp{autoheader}, it will remind us of any macros we forgot
+to add to @file{acconfig.h}.
+
+When we run @samp{automake}, it will want to add some files to our
+distribution.  It will add them automatically if we use the
+@samp{--add-missing} option.
+
+By default, @samp{automake} will run in GNU mode, which means that it
+will want us to create certain additional files; as of this writing, it
+will want @file{NEWS}, @file{README}, @file{AUTHORS}, and
+@file{ChangeLog}, all of which are files which should appear in a
+standard GNU distribution.  We can either add those files, or run
+@samp{automake} with the @samp{--foreign} option.
+
+Running these tools will generate the following files, all of which are
+described in the next chapter.
+
+@itemize @bullet
+@item
+@file{aclocal.m4}
+@item
+@file{configure}
+@item
+@file{config.in}
+@item
+@file{Makefile.in}
+@item
+@file{stamp-h.in}
+@end itemize
+
+@node Files
+@chapter Files
+
+As was seen in the previous chapter, the GNU configure and build system
+uses a number of different files.  The developer must write a few files.
+The others are generated by various tools.
+
+The system is rather flexible, and can be used in many different ways.
+In describing the files that it uses, I will describe the common case,
+and mention some other cases that may arise.
+
+@menu
+* Developer Files::            Developer Files.
+* Build Files::                        Build Files.
+* Support Files::              Support Files.
+@end menu
+
+@node Developer Files
+@section Developer Files
+
+This section describes the files written or generated by the developer
+of a package.
+
+@menu
+* Developer Files Picture::    Developer Files Picture.
+* Written Developer Files::    Written Developer Files.
+* Generated Developer Files::  Generated Developer Files.
+@end menu
+
+@node Developer Files Picture
+@subsection Developer Files Picture
+
+Here is a picture of the files which are written by the developer, the
+generated files which would be included with a complete source
+distribution, and the tools which create those files.
+@ifinfo
+The file names are plain text and the tool names are enclosed by
+@samp{*} characters
+@end ifinfo
+@ifnotinfo
+The file names are in rectangles with square corners and the tool names
+are in rectangles with rounded corners
+@end ifnotinfo
+(e.g., @samp{autoheader} is the name of a tool, not the name of a file).
+
+@image{configdev}
+
+@node Written Developer Files
+@subsection Written Developer Files
+
+The following files would be written by the developer.
+
+@table @file
+@item configure.in
+@cindex @file{configure.in}
+This is the configuration script.  This script contains invocations of
+autoconf macros.  It may also contain ordinary shell script code.  This
+file will contain feature tests for portability issues.  The last thing
+in the file will normally be an @samp{AC_OUTPUT} macro listing which
+files to create when the builder runs the configure script.  This file
+is always required when using the GNU configure system.  @xref{Write
+configure.in}.
+
+@item Makefile.am
+@cindex @file{Makefile.am}
+This is the automake input file.  It describes how the code should be
+built.  It consists of definitions of automake variables.  It may also
+contain ordinary Makefile targets.  This file is only needed when using
+automake (newer tools normally use automake, but there are still older
+tools which have not been converted, in which the developer writes
+@file{Makefile.in} directly).  @xref{Write Makefile.am}.
+
+@item acconfig.h
+@cindex @file{acconfig.h}
+When the configure script creates a portability header file, by using
+@samp{AM_CONFIG_HEADER} (or, if not using automake,
+@samp{AC_CONFIG_HEADER}), this file is used to describe macros which are
+not recognized by the @samp{autoheader} command.  This is normally a
+fairly uninteresting file, consisting of a collection of @samp{#undef}
+lines with comments.  Normally any call to @samp{AC_DEFINE} in
+@file{configure.in} will require a line in this file. @xref{Write
+acconfig.h}.
+
+@item acinclude.m4
+@cindex @file{acinclude.m4}
+This file is not always required.  It defines local autoconf macros.
+These macros may then be used in @file{configure.in}.  If you don't need
+any local autoconf macros, then you don't need this file at all.  In
+fact, in general, you never need local autoconf macros, since you can
+put everything in @file{configure.in}, but sometimes a local macro is
+convenient.
+
+Newer tools may omit @file{acinclude.m4}, and instead use a
+subdirectory, typically named @file{m4}, and define
+@samp{ACLOCAL_AMFLAGS = -I m4} in @file{Makefile.am} to force
+@samp{aclocal} to look there for macro definitions.  The macro
+definitions are then placed in separate files in that directory.
+
+The @file{acinclude.m4} file is only used when using automake; in older
+tools, the developer writes @file{aclocal.m4} directly, if it is needed.
+@end table
+
+@node Generated Developer Files
+@subsection Generated Developer Files
+
+The following files would be generated by the developer.
+
+When using automake, these files are normally not generated manually
+after the first time.  Instead, the generated @file{Makefile} contains
+rules to automatically rebuild the files as required.  When
+@samp{AM_MAINTAINER_MODE} is used in @file{configure.in} (the normal
+case in Cygnus code), the automatic rebuilding rules will only be
+defined if you configure using the @samp{--enable-maintainer-mode}
+option.
+
+When using automatic rebuilding, it is important to ensure that all the
+various tools have been built and installed on your @samp{PATH}.  Using
+automatic rebuilding is highly recommended, so much so that I'm not
+going to explain what you have to do if you don't use it.
+
+@table @file
+@item configure
+@cindex @file{configure}
+This is the configure script which will be run when building the
+package.  This is generated by @samp{autoconf} from @file{configure.in}
+and @file{aclocal.m4}.  This is a shell script.
+
+@item Makefile.in
+@cindex @file{Makefile.in}
+This is the file which the configure script will turn into the
+@file{Makefile} at build time.  This file is generated by
+@samp{automake} from @file{Makefile.am}.  If you aren't using automake,
+you must write this file yourself.  This file is pretty much a normal
+@file{Makefile}, with some configure substitutions for certain
+variables.
+
+@item aclocal.m4
+@cindex @file{aclocal.m4}
+This file is created by the @samp{aclocal} program, based on the
+contents of @file{configure.in} and @file{acinclude.m4} (or, as noted in
+the description of @file{acinclude.m4} above, on the contents of an
+@file{m4} subdirectory).  This file contains definitions of autoconf
+macros which @samp{autoconf} will use when generating the file
+@file{configure}.  These autoconf macros may be defined by you in
+@file{acinclude.m4} or they may be defined by other packages such as
+automake, libtool or gettext.  If you aren't using automake, you will
+normally write this file yourself; in that case, if @file{configure.in}
+uses only standard autoconf macros, this file will not be needed at all.
+
+@item config.in
+@cindex @file{config.in}
+@cindex @file{config.h.in}
+This file is created by @samp{autoheader} based on @file{acconfig.h} and
+@file{configure.in}.  At build time, the configure script will define
+some of the macros in it to create @file{config.h}, which may then be
+included by your program.  This permits your C code to use preprocessor
+conditionals to change its behaviour based on the characteristics of the
+host system.  This file may also be called @file{config.h.in}.
+
+@item stamp.h-in
+@cindex @file{stamp-h.in}
+This rather uninteresting file, which I omitted from the picture, is
+generated by @samp{automake}.  It always contains the string
+@samp{timestamp}.  It is used as a timestamp file indicating whether
+@file{config.in} is up to date.  Using a timestamp file means that
+@file{config.in} can be marked as up to date without actually changing
+its modification time.  This is useful since @file{config.in} depends
+upon @file{configure.in}, but it is easy to change @file{configure.in}
+in a way which does not affect @file{config.in}.
+@end table
+
+@node Build Files
+@section Build Files
+
+This section describes the files which are created at configure and
+build time.  These are the files which somebody who builds the package
+will see.
+
+Of course, the developer will also build the package.  The distinction
+between developer files and build files is not that the developer does
+not see the build files, but that somebody who only builds the package
+does not have to worry about the developer files.
+
+@menu
+* Build Files Picture::                Build Files Picture.
+* Build Files Description::    Build Files Description.
+@end menu
+
+@node Build Files Picture
+@subsection Build Files Picture
+
+Here is a picture of the files which will be created at build time.
+@file{config.status} is both a created file and a shell script which is
+run to create other files, and the picture attempts to show that.
+
+@image{configbuild}
+
+@node Build Files Description
+@subsection Build Files Description
+
+This is a description of the files which are created at build time.
+
+@table @file
+@item config.status
+@cindex @file{config.status}
+The first step in building a package is to run the @file{configure}
+script.  The @file{configure} script will create the file
+@file{config.status}, which is itself a shell script.  When you first
+run @file{configure}, it will automatically run @file{config.status}.
+An @file{Makefile} derived from an automake generated @file{Makefile.in}
+will contain rules to automatically run @file{config.status} again when
+necessary to recreate certain files if their inputs change.
+
+@item Makefile
+@cindex @file{Makefile}
+This is the file which make will read to build the program.  The
+@file{config.status} script will transform @file{Makefile.in} into
+@file{Makefile}.
+
+@item config.h
+@cindex @file{config.h}
+This file defines C preprocessor macros which C code can use to adjust
+its behaviour on different systems.  The @file{config.status} script
+will transform @file{config.in} into @file{config.h}.
+
+@item config.cache
+@cindex @file{config.cache}
+This file did not fit neatly into the picture, and I omitted it.  It is
+used by the @file{configure} script to cache results between runs.  This
+can be an important speedup.  If you modify @file{configure.in} in such
+a way that the results of old tests should change (perhaps you have
+added a new library to @samp{LDFLAGS}), then you will have to remove
+@file{config.cache} to force the tests to be rerun.
+
+The autoconf manual explains how to set up a site specific cache file.
+This can speed up running @file{configure} scripts on your system.
+
+@item stamp.h
+@cindex @file{stamp-h}
+This file, which I omitted from the picture, is similar to
+@file{stamp-h.in}.  It is used as a timestamp file indicating whether
+@file{config.h} is up to date.  This is useful since @file{config.h}
+depends upon @file{config.status}, but it is easy for
+@file{config.status} to change in a way which does not affect
+@file{config.h}.
+@end table
+
+@node Support Files
+@section Support Files
+
+The GNU configure and build system requires several support files to be
+included with your distribution.  You do not normally need to concern
+yourself with these.  If you are using the Cygnus tree, most are already
+present.  Otherwise, they will be installed with your source by
+@samp{automake} (with the @samp{--add-missing} option) and
+@samp{libtoolize}.
+
+You don't have to put the support files in the top level directory.  You
+can put them in a subdirectory, and use the @samp{AC_CONFIG_AUX_DIR}
+macro in @file{configure.in} to tell @samp{automake} and the
+@file{configure} script where they are.
+
+In this section, I describe the support files, so that you can know what
+they are and why they are there.
+
+@table @file
+@item ABOUT-NLS
+Added by automake if you are using gettext.  This is a documentation
+file about the gettext project.
+@item ansi2knr.c
+Used by an automake generated @file{Makefile} if you put @samp{ansi2knr}
+in @samp{AUTOMAKE_OPTIONS} in @file{Makefile.am}.  This permits
+compiling ANSI C code with a K&R C compiler.
+@item ansi2knr.1
+The man page which goes with @file{ansi2knr.c}.
+@item config.guess
+A shell script which determines the configuration name for the system on
+which it is run.
+@item config.sub
+A shell script which canonicalizes a configuration name entered by a
+user.
+@item elisp-comp
+Used to compile Emacs LISP files.
+@item install-sh
+A shell script which installs a program.  This is used if the configure
+script can not find an install binary.
+@item ltconfig
+Used by libtool.  This is a shell script which configures libtool for
+the particular system on which it is used.
+@item ltmain.sh
+Used by libtool.  This is the actual libtool script which is used, after
+it is configured by @file{ltconfig} to build a library.
+@item mdate-sh
+A shell script used by an automake generated @file{Makefile} to pretty
+print the modification time of a file.  This is used to maintain version
+numbers for texinfo files.
+@item missing
+A shell script used if some tool is missing entirely.  This is used by
+an automake generated @file{Makefile} to avoid certain sorts of
+timestamp problems.
+@item mkinstalldirs
+A shell script which creates a directory, including all parent
+directories.  This is used by an automake generated @file{Makefile}
+during installation.
+@item texinfo.tex
+Required if you have any texinfo files.  This is used when converting
+Texinfo files into DVI using @samp{texi2dvi} and @TeX{}.
+@item ylwrap
+A shell script used by an automake generated @file{Makefile} to run
+programs like @samp{bison}, @samp{yacc}, @samp{flex}, and @samp{lex}.
+These programs default to producing output files with a fixed name, and
+the @file{ylwrap} script runs them in a subdirectory to avoid file name
+conflicts when using a parallel make program.
+@end table
+
+@node Configuration Names
+@chapter Configuration Names
+@cindex configuration names
+@cindex configuration triplets
+@cindex triplets
+@cindex host names
+@cindex host triplets
+@cindex canonical system names
+@cindex system names
+@cindex system types
+
+The GNU configure system names all systems using a @dfn{configuration
+name}.  All such names used to be triplets (they may now contain four
+parts in certain cases), and the term @dfn{configuration triplet} is
+still seen.
+
+@menu
+* Configuration Name Definition::      Configuration Name Definition.
+* Using Configuration Names::          Using Configuration Names.
+@end menu
+
+@node Configuration Name Definition
+@section Configuration Name Definition
+
+This is a string of the form
+@var{cpu}-@var{manufacturer}-@var{operating_system}.  In some cases,
+this is extended to a four part form:
+@var{cpu}-@var{manufacturer}-@var{kernel}-@var{operating_system}.
+
+When using a configuration name in a configure option, it is normally
+not necessary to specify an entire name.  In particular, the
+@var{manufacturer} field is often omitted, leading to strings such as
+@samp{i386-linux} or @samp{sparc-sunos}.  The shell script
+@file{config.sub} will translate these shortened strings into the
+canonical form.  autoconf will arrange for @file{config.sub} to be run
+automatically when it is needed.
+
+The fields of a configuration name are as follows:
+
+@table @var
+@item cpu
+The type of processor.  This is typically something like @samp{i386} or
+@samp{sparc}.  More specific variants are used as well, such as
+@samp{mipsel} to indicate a little endian MIPS processor.
+@item manufacturer
+A somewhat freeform field which indicates the manufacturer of the
+system.  This is often simply @samp{unknown}.  Other common strings are
+@samp{pc} for an IBM PC compatible system, or the name of a workstation
+vendor, such as @samp{sun}.
+@item operating_system
+The name of the operating system which is run on the system.  This will
+be something like @samp{solaris2.5} or @samp{irix6.3}.  There is no
+particular restriction on the version number, and strings like
+@samp{aix4.1.4.0} are seen.  For an embedded system, which has no
+operating system, this field normally indicates the type of object file
+format, such as @samp{elf} or @samp{coff}.
+@item kernel
+This is used mainly for GNU/Linux.  A typical GNU/Linux configuration
+name is @samp{i586-pc-linux-gnulibc1}.  In this case the kernel,
+@samp{linux}, is separated from the operating system, @samp{gnulibc1}.
+@end table
+
+The shell script @file{config.guess} will normally print the correct
+configuration name for the system on which it is run.  It does by
+running @samp{uname} and by examining other characteristics of the
+system.
+
+Because @file{config.guess} can normally determine the configuration
+name for a machine, it is normally only necessary to specify a
+configuration name when building a cross-compiler or when building using
+a cross-compiler.
+
+@node Using Configuration Names
+@section Using Configuration Names
+
+A configure script will sometimes have to make a decision based on a
+configuration name.  You will need to do this if you have to compile
+code differently based on something which can not be tested using a
+standard autoconf feature test.
+
+It is normally better to test for particular features, rather than to
+test for a particular system.  This is because as Unix evolves,
+different systems copy features from one another.  Even if you need to
+determine whether the feature is supported based on a configuration
+name, you should define a macro which describes the feature, rather than
+defining a macro which describes the particular system you are on.
+
+Testing for a particular system is normally done using a case statement
+in @file{configure.in}.  The case statement might look something like
+the following, assuming that @samp{host} is a shell variable holding a
+canonical configuration name (which will be the case if
+@file{configure.in} uses the @samp{AC_CANONICAL_HOST} or
+@samp{AC_CANONICAL_SYSTEM} macro).
+
+@smallexample
+case "$@{host@}" in
+i[3456]86-*-linux-gnu*) do something ;;
+sparc*-sun-solaris2.[56789]*) do something ;;
+sparc*-sun-solaris*) do something ;;
+mips*-*-elf*) do something ;;
+esac
+@end smallexample
+
+It is particularly important to use @samp{*} after the operating system
+field, in order to match the version number which will be generated by
+@file{config.guess}.
+
+In most cases you must be careful to match a range of processor types.
+For most processor families, a trailing @samp{*} suffices, as in
+@samp{mips*} above.  For the i386 family, something along the lines of
+@samp{i[3456]86} suffices at present.  For the m68k family, you will
+need something like @samp{m68*}.  Of course, if you do not need to match
+on the processor, it is simpler to just replace the entire field by a
+@samp{*}, as in @samp{*-*-irix*}.
+
+@node Cross Compilation Tools
+@chapter Cross Compilation Tools
+@cindex cross tools
+
+The GNU configure and build system can be used to build @dfn{cross
+compilation} tools.  A cross compilation tool is a tool which runs on
+one system and produces code which runs on another system.
+
+@menu
+* Cross Compilation Concepts::         Cross Compilation Concepts.
+* Host and Target::                    Host and Target.
+* Using the Host Type::                        Using the Host Type.
+* Specifying the Target::              Specifying the Target.
+* Using the Target Type::              Using the Target Type.
+* Cross Tools in the Cygnus Tree::     Cross Tools in the Cygnus Tree
+@end menu
+
+@node Cross Compilation Concepts
+@section Cross Compilation Concepts
+
+@cindex cross compiler
+A compiler which produces programs which run on a different system is a
+cross compilation compiler, or simply a @dfn{cross compiler}.
+Similarly, we speak of cross assemblers, cross linkers, etc.
+
+In the normal case, a compiler produces code which runs on the same
+system as the one on which the compiler runs.  When it is necessary to
+distinguish this case from the cross compilation case, such a compiler
+is called a @dfn{native compiler}.  Similarly, we speak of native
+assemblers, etc.
+
+Although the debugger is not strictly speaking a compilation tool, it is
+nevertheless meaningful to speak of a cross debugger: a debugger which
+is used to debug code which runs on another system.  Everything that is
+said below about configuring cross compilation tools applies to the
+debugger as well.
+
+@node Host and Target
+@section Host and Target
+@cindex host system
+@cindex target system
+
+When building cross compilation tools, there are two different systems
+involved: the system on which the tools will run, and the system for
+which the tools generate code.
+
+The system on which the tools will run is called the @dfn{host} system.
+
+The system for which the tools generate code is called the @dfn{target}
+system.
+
+For example, suppose you have a compiler which runs on a GNU/Linux
+system and generates ELF programs for a MIPS embedded system.  In this
+case the GNU/Linux system is the host, and the MIPS ELF system is the
+target.  Such a compiler could be called a GNU/Linux cross MIPS ELF
+compiler, or, equivalently, a @samp{i386-linux-gnu} cross
+@samp{mips-elf} compiler.
+
+Naturally, most programs are not cross compilation tools.  For those
+programs, it does not make sense to speak of a target.  It only makes
+sense to speak of a target for tools like @samp{gcc} or the
+@samp{binutils} which actually produce running code.  For example, it
+does not make sense to speak of the target of a tool like @samp{bison}
+or @samp{make}.
+
+Most cross compilation tools can also serve as native tools.  For a
+native compilation tool, it is still meaningful to speak of a target.
+For a native tool, the target is the same as the host.  For example, for
+a GNU/Linux native compiler, the host is GNU/Linux, and the target is
+also GNU/Linux.
+
+@node Using the Host Type
+@section Using the Host Type
+
+In almost all cases the host system is the system on which you run the
+@samp{configure} script, and on which you build the tools (for the case
+when they differ, @pxref{Canadian Cross}).
+
+@cindex @samp{AC_CANONICAL_HOST}
+If your configure script needs to know the configuration name of the
+host system, and the package is not a cross compilation tool and
+therefore does not have a target, put @samp{AC_CANONICAL_HOST} in
+@file{configure.in}.  This macro will arrange to define a few shell
+variables when the @samp{configure} script is run.
+
+@table @samp
+@item host
+The canonical configuration name of the host.  This will normally be
+determined by running the @file{config.guess} shell script, although the
+user is permitted to override this by using an explicit @samp{--host}
+option.
+@item host_alias
+In the unusual case that the user used an explicit @samp{--host} option,
+this will be the argument to @samp{--host}.  In the normal case, this
+will be the same as the @samp{host} variable.
+@item host_cpu
+@itemx host_vendor
+@itemx host_os
+The first three parts of the canonical configuration name.
+@end table
+
+The shell variables may be used by putting shell code in
+@file{configure.in}.  For an example, see @ref{Using Configuration
+Names}.
+
+@node Specifying the Target
+@section Specifying the Target
+
+By default, the @samp{configure} script will assume that the target is
+the same as the host.  This is the more common case; for example, it
+leads to a native compiler rather than a cross compiler.
+
+@cindex @samp{--target} option
+@cindex target option
+@cindex configure target
+If you want to build a cross compilation tool, you must specify the
+target explicitly by using the @samp{--target} option when you run
+@samp{configure}.  The argument to @samp{--target} is the configuration
+name of the system for which you wish to generate code.
+@xref{Configuration Names}.
+
+For example, to build tools which generate code for a MIPS ELF embedded
+system, you would use @samp{--target mips-elf}.
+
+@node Using the Target Type
+@section Using the Target Type
+
+@cindex @samp{AC_CANONICAL_SYSTEM}
+When writing @file{configure.in} for a cross compilation tool, you will
+need to use information about the target.  To do this, put
+@samp{AC_CANONICAL_SYSTEM} in @file{configure.in}.
+
+@samp{AC_CANONICAL_SYSTEM} will look for a @samp{--target} option and
+canonicalize it using the @file{config.sub} shell script.  It will also
+run @samp{AC_CANONICAL_HOST} (@pxref{Using the Host Type}).
+
+The target type will be recorded in the following shell variables.  Note
+that the host versions of these variables will also be defined by
+@samp{AC_CANONICAL_HOST}.
+
+@table @samp
+@item target
+The canonical configuration name of the target.
+@item target_alias
+The argument to the @samp{--target} option.  If the user did not specify
+a @samp{--target} option, this will be the same as @samp{host_alias}.
+@item target_cpu
+@itemx target_vendor
+@itemx target_os
+The first three parts of the canonical target configuration name.
+@end table
+
+Note that if @samp{host} and @samp{target} are the same string, you can
+assume a native configuration.  If they are different, you can assume a
+cross configuration.
+
+It is arguably possible for @samp{host} and @samp{target} to represent
+the same system, but for the strings to not be identical.  For example,
+if @samp{config.guess} returns @samp{sparc-sun-sunos4.1.4}, and somebody
+configures with @samp{--target sparc-sun-sunos4.1}, then the slight
+differences between the two versions of SunOS may be unimportant for
+your tool.  However, in the general case it can be quite difficult to
+determine whether the differences between two configuration names are
+significant or not.  Therefore, by convention, if the user specifies a
+@samp{--target} option without specifying a @samp{--host} option, it is
+assumed that the user wants to configure a cross compilation tool.
+
+The variables @samp{target} and @samp{target_alias} should be handled
+differently.
+
+In general, whenever the user may actually see a string,
+@samp{target_alias} should be used.  This includes anything which may
+appear in the file system, such as a directory name or part of a tool
+name.  It also includes any tool output, unless it is clearly labelled
+as the canonical target configuration name.  This permits the user to
+use the @samp{--target} option to specify how the tool will appear to
+the outside world.
+
+On the other hand, when checking for characteristics of the target
+system, @samp{target} should be used.  This is because a wide variety of
+@samp{--target} options may map into the same canonical configuration
+name.  You should not attempt to duplicate the canonicalization done by
+@samp{config.sub} in your own code.
+
+By convention, cross tools are installed with a prefix of the argument
+used with the @samp{--target} option, also known as @samp{target_alias}
+(@pxref{Using the Target Type}).  If the user does not use the
+@samp{--target} option, and thus is building a native tool, no prefix is
+used.
+
+For example, if gcc is configured with @samp{--target mips-elf}, then
+the installed binary will be named @samp{mips-elf-gcc}.  If gcc is
+configured without a @samp{--target} option, then the installed binary
+will be named @samp{gcc}.
+
+The autoconf macro @samp{AC_ARG_PROGRAM} will handle this for you.  If
+you are using automake, no more need be done; the programs will
+automatically be installed with the correct prefixes.  Otherwise, see
+the autoconf documentation for @samp{AC_ARG_PROGRAM}.
+
+@node Cross Tools in the Cygnus Tree
+@section Cross Tools in the Cygnus Tree
+
+The Cygnus tree is used for various packages including gdb, the GNU
+binutils, and egcs.  It is also, of course, used for Cygnus releases.
+
+In the Cygnus tree, the top level @file{configure} script uses the old
+Cygnus configure system, not autoconf.  The top level @file{Makefile.in}
+is written to build packages based on what is in the source tree, and
+supports building a large number of tools in a single
+@samp{configure}/@samp{make} step.
+
+The Cygnus tree may be configured with a @samp{--target} option.  The
+@samp{--target} option applies recursively to every subdirectory, and
+permits building an entire set of cross tools at once.
+
+@menu
+* Host and Target Libraries::          Host and Target Libraries.
+* Target Library Configure Scripts::   Target Library Configure Scripts.
+* Make Targets in Cygnus Tree::         Make Targets in Cygnus Tree.
+* Target libiberty::                   Target libiberty
+@end menu
+
+@node Host and Target Libraries
+@subsection Host and Target Libraries
+
+The Cygnus tree distinguishes host libraries from target libraries.
+
+Host libraries are built with the compiler used to build the programs
+which run on the host, which is called the host compiler.  This includes
+libraries such as @samp{bfd} and @samp{tcl}.  These libraries are built
+with the host compiler, and are linked into programs like the binutils
+or gcc which run on the host.
+
+Target libraries are built with the target compiler.  If gcc is present
+in the source tree, then the target compiler is the gcc that is built
+using the host compiler.  Target libraries are libraries such as
+@samp{newlib} and @samp{libstdc++}.  These libraries are not linked into
+the host programs, but are instead made available for use with programs
+built with the target compiler.
+
+For the rest of this section, assume that gcc is present in the source
+tree, so that it will be used to build the target libraries.
+
+There is a complication here.  The configure process needs to know which
+compiler you are going to use to build a tool; otherwise, the feature
+tests will not work correctly.  The Cygnus tree handles this by not
+configuring the target libraries until the target compiler is built.  In
+order to permit everything to build using a single
+@samp{configure}/@samp{make}, the configuration of the target libraries
+is actually triggered during the make step.
+
+When the target libraries are configured, the @samp{--target} option is
+not used.  Instead, the @samp{--host} option is used with the argument
+of the @samp{--target} option for the overall configuration.  If no
+@samp{--target} option was used for the overall configuration, the
+@samp{--host} option will be passed with the output of the
+@file{config.guess} shell script.  Any @samp{--build} option is passed
+down unchanged.
+
+This translation of configuration options is done because since the
+target libraries are compiled with the target compiler, they are being
+built in order to run on the target of the overall configuration.  By
+the definition of host, this means that their host system is the same as
+the target system of the overall configuration.
+
+The same process is used for both a native configuration and a cross
+configuration.  Even when using a native configuration, the target
+libraries will be configured and built using the newly built compiler.
+This is particularly important for the C++ libraries, since there is no
+reason to assume that the C++ compiler used to build the host tools (if
+there even is one) uses the same ABI as the g++ compiler which will be
+used to build the target libraries.
+
+There is one difference between a native configuration and a cross
+configuration.  In a native configuration, the target libraries are
+normally configured and built as siblings of the host tools.  In a cross
+configuration, the target libraries are normally built in a subdirectory
+whose name is the argument to @samp{--target}.  This is mainly for
+historical reasons.
+
+To summarize, running @samp{configure} in the Cygnus tree configures all
+the host libraries and tools, but does not configure any of the target
+libraries.  Running @samp{make} then does the following steps:
+
+@itemize @bullet
+@item
+Build the host libraries.
+@item
+Build the host programs, including gcc.  Note that we call gcc both a
+host program (since it runs on the host) and a target compiler (since it
+generates code for the target).
+@item
+Using the newly built target compiler, configure the target libraries.
+@item
+Build the target libraries.
+@end itemize
+
+The steps need not be done in precisely this order, since they are
+actually controlled by @file{Makefile} targets.
+
+@node Target Library Configure Scripts
+@subsection Target Library Configure Scripts
+
+There are a few things you must know in order to write a configure
+script for a target library.  This is just a quick sketch, and beginners
+shouldn't worry if they don't follow everything here.
+
+The target libraries are configured and built using a newly built target
+compiler.  There may not be any startup files or libraries for this
+target compiler.  In fact, those files will probably be built as part of
+some target library, which naturally means that they will not exist when
+your target library is configured.
+
+This means that the configure script for a target library may not use
+any test which requires doing a link.  This unfortunately includes many
+useful autoconf macros, such as @samp{AC_CHECK_FUNCS}.  autoconf macros
+which do a compile but not a link, such as @samp{AC_CHECK_HEADERS}, may
+be used.
+
+This is a severe restriction, but normally not a fatal one, as target
+libraries can often assume the presence of other target libraries, and
+thus know which functions will be available.
+
+As of this writing, the autoconf macro @samp{AC_PROG_CC} does a link to
+make sure that the compiler works.  This may fail in a target library,
+so target libraries must use a different set of macros to locate the
+compiler.  See the @file{configure.in} file in a directory like
+@file{libiberty} or @file{libgloss} for an example.
+
+As noted in the previous section, target libraries are sometimes built
+in directories which are siblings to the host tools, and are sometimes
+built in a subdirectory.  The @samp{--with-target-subdir} configure
+option will be passed when the library is configured.  Its value will be
+an empty string if the target library is a sibling.  Its value will be
+the name of the subdirectory if the target library is in a subdirectory.
+
+If the overall build is not a native build (i.e., the overall configure
+used the @samp{--target} option), then the library will be configured
+with the @samp{--with-cross-host} option.  The value of this option will
+be the host system of the overall build.  Recall that the host system of
+the library will be the target of the overall build.  If the overall
+build is a native build, the @samp{--with-cross-host} option will not be
+used.
+
+A library which can be built both standalone and as a target library may
+want to install itself into different directories depending upon the
+case.  When built standalone, or when built native, the library should
+be installed in @samp{$(libdir)}.  When built as a target library which
+is not native, the library should be installed in @samp{$(tooldir)/lib}.
+The @samp{--with-cross-host} option may be used to distinguish these
+cases.
+
+This same test of @samp{--with-cross-host} may be used to see whether it
+is OK to use link tests in the configure script.  If the
+@samp{--with-cross-host} option is not used, then the library is being
+built either standalone or native, and a link should work.
+
+@node Make Targets in Cygnus Tree
+@subsection Make Targets in Cygnus Tree
+
+The top level @file{Makefile} in the Cygnus tree defines targets for
+every known subdirectory.
+
+For every subdirectory @var{dir} which holds a host library or program,
+the @file{Makefile} target @samp{all-@var{dir}} will build that library
+or program.
+
+There are dependencies among host tools.  For example, building gcc
+requires first building gas, because the gcc build process invokes the
+target assembler.  These dependencies are reflected in the top level
+@file{Makefile}.
+
+For every subdirectory @var{dir} which holds a target library, the
+@file{Makefile} target @samp{configure-target-@var{dir}} will configure
+that library.  The @file{Makefile} target @samp{all-target-@var{dir}}
+will build that library.
+
+Every @samp{configure-target-@var{dir}} target depends upon
+@samp{all-gcc}, since gcc, the target compiler, is required to configure
+the tool.  Every @samp{all-target-@var{dir}} target depends upon the
+corresponding @samp{configure-target-@var{dir}} target.
+
+There are several other targets which may be of interest for each
+directory: @samp{install-@var{dir}}, @samp{clean-@var{dir}}, and
+@samp{check-@var{dir}}.  There are also corresponding @samp{target}
+versions of these for the target libraries , such as
+@samp{install-target-@var{dir}}.
+
+@node Target libiberty
+@subsection Target libiberty
+
+The @file{libiberty} subdirectory is currently a special case, in that
+it is the only directory which is built both using the host compiler and
+using the target compiler.
+
+This is because the files in @file{libiberty} are used when building the
+host tools, and they are also incorporated into the @file{libstdc++}
+target library as support code.
+
+This duality does not pose any particular difficulties.  It means that
+there are targets for both @samp{all-libiberty} and
+@samp{all-target-libiberty}.
+
+In a native configuration, when target libraries are not built in a
+subdirectory, the same objects are normally used as both the host build
+and the target build.  This is normally OK, since libiberty contains
+only C code, and in a native configuration the results of the host
+compiler and the target compiler are normally interoperable.
+
+Irix 6 is again an exception here, since the SGI native compiler
+defaults to using the @samp{O32} ABI, and gcc defaults to using the
+@samp{N32} ABI.  On Irix 6, the target libraries are built in a
+subdirectory even for a native configuration, avoiding this problem.
+
+There are currently no other libraries built for both the host and the
+target, but there is no conceptual problem with adding more.
+
+@node Canadian Cross
+@chapter Canadian Cross
+@cindex canadian cross
+@cindex building with a cross compiler
+@cindex cross compiler, building with
+
+It is possible to use the GNU configure and build system to build a
+program which will run on a system which is different from the system on
+which the tools are built.  In other words, it is possible to build
+programs using a cross compiler.
+
+This is referred to as a @dfn{Canadian Cross}.
+
+@menu
+* Canadian Cross Example::             Canadian Cross Example.
+* Canadian Cross Concepts::            Canadian Cross Concepts.
+* Build Cross Host Tools::             Build Cross Host Tools.
+* Build and Host Options::             Build and Host Options.
+* CCross not in Cygnus Tree::          Canadian Cross not in Cygnus Tree.
+* CCross in Cygnus Tree::              Canadian Cross in Cygnus Tree.
+* Supporting Canadian Cross::          Supporting Canadian Cross.
+@end menu
+
+@node Canadian Cross Example
+@section Canadian Cross Example
+
+Here is an example of a Canadian Cross.
+
+While running on a GNU/Linux, you can build a program which will run on
+a Solaris system.  You would use a GNU/Linux cross Solaris compiler to
+build the program.
+
+Of course, you could not run the resulting program on your GNU/Linux
+system.  You would have to copy it over to a Solaris system before you
+would run it.
+
+Of course, you could also simply build the programs on the Solaris
+system in the first place.  However, perhaps the Solaris system is not
+available for some reason; perhaps you actually don't have one, but you
+want to build the tools for somebody else to use.  Or perhaps your
+GNU/Linux system is much faster than your Solaris system.
+
+A Canadian Cross build is most frequently used when building programs to
+run on a non-Unix system, such as DOS or Windows.  It may be simpler to
+configure and build on a Unix system than to support the configuration
+machinery on a non-Unix system.
+
+@node Canadian Cross Concepts
+@section Canadian Cross Concepts
+
+When building a Canadian Cross, there are at least two different systems
+involved: the system on which the tools are being built, and the system
+on which the tools will run.
+
+The system on which the tools are being built is called the @dfn{build}
+system.
+
+The system on which the tools will run is called the host system.
+
+For example, if you are building a Solaris program on a GNU/Linux
+system, as in the previous section, the build system would be GNU/Linux,
+and the host system would be Solaris.
+
+It is, of course, possible to build a cross compiler using a Canadian
+Cross (i.e., build a cross compiler using a cross compiler).  In this
+case, the system for which the resulting cross compiler generates code
+is called the target system.  (For a more complete discussion of host
+and target systems, @pxref{Host and Target}).
+
+An example of building a cross compiler using a Canadian Cross would be
+building a Windows cross MIPS ELF compiler on a GNU/Linux system.  In
+this case the build system would be GNU/Linux, the host system would be
+Windows, and the target system would be MIPS ELF.
+
+The name Canadian Cross comes from the case when the build, host, and
+target systems are all different.  At the time that these issues were
+all being hashed out, Canada had three national political parties.
+
+@node Build Cross Host Tools
+@section Build Cross Host Tools
+
+In order to configure a program for a Canadian Cross build, you must
+first build and install the set of cross tools you will use to build the
+program.
+
+These tools will be build cross host tools.  That is, they will run on
+the build system, and will produce code that runs on the host system.
+
+It is easy to confuse the meaning of build and host here.  Always
+remember that the build system is where you are doing the build, and the
+host system is where the resulting program will run.  Therefore, you
+need a build cross host compiler.
+
+In general, you must have a complete cross environment in order to do
+the build.  This normally means a cross compiler, cross assembler, and
+so forth, as well as libraries and include files for the host system.
+
+@node Build and Host Options
+@section Build and Host Options
+@cindex configuring a canadian cross
+@cindex canadian cross, configuring
+
+When you run @file{configure}, you must use both the @samp{--build} and
+@samp{--host} options.
+
+@cindex @samp{--build} option
+@cindex build option
+@cindex configure build system
+The @samp{--build} option is used to specify the configuration name of
+the build system.  This can normally be the result of running the
+@file{config.guess} shell script, and it is reasonable to use
+@samp{--build=`config.guess`}.
+
+@cindex @samp{--host} option
+@cindex host option
+@cindex configure host
+The @samp{--host} option is used to specify the configuration name of
+the host system.
+
+As we explained earlier, @file{config.guess} is used to set the default
+value for the @samp{--host} option (@pxref{Using the Host Type}).  We
+can now see that since @file{config.guess} returns the type of system on
+which it is run, it really identifies the build system.  Since the host
+system is normally the same as the build system (i.e., people do not
+normally build using a cross compiler), it is reasonable to use the
+result of @file{config.guess} as the default for the host system when
+the @samp{--host} option is not used.
+
+It might seem that if the @samp{--host} option were used without the
+@samp{--build} option that the configure script could run
+@file{config.guess} to determine the build system, and presume a
+Canadian Cross if the result of @file{config.guess} differed from the
+@samp{--host} option.  However, for historical reasons, some configure
+scripts are routinely run using an explicit @samp{--host} option, rather
+than using the default from @file{config.guess}.  As noted earlier, it
+is difficult or impossible to reliably compare configuration names
+(@pxref{Using the Target Type}).  Therefore, by convention, if the
+@samp{--host} option is used, but the @samp{--build} option is not used,
+then the build system defaults to the host system.
+
+@node CCross not in Cygnus Tree
+@section Canadian Cross not in Cygnus Tree.
+
+If you are not using the Cygnus tree, you must explicitly specify the
+cross tools which you want to use to build the program.  This is done by
+setting environment variables before running the @file{configure}
+script.
+
+You must normally set at least the environment variables @samp{CC},
+@samp{AR}, and @samp{RANLIB} to the cross tools which you want to use to
+build.
+
+For some programs, you must set additional cross tools as well, such as
+@samp{AS}, @samp{LD}, or @samp{NM}.
+
+You would set these environment variables to the build cross tools which
+you are going to use.
+
+For example, if you are building a Solaris program on a GNU/Linux
+system, and your GNU/Linux cross Solaris compiler were named
+@samp{solaris-gcc}, then you would set the environment variable
+@samp{CC} to @samp{solaris-gcc}.
+
+@node CCross in Cygnus Tree
+@section Canadian Cross in Cygnus Tree
+@cindex canadian cross in cygnus tree
+
+This section describes configuring and building a Canadian Cross when
+using the Cygnus tree.
+
+@menu
+* Standard Cygnus CCross::     Building a Normal Program.
+* Cross Cygnus CCross::                Building a Cross Program.
+@end menu
+
+@node Standard Cygnus CCross
+@subsection Building a Normal Program
+
+When configuring a Canadian Cross in the Cygnus tree, all the
+appropriate environment variables are automatically set to
+@samp{@var{host}-@var{tool}}, where @var{host} is the value used for the
+@samp{--host} option, and @var{tool} is the name of the tool (e.g.,
+@samp{gcc}, @samp{as}, etc.).  These tools must be on your @samp{PATH}.
+
+Adding a prefix of @var{host} will give the usual name for the build
+cross host tools.  To see this, consider that when these cross tools
+were built, they were configured to run on the build system and to
+produce code for the host system.  That is, they were configured with a
+@samp{--target} option that is the same as the system which we are now
+calling the host.  Recall that the default name for installed cross
+tools uses the target system as a prefix (@pxref{Using the Target
+Type}).  Since that is the system which we are now calling the host,
+@var{host} is the right prefix to use.
+
+For example, if you configure with @samp{--build=i386-linux-gnu} and
+@samp{--host=solaris}, then the Cygnus tree will automatically default
+to using the compiler @samp{solaris-gcc}.  You must have previously
+built and installed this compiler, probably by doing a build with no
+@samp{--host} option and with a @samp{--target} option of
+@samp{solaris}.
+
+@node Cross Cygnus CCross
+@subsection Building a Cross Program
+
+There are additional considerations if you want to build a cross
+compiler, rather than a native compiler, in the Cygnus tree using a
+Canadian Cross.
+
+When you build a cross compiler using the Cygnus tree, then the target
+libraries will normally be built with the newly built target compiler
+(@pxref{Host and Target Libraries}).  However, this will not work when
+building with a Canadian Cross.  This is because the newly built target
+compiler will be a program which runs on the host system, and therefore
+will not be able to run on the build system.
+
+Therefore, when building a cross compiler with the Cygnus tree, you must
+first install a set of build cross target tools.  These tools will be
+used when building the target libraries.
+
+Note that this is not a requirement of a Canadian Cross in general.  For
+example, it would be possible to build just the host cross target tools
+on the build system, to copy the tools to the host system, and to build
+the target libraries on the host system.  The requirement for build
+cross target tools is imposed by the Cygnus tree, which expects to be
+able to build both host programs and target libraries in a single
+@samp{configure}/@samp{make} step.  Because it builds these in a single
+step, it expects to be able to build the target libraries on the build
+system, which means that it must use a build cross target toolchain.
+
+For example, suppose you want to build a Windows cross MIPS ELF compiler
+on a GNU/Linux system.  You must have previously installed both a
+GNU/Linux cross Windows compiler and a GNU/Linux cross MIPS ELF
+compiler.
+
+In order to build the Windows (configuration name @samp{i386-cygwin32})
+cross MIPS ELF (configure name @samp{mips-elf}) compiler, you might
+execute the following commands (long command lines are broken across
+lines with a trailing backslash as a continuation character).
+
+@example
+mkdir linux-x-cygwin32
+cd linux-x-cygwin32
+@var{srcdir}/configure --target i386-cygwin32 --prefix=@var{installdir} \
+  --exec-prefix=@var{installdir}/H-i386-linux
+make
+make install
+cd ..
+mkdir linux-x-mips-elf
+cd linux-x-mips-elf
+@var{srcdir}/configure --target mips-elf --prefix=@var{installdir} \
+  --exec-prefix=@var{installdir}/H-i386-linux
+make
+make install
+cd ..
+mkdir cygwin32-x-mips-elf
+cd cygwin32-x-mips-elf
+@var{srcdir}/configure --build=i386-linux-gnu --host=i386-cygwin32 \
+  --target=mips-elf --prefix=@var{wininstalldir} \
+  --exec-prefix=@var{wininstalldir}/H-i386-cygwin32
+make
+make install
+@end example
+
+You would then copy the contents of @var{wininstalldir} over to the
+Windows machine, and run the resulting programs.
+
+@node Supporting Canadian Cross
+@section Supporting Canadian Cross
+
+If you want to make it possible to build a program you are developing
+using a Canadian Cross, you must take some care when writing your
+configure and make rules.  Simple cases will normally work correctly.
+However, it is not hard to write configure and make tests which will
+fail in a Canadian Cross.
+
+@menu
+* CCross in Configure::                Supporting Canadian Cross in Configure Scripts.
+* CCross in Make::             Supporting Canadian Cross in Makefiles.
+@end menu
+
+@node CCross in Configure
+@subsection Supporting Canadian Cross in Configure Scripts
+@cindex canadian cross in configure
+
+In a @file{configure.in} file, after calling @samp{AC_PROG_CC}, you can
+find out whether this is a Canadian Cross configure by examining the
+shell variable @samp{cross_compiling}.  In a Canadian Cross, which means
+that the compiler is a cross compiler, @samp{cross_compiling} will be
+@samp{yes}.  In a normal configuration, @samp{cross_compiling} will be
+@samp{no}.
+
+You ordinarily do not need to know the type of the build system in a
+configure script.  However, if you do need that information, you can get
+it by using the macro @samp{AC_CANONICAL_SYSTEM}, the same macro that is
+used to determine the target system.  This macro will set the variables
+@samp{build}, @samp{build_alias}, @samp{build_cpu}, @samp{build_vendor},
+and @samp{build_os}, which correspond to the similar @samp{target} and
+@samp{host} variables, except that they describe the build system.
+
+When writing tests in @file{configure.in}, you must remember that you
+want to test the host environment, not the build environment.
+
+Macros like @samp{AC_CHECK_FUNCS} which use the compiler will test the
+host environment.  That is because the tests will be done by running the
+compiler, which is actually a build cross host compiler.  If the
+compiler can find the function, that means that the function is present
+in the host environment.
+
+Tests like @samp{test -f /dev/ptyp0}, on the other hand, will test the
+build environment.  Remember that the configure script is running on the
+build system, not the host system.  If your configure scripts examines
+files, those files will be on the build system.  Whatever you determine
+based on those files may or may not be the case on the host system.
+
+Most autoconf macros will work correctly for a Canadian Cross.  The main
+exception is @samp{AC_TRY_RUN}.  This macro tries to compile and run a
+test program.  This will fail in a Canadian Cross, because the program
+will be compiled for the host system, which means that it will not run
+on the build system.
+
+The @samp{AC_TRY_RUN} macro provides an optional argument to tell the
+configure script what to do in a Canadian Cross.  If that argument is
+not present, you will get a warning when you run @samp{autoconf}:
+@smallexample
+warning: AC_TRY_RUN called without default to allow cross compiling
+@end smallexample
+@noindent
+This tells you that the resulting @file{configure} script will not work
+with a Canadian Cross.
+
+In some cases while it may better to perform a test at configure time,
+it is also possible to perform the test at run time.  In such a case you
+can use the cross compiling argument to @samp{AC_TRY_RUN} to tell your
+program that the test could not be performed at configure time.
+
+There are a few other autoconf macros which will not work correctly with
+a Canadian Cross: a partial list is @samp{AC_FUNC_GETPGRP},
+@samp{AC_FUNC_SETPGRP}, @samp{AC_FUNC_SETVBUF_REVERSED}, and
+@samp{AC_SYS_RESTARTABLE_SYSCALLS}.  The @samp{AC_CHECK_SIZEOF} macro is
+generally not very useful with a Canadian Cross; it permits an optional
+argument indicating the default size, but there is no way to know what
+the correct default should be.
+
+@node CCross in Make
+@subsection Supporting Canadian Cross in Makefiles.
+@cindex canadian cross in makefile
+
+The main Canadian Cross issue in a @file{Makefile} arises when you want
+to use a subsidiary program to generate code or data which you will then
+include in your real program.
+
+If you compile this subsidiary program using @samp{$(CC)} in the usual
+way, you will not be able to run it.  This is because @samp{$(CC)} will
+build a program for the host system, but the program is being built on
+the build system.
+
+You must instead use a compiler for the build system, rather than the
+host system.  In the Cygnus tree, this make variable
+@samp{$(CC_FOR_BUILD)} will hold a compiler for the build system.
+
+Note that you should not include @file{config.h} in a file you are
+compiling with @samp{$(CC_FOR_BUILD)}.  The @file{configure} script will
+build @file{config.h} with information for the host system.  However,
+you are compiling the file using a compiler for the build system (a
+native compiler).  Subsidiary programs are normally simple filters which
+do no user interaction, and it is normally possible to write them in a
+highly portable fashion so that the absence of @file{config.h} is not
+crucial.
+
+@cindex @samp{HOST_CC}
+The gcc @file{Makefile.in} shows a complex situation in which certain
+files, such as @file{rtl.c}, must be compiled into both subsidiary
+programs run on the build system and into the final program.  This
+approach may be of interest for advanced build system hackers.  Note
+that the build system compiler is rather confusingly called
+@samp{HOST_CC}.
+
+@node Cygnus Configure
+@chapter Cygnus Configure
+@cindex cygnus configure
+
+The Cygnus configure script predates autoconf.  All of its interesting
+features have been incorporated into autoconf.  No new programs should
+be written to use the Cygnus configure script.
+
+However, the Cygnus configure script is still used in a few places: at
+the top of the Cygnus tree and in a few target libraries in the Cygnus
+tree.  Until those uses have been replaced with autoconf, some brief
+notes are appropriate here.  This is not complete documentation, but it
+should be possible to use this as a guide while examining the scripts
+themselves.
+
+@menu
+* Cygnus Configure Basics::            Cygnus Configure Basics.
+* Cygnus Configure in C++ Libraries::  Cygnus Configure in C++ Libraries.
+@end menu
+
+@node Cygnus Configure Basics
+@section Cygnus Configure Basics
+
+Cygnus configure does not use any generated files; there is no program
+corresponding to @samp{autoconf}.  Instead, there is a single shell
+script named @samp{configure} which may be found at the top of the
+Cygnus tree.  This shell script was written by hand; it was not
+generated by autoconf, and it is incorrect, and indeed harmful, to run
+@samp{autoconf} in the top level of a Cygnus tree.
+
+Cygnus configure works in a particular directory by examining the file
+@file{configure.in} in that directory.  That file is broken into four
+separate shell scripts.
+
+The first is the contents of @file{configure.in} up to a line that
+starts with @samp{# per-host:}.  This is the common part.
+
+The second is the rest of @file{configure.in} up to a line that starts
+with @samp{# per-target:}.  This is the per host part.
+
+The third is the rest of @file{configure.in} up to a line that starts
+with @samp{# post-target:}.  This is the per target part.
+
+The fourth is the remainder of @file{configure.in}.  This is the post
+target part.
+
+If any of these comment lines are missing, the corresponding shell
+script is empty.
+
+Cygnus configure will first execute the common part.  This must set the
+shell variable @samp{srctrigger} to the name of a source file, to
+confirm that Cygnus configure is looking at the right directory.  This
+may set the shell variables @samp{package_makefile_frag} and
+@samp{package_makefile_rules_frag}.
+
+Cygnus configure will next set the @samp{build} and @samp{host} shell
+variables, and execute the per host part.  This may set the shell
+variable @samp{host_makefile_frag}.
+
+Cygnus configure will next set the @samp{target} variable, and execute
+the per target part.  This may set the shell variable
+@samp{target_makefile_frag}.
+
+Any of these scripts may set the @samp{subdirs} shell variable.  This
+variable is a list of subdirectories where a @file{Makefile.in} file may
+be found.  Cygnus configure will automatically look for a
+@file{Makefile.in} file in the current directory.  The @samp{subdirs}
+shell variable is not normally used, and I believe that the only
+directory which uses it at present is @file{newlib}.
+
+For each @file{Makefile.in}, Cygnus configure will automatically create
+a @file{Makefile} by adding definitions for @samp{make} variables such
+as @samp{host} and @samp{target}, and automatically editing the values
+of @samp{make} variables such as @samp{prefix} if they are present.
+
+Also, if any of the @samp{makefile_frag} shell variables are set, Cygnus
+configure will interpret them as file names relative to either the
+working directory or the source directory, and will read the contents of
+the file into the generated @file{Makefile}.  The file contents will be
+read in after the first line in @file{Makefile.in} which starts with
+@samp{####}.
+
+These @file{Makefile} fragments are used to customize behaviour for a
+particular host or target.  They serve to select particular files to
+compile, and to define particular preprocessor macros by providing
+values for @samp{make} variables which are then used during compilation.
+Cygnus configure, unlike autoconf, normally does not do feature tests,
+and normally requires support to be added manually for each new host.
+
+The @file{Makefile} fragment support is similar to the autoconf
+@samp{AC_SUBST_FILE} macro.
+
+After creating each @file{Makefile}, the post target script will be run
+(i.e., it may be run several times).  This script may further customize
+the @file{Makefile}.  When it is run, the shell variable @samp{Makefile}
+will hold the name of the @file{Makefile}, including the appropriate
+directory component.
+
+Like an autoconf generated @file{configure} script, Cygnus configure
+will create a file named @file{config.status} which, when run, will
+automatically recreate the configuration.  The @file{config.status} file
+will simply execute the Cygnus configure script again with the
+appropriate arguments.
+
+Any of the parts of @file{configure.in} may set the shell variables
+@samp{files} and @samp{links}.  Cygnus configure will set up symlinks
+from the names in @samp{links} to the files named in @samp{files}.  This
+is similar to the autoconf @samp{AC_LINK_FILES} macro.
+
+Finally, any of the parts of @file{configure.in} may set the shell
+variable @samp{configdirs} to a set of subdirectories.  If it is set,
+Cygnus configure will recursively run the configure process in each
+subdirectory.  If the subdirectory uses Cygnus configure, it will
+contain a @file{configure.in} file but no @file{configure} file, in
+which case Cygnus configure will invoke itself recursively.  If the
+subdirectory has a @file{configure} file, Cygnus configure assumes that
+it is an autoconf generated @file{configure} script, and simply invokes
+it directly.
+
+@node Cygnus Configure in C++ Libraries
+@section Cygnus Configure in C++ Libraries
+@cindex @file{libstdc++} configure
+@cindex @file{libio} configure
+@cindex @file{libg++} configure
+
+The C++ library configure system, written by Per Bothner, deserves
+special mention.  It uses Cygnus configure, but it does feature testing
+like that done by autoconf generated @file{configure} scripts.  This
+approach is used in the libraries @file{libio}, @file{libstdc++}, and
+@file{libg++}.
+
+Most of the @file{Makefile} information is written out by the shell
+script @file{libio/config.shared}.  Each @file{configure.in} file sets
+certain shell variables, and then invokes @file{config.shared} to create
+two package @file{Makefile} fragments.  These fragments are then
+incorporated into the resulting @file{Makefile} by the Cygnus configure
+script.
+
+The file @file{_G_config.h} is created in the @file{libio} object
+directory by running the shell script @file{libio/gen-params}.  This
+shell script uses feature tests to define macros and typedefs in
+@file{_G_config.h}.
+
+@node Multilibs
+@chapter Multilibs
+@cindex multilibs
+
+For some targets gcc may have different processor requirements depending
+upon command line options.  An obvious example is the
+@samp{-msoft-float} option supported on several processors.  This option
+means that the floating point registers are not available, which means
+that floating point operations must be done by calling an emulation
+subroutine rather than by using machine instructions.
+
+For such options, gcc is often configured to compile target libraries
+twice: once with @samp{-msoft-float} and once without.  When gcc
+compiles target libraries more than once, the resulting libraries are
+called @dfn{multilibs}.
+
+Multilibs are not really part of the GNU configure and build system, but
+we discuss them here since they require support in the @file{configure}
+scripts and @file{Makefile}s used for target libraries.
+
+@menu
+* Multilibs in gcc::                   Multilibs in gcc.
+* Multilibs in Target Libraries::      Multilibs in Target Libraries.
+@end menu
+
+@node Multilibs in gcc
+@section Multilibs in gcc
+
+In gcc, multilibs are defined by setting the variable
+@samp{MULTILIB_OPTIONS} in the target @file{Makefile} fragment.  Several
+other @samp{MULTILIB} variables may also be defined there.  @xref{Target
+Fragment, , The Target Makefile Fragment, gcc, Using and Porting GNU
+CC}.
+
+If you have built gcc, you can see what multilibs it uses by running it
+with the @samp{-print-multi-lib} option.  The output @samp{.;} means
+that no multilibs are used.  In general, the output is a sequence of
+lines, one per multilib.  The first part of each line, up to the
+@samp{;}, is the name of the multilib directory.  The second part is a
+list of compiler options separated by @samp{@@} characters.
+
+Multilibs are built in a tree of directories.  The top of the tree,
+represented by @samp{.} in the list of multilib directories, is the
+default library to use when no special compiler options are used.  The
+subdirectories of the tree hold versions of the library to use when
+particular compiler options are used.
+
+@node Multilibs in Target Libraries
+@section Multilibs in Target Libraries
+
+The target libraries in the Cygnus tree are automatically built with
+multilibs.  That means that each library is built multiple times.
+
+This default is set in the top level @file{configure.in} file, by adding
+@samp{--enable-multilib} to the list of arguments passed to configure
+when it is run for the target libraries (@pxref{Host and Target
+Libraries}).
+
+Each target library uses the shell script @file{config-ml.in}, written
+by Doug Evans, to prepare to build target libraries.  This shell script
+is invoked after the @file{Makefile} has been created by the
+@file{configure} script.  If multilibs are not enabled, it does nothing,
+otherwise it modifies the @file{Makefile} to support multilibs.
+
+The @file{config-ml.in} script makes one copy of the @file{Makefile} for
+each multilib in the appropriate subdirectory.  When configuring in the
+source directory (which is not recommended), it will build a symlink
+tree of the sources in each subdirectory.
+
+The @file{config-ml.in} script sets several variables in the various
+@file{Makefile}s.  The @file{Makefile.in} must have definitions for
+these variables already; @file{config-ml.in} simply changes the existing
+values.  The @file{Makefile} should use default values for these
+variables which will do the right thing in the subdirectories.
+
+@table @samp
+@item MULTISRCTOP
+@file{config-ml.in} will set this to a sequence of @samp{../} strings,
+where the number of strings is the number of multilib levels in the
+source tree.  The default value should be the empty string.
+@item MULTIBUILDTOP
+@file{config-ml.in} will set this to a sequence of @samp{../} strings,
+where the number of strings is number of multilib levels in the object
+directory.  The default value should be the empty string.  This will
+differ from @samp{MULTISRCTOP} when configuring in the source tree
+(which is not recommended).
+@item MULTIDIRS
+In the top level @file{Makefile} only, @file{config-ml.in} will set this
+to the list of multilib subdirectories.  The default value should be the
+empty string.
+@item MULTISUBDIR
+@file{config-ml.in} will set this to the installed subdirectory name to
+use for this subdirectory, with a leading @samp{/}.  The default value
+shold be the empty string.
+@item MULTIDO
+@itemx MULTICLEAN
+In the top level @file{Makefile} only, @file{config-ml.in} will set
+these variables to commands to use when doing a recursive make.  These
+variables should both default to the string @samp{true}, so that by
+default nothing happens.
+@end table
+
+All references to the parent of the source directory should use the
+variable @samp{MULTISRCTOP}.  Instead of writing @samp{$(srcdir)/..},
+you must write @samp{$(srcdir)/$(MULTISRCTOP)..}.
+
+Similarly, references to the parent of the object directory should use
+the variable @samp{MULTIBUILDTOP}.
+
+In the installation target, the libraries should be installed in the
+subdirectory @samp{MULTISUBDIR}.  Instead of installing
+@samp{$(libdir)/libfoo.a}, install
+@samp{$(libdir)$(MULTISUBDIR)/libfoo.a}.
+
+The @file{config-ml.in} script also modifies the top level
+@file{Makefile} to add @samp{multi-do} and @samp{multi-clean} targets
+which are used when building multilibs.
+
+The default target of the @file{Makefile} should include the following
+command:
+@smallexample
+@@$(MULTIDO) $(FLAGS_TO_PASS) DO=all multi-do
+@end smallexample
+@noindent
+This assumes that @samp{$(FLAGS_TO_PASS)} is defined as a set of
+variables to pass to a recursive invocation of @samp{make}.  This will
+build all the multilibs.  Note that the default value of @samp{MULTIDO}
+is @samp{true}, so by default this command will do nothing.  It will
+only do something in the top level @file{Makefile} if multilibs were
+enabled.
+
+The @samp{install} target of the @file{Makefile} should include the
+following command:
+@smallexample
+@@$(MULTIDO) $(FLAGS_TO_PASS) DO=install multi-do
+@end smallexample
+
+In general, any operation, other than clean, which should be performed
+on all the multilibs should use a @samp{$(MULTIDO)} line, setting the
+variable @samp{DO} to the target of each recursive call to @samp{make}.
+
+The @samp{clean} targets (@samp{clean}, @samp{mostlyclean}, etc.) should
+use @samp{$(MULTICLEAN)}.  For example, the @samp{clean} target should
+do this:
+@smallexample
+@@$(MULTICLEAN) DO=clean multi-clean
+@end smallexample
+
+@node FAQ
+@chapter Frequently Asked Questions
+
+@table @asis
+@item Which do I run first, @samp{autoconf} or @samp{automake}?
+Except when you first add autoconf or automake support to a package, you
+shouldn't run either by hand.  Instead, configure with the
+@samp{--enable-maintainer-mode} option, and let @samp{make} take care of
+it.
+
+@cindex undefined macros
+@item @samp{autoconf} says something about undefined macros.
+This means that you have macros in your @file{configure.in} which are
+not defined by @samp{autoconf}.  You may be using an old version of
+@samp{autoconf}; try building and installing a newer one.  Make sure the
+newly installled @samp{autoconf} is first on your @samp{PATH}.  Also,
+see the next question.
+
+@cindex @samp{CY_GNU_GETTEXT} in @file{configure}
+@cindex @samp{AM_PROG_LIBTOOL} in @file{configure}
+@item My @file{configure} script has stuff like @samp{CY_GNU_GETTEXT} in it.
+This means that you have macros in your @file{configure.in} which should
+be defined in your @file{aclocal.m4} file, but aren't.  This usually
+means that @samp{aclocal} was not able to appropriate definitions of the
+macros.  Make sure that you have installed all the packages you need.
+In particular, make sure that you have installed libtool (this is where
+@samp{AM_PROG_LIBTOOL} is defined) and gettext (this is where
+@samp{CY_GNU_GETTEXT} is defined, at least in the Cygnus version of
+gettext).
+
+@cindex @file{Makefile}, garbage characters
+@item My @file{Makefile} has @samp{@@} characters in it.
+This may mean that you tried to use an autoconf substitution in your
+@file{Makefile.in} without adding the appropriate @samp{AC_SUBST} call
+to your @file{configure} script.  Or it may just mean that you need to
+rebuild @file{Makefile} in your build directory.  To rebuild
+@file{Makefile} from @file{Makefile.in}, run the shell script
+@file{config.status} with no arguments.  If you need to force
+@file{configure} to run again, first run @samp{config.status --recheck}.
+These runs are normally done automatically by @file{Makefile} targets,
+but if your @file{Makefile} has gotten messed up you'll need to help
+them along.
+
+@cindex @samp{config.status --recheck}
+@item Why do I have to run both @samp{config.status --recheck} and @samp{config.status}?
+Normally, you don't; they will be run automatically by @file{Makefile}
+targets.  If you do need to run them, use @samp{config.status --recheck}
+to run the @file{configure} script again with the same arguments as the
+first time you ran it.  Use @samp{config.status} (with no arguments) to
+regenerate all files (@file{Makefile}, @file{config.h}, etc.) based on
+the results of the configure script.  The two cases are separate because
+it isn't always necessary to regenerate all the files after running
+@samp{config.status --recheck}.  The @file{Makefile} targets generated
+by automake will use the environment variables @samp{CONFIG_FILES} and
+@samp{CONFIG_HEADERS} to only regenerate files as they are needed.
+
+@item What is the Cygnus tree?
+The Cygnus tree is used for various packages including gdb, the GNU
+binutils, and egcs.  It is also, of course, used for Cygnus releases.
+It is the build system which was developed at Cygnus, using the Cygnus
+configure script.  It permits building many different packages with a
+single configure and make.  The configure scripts in the tree are being
+converted to autoconf, but the general build structure remains intact.
+
+@item Why do I have to keep rebuilding and reinstalling the tools?
+I know, it's a pain.  Unfortunately, there are bugs in the tools
+themselves which need to be fixed, and each time that happens everybody
+who uses the tools need to reinstall new versions of them.  I don't know
+if there is going to be a clever fix until the tools stabilize.
+
+@item Why not just have a Cygnus tree @samp{make} target to update the tools?
+The tools unfortunately need to be installed before they can be used.
+That means that they must be built using an appropriate prefix, and it
+seems unwise to assume that every configuration uses an appropriate
+prefix.  It might be possible to make them work in place, or it might be
+possible to install them in some subdirectory; so far these approaches
+have not been implemented.
+@end table
+
+@node Index
+@unnumbered Index
+
+@printindex cp
+
+@contents
+@bye
diff --git a/etc/make-stds.texi b/etc/make-stds.texi
new file mode 100644 (file)
index 0000000..2149764
--- /dev/null
@@ -0,0 +1,914 @@
+@comment This file is included by both standards.texi and make.texinfo.
+@comment It was broken out of standards.texi on 1/6/93 by roland.
+
+@node Makefile Conventions
+@chapter Makefile Conventions
+@comment standards.texi does not print an index, but make.texinfo does.
+@cindex makefile, conventions for
+@cindex conventions for makefiles
+@cindex standards for makefiles
+
+This
+@ifinfo
+node
+@end ifinfo
+@iftex
+@ifset CODESTD
+section
+@end ifset
+@ifclear CODESTD
+chapter
+@end ifclear
+@end iftex
+describes conventions for writing the Makefiles for GNU programs.
+
+@menu
+* Makefile Basics::            General Conventions for Makefiles
+* Utilities in Makefiles::     Utilities in Makefiles
+* Command Variables::          Variables for Specifying Commands
+* Directory Variables::                Variables for Installation Directories
+* Standard Targets::           Standard Targets for Users
+* Install Command Categories::  Three categories of commands in the `install'
+                                  rule: normal, pre-install and post-install.
+@end menu
+
+@node Makefile Basics
+@section General Conventions for Makefiles
+
+Every Makefile should contain this line:
+
+@example
+SHELL = /bin/sh
+@end example
+
+@noindent
+to avoid trouble on systems where the @code{SHELL} variable might be
+inherited from the environment.  (This is never a problem with GNU
+@code{make}.)
+
+Different @code{make} programs have incompatible suffix lists and
+implicit rules, and this sometimes creates confusion or misbehavior.  So
+it is a good idea to set the suffix list explicitly using only the
+suffixes you need in the particular Makefile, like this:
+
+@example
+.SUFFIXES:
+.SUFFIXES: .c .o
+@end example
+
+@noindent
+The first line clears out the suffix list, the second introduces all
+suffixes which may be subject to implicit rules in this Makefile.
+
+Don't assume that @file{.} is in the path for command execution.  When
+you need to run programs that are a part of your package during the
+make, please make sure that it uses @file{./} if the program is built as
+part of the make or @file{$(srcdir)/} if the file is an unchanging part
+of the source code.  Without one of these prefixes, the current search
+path is used.
+
+The distinction between @file{./} (the @dfn{build directory}) and
+@file{$(srcdir)/} (the @dfn{source directory}) is important because
+users can build in a separate directory using the @samp{--srcdir} option
+to @file{configure}.  A rule of the form:
+
+@smallexample
+foo.1 : foo.man sedscript
+        sed -e sedscript foo.man > foo.1
+@end smallexample
+
+@noindent
+will fail when the build directory is not the source directory, because
+@file{foo.man} and @file{sedscript} are in the the source directory.
+
+When using GNU @code{make}, relying on @samp{VPATH} to find the source
+file will work in the case where there is a single dependency file,
+since the @code{make} automatic variable @samp{$<} will represent the
+source file wherever it is.  (Many versions of @code{make} set @samp{$<}
+only in implicit rules.)  A Makefile target like
+
+@smallexample
+foo.o : bar.c
+        $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o
+@end smallexample
+
+@noindent
+should instead be written as
+
+@smallexample
+foo.o : bar.c
+        $(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@@
+@end smallexample
+
+@noindent
+in order to allow @samp{VPATH} to work correctly.  When the target has
+multiple dependencies, using an explicit @samp{$(srcdir)} is the easiest
+way to make the rule work well.  For example, the target above for
+@file{foo.1} is best written as:
+
+@smallexample
+foo.1 : foo.man sedscript
+        sed -e $(srcdir)/sedscript $(srcdir)/foo.man > $@@
+@end smallexample
+
+GNU distributions usually contain some files which are not source
+files---for example, Info files, and the output from Autoconf, Automake,
+Bison or Flex.  Since these files normally appear in the source
+directory, they should always appear in the source directory, not in the
+build directory.  So Makefile rules to update them should put the
+updated files in the source directory.
+
+However, if a file does not appear in the distribution, then the
+Makefile should not put it in the source directory, because building a
+program in ordinary circumstances should not modify the source directory
+in any way.
+
+Try to make the build and installation targets, at least (and all their
+subtargets) work correctly with a parallel @code{make}.
+
+@node Utilities in Makefiles
+@section Utilities in Makefiles
+
+Write the Makefile commands (and any shell scripts, such as
+@code{configure}) to run in @code{sh}, not in @code{csh}.  Don't use any
+special features of @code{ksh} or @code{bash}.
+
+The @code{configure} script and the Makefile rules for building and
+installation should not use any utilities directly except these:
+
+@c dd find
+@c gunzip gzip md5sum
+@c mkfifo mknod tee uname 
+
+@example
+cat cmp cp diff echo egrep expr false grep install-info
+ln ls mkdir mv pwd rm rmdir sed sleep sort tar test touch true
+@end example
+
+The compression program @code{gzip} can be used in the @code{dist} rule.
+
+Stick to the generally supported options for these programs.  For
+example, don't use @samp{mkdir -p}, convenient as it may be, because
+most systems don't support it.
+
+It is a good idea to avoid creating symbolic links in makefiles, since a
+few systems don't support them.
+
+The Makefile rules for building and installation can also use compilers
+and related programs, but should do so via @code{make} variables so that the
+user can substitute alternatives.  Here are some of the programs we
+mean:
+
+@example
+ar bison cc flex install ld ldconfig lex
+make makeinfo ranlib texi2dvi yacc
+@end example
+
+Use the following @code{make} variables to run those programs:
+
+@example
+$(AR) $(BISON) $(CC) $(FLEX) $(INSTALL) $(LD) $(LDCONFIG) $(LEX)
+$(MAKE) $(MAKEINFO) $(RANLIB) $(TEXI2DVI) $(YACC)
+@end example
+
+When you use @code{ranlib} or @code{ldconfig}, you should make sure
+nothing bad happens if the system does not have the program in question.
+Arrange to ignore an error from that command, and print a message before
+the command to tell the user that failure of this command does not mean
+a problem.  (The Autoconf @samp{AC_PROG_RANLIB} macro can help with
+this.)
+
+If you use symbolic links, you should implement a fallback for systems
+that don't have symbolic links.
+
+Additional utilities that can be used via Make variables are:
+
+@example
+chgrp chmod chown mknod
+@end example
+
+It is ok to use other utilities in Makefile portions (or scripts)
+intended only for particular systems where you know those utilities
+exist.
+
+@node Command Variables
+@section Variables for Specifying Commands
+
+Makefiles should provide variables for overriding certain commands, options,
+and so on.
+
+In particular, you should run most utility programs via variables.
+Thus, if you use Bison, have a variable named @code{BISON} whose default
+value is set with @samp{BISON = bison}, and refer to it with
+@code{$(BISON)} whenever you need to use Bison.
+
+File management utilities such as @code{ln}, @code{rm}, @code{mv}, and
+so on, need not be referred to through variables in this way, since users
+don't need to replace them with other programs.
+
+Each program-name variable should come with an options variable that is
+used to supply options to the program.  Append @samp{FLAGS} to the
+program-name variable name to get the options variable name---for
+example, @code{BISONFLAGS}.  (The names @code{CFLAGS} for the C
+compiler, @code{YFLAGS} for yacc, and @code{LFLAGS} for lex, are
+exceptions to this rule, but we keep them because they are standard.)
+Use @code{CPPFLAGS} in any compilation command that runs the
+preprocessor, and use @code{LDFLAGS} in any compilation command that
+does linking as well as in any direct use of @code{ld}.
+
+If there are C compiler options that @emph{must} be used for proper
+compilation of certain files, do not include them in @code{CFLAGS}.
+Users expect to be able to specify @code{CFLAGS} freely themselves.
+Instead, arrange to pass the necessary options to the C compiler
+independently of @code{CFLAGS}, by writing them explicitly in the
+compilation commands or by defining an implicit rule, like this:
+
+@smallexample
+CFLAGS = -g
+ALL_CFLAGS = -I. $(CFLAGS)
+.c.o:
+        $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
+@end smallexample
+
+Do include the @samp{-g} option in @code{CFLAGS}, because that is not
+@emph{required} for proper compilation.  You can consider it a default
+that is only recommended.  If the package is set up so that it is
+compiled with GCC by default, then you might as well include @samp{-O}
+in the default value of @code{CFLAGS} as well.
+
+Put @code{CFLAGS} last in the compilation command, after other variables
+containing compiler options, so the user can use @code{CFLAGS} to
+override the others.
+
+@code{CFLAGS} should be used in every invocation of the C compiler,
+both those which do compilation and those which do linking.
+
+Every Makefile should define the variable @code{INSTALL}, which is the
+basic command for installing a file into the system.
+
+Every Makefile should also define the variables @code{INSTALL_PROGRAM}
+and @code{INSTALL_DATA}.  (The default for each of these should be
+@code{$(INSTALL)}.)  Then it should use those variables as the commands
+for actual installation, for executables and nonexecutables
+respectively.  Use these variables as follows:
+
+@example
+$(INSTALL_PROGRAM) foo $(bindir)/foo
+$(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a
+@end example
+
+Optionally, you may prepend the value of @code{DESTDIR} to the target
+filename.  Doing this allows the installer to create a snapshot of the
+installation to be copied onto the real target filesystem later.  Do not
+set the value of @code{DESTDIR} in your Makefile, and do not include it
+in any installed files.  With support for @code{DESTDIR}, the above
+examples become:
+
+@example
+$(INSTALL_PROGRAM) foo $(DESTDIR)$(bindir)/foo
+$(INSTALL_DATA) libfoo.a $(DESTDIR)$(libdir)/libfoo.a
+@end example
+
+@noindent
+Always use a file name, not a directory name, as the second argument of
+the installation commands.  Use a separate command for each file to be
+installed.
+
+@node Directory Variables
+@section Variables for Installation Directories
+
+Installation directories should always be named by variables, so it is
+easy to install in a nonstandard place.  The standard names for these
+variables are described below.  They are based on a standard filesystem
+layout; variants of it are used in SVR4, 4.4BSD, Linux, Ultrix v4, and
+other modern operating systems.
+
+These two variables set the root for the installation.  All the other
+installation directories should be subdirectories of one of these two,
+and nothing should be directly installed into these two directories.
+
+@table @samp
+@item prefix
+A prefix used in constructing the default values of the variables listed
+below.  The default value of @code{prefix} should be @file{/usr/local}.
+When building the complete GNU system, the prefix will be empty and
+@file{/usr} will be a symbolic link to @file{/}.
+(If you are using Autoconf, write it as @samp{@@prefix@@}.)
+
+Running @samp{make install} with a different value of @code{prefix}
+from the one used to build the program should @var{not} recompile
+the program.
+
+@item exec_prefix
+A prefix used in constructing the default values of some of the
+variables listed below.  The default value of @code{exec_prefix} should
+be @code{$(prefix)}.
+(If you are using Autoconf, write it as @samp{@@exec_prefix@@}.)
+
+Generally, @code{$(exec_prefix)} is used for directories that contain
+machine-specific files (such as executables and subroutine libraries),
+while @code{$(prefix)} is used directly for other directories.
+
+Running @samp{make install} with a different value of @code{exec_prefix}
+from the one used to build the program should @var{not} recompile the
+program.
+@end table
+
+Executable programs are installed in one of the following directories.
+
+@table @samp
+@item bindir
+The directory for installing executable programs that users can run.
+This should normally be @file{/usr/local/bin}, but write it as
+@file{$(exec_prefix)/bin}.
+(If you are using Autoconf, write it as @samp{@@bindir@@}.)
+
+@item sbindir
+The directory for installing executable programs that can be run from
+the shell, but are only generally useful to system administrators.  This
+should normally be @file{/usr/local/sbin}, but write it as
+@file{$(exec_prefix)/sbin}.
+(If you are using Autoconf, write it as @samp{@@sbindir@@}.)
+
+@item libexecdir
+@comment This paragraph adjusted to avoid overfull hbox --roland 5jul94
+The directory for installing executable programs to be run by other
+programs rather than by users.  This directory should normally be
+@file{/usr/local/libexec}, but write it as @file{$(exec_prefix)/libexec}.
+(If you are using Autoconf, write it as @samp{@@libexecdir@@}.)
+@end table
+
+Data files used by the program during its execution are divided into
+categories in two ways.
+
+@itemize @bullet
+@item
+Some files are normally modified by programs; others are never normally
+modified (though users may edit some of these).
+
+@item
+Some files are architecture-independent and can be shared by all
+machines at a site; some are architecture-dependent and can be shared
+only by machines of the same kind and operating system; others may never
+be shared between two machines.
+@end itemize
+
+This makes for six different possibilities.  However, we want to
+discourage the use of architecture-dependent files, aside from object
+files and libraries.  It is much cleaner to make other data files
+architecture-independent, and it is generally not hard.
+
+Therefore, here are the variables Makefiles should use to specify
+directories:
+
+@table @samp
+@item datadir
+The directory for installing read-only architecture independent data
+files.  This should normally be @file{/usr/local/share}, but write it as
+@file{$(prefix)/share}.
+(If you are using Autoconf, write it as @samp{@@datadir@@}.)
+As a special exception, see @file{$(infodir)}
+and @file{$(includedir)} below.
+
+@item sysconfdir
+The directory for installing read-only data files that pertain to a
+single machine--that is to say, files for configuring a host.  Mailer
+and network configuration files, @file{/etc/passwd}, and so forth belong
+here.  All the files in this directory should be ordinary ASCII text
+files.  This directory should normally be @file{/usr/local/etc}, but
+write it as @file{$(prefix)/etc}.
+(If you are using Autoconf, write it as @samp{@@sysconfdir@@}.)
+
+Do not install executables here in this directory (they probably belong
+in @file{$(libexecdir)} or @file{$(sbindir)}).  Also do not install
+files that are modified in the normal course of their use (programs
+whose purpose is to change the configuration of the system excluded).
+Those probably belong in @file{$(localstatedir)}.
+
+@item sharedstatedir
+The directory for installing architecture-independent data files which
+the programs modify while they run.  This should normally be
+@file{/usr/local/com}, but write it as @file{$(prefix)/com}.
+(If you are using Autoconf, write it as @samp{@@sharedstatedir@@}.)
+
+@item localstatedir
+The directory for installing data files which the programs modify while
+they run, and that pertain to one specific machine.  Users should never
+need to modify files in this directory to configure the package's
+operation; put such configuration information in separate files that go
+in @file{$(datadir)} or @file{$(sysconfdir)}.  @file{$(localstatedir)}
+should normally be @file{/usr/local/var}, but write it as
+@file{$(prefix)/var}.
+(If you are using Autoconf, write it as @samp{@@localstatedir@@}.)
+
+@item libdir
+The directory for object files and libraries of object code.  Do not
+install executables here, they probably ought to go in @file{$(libexecdir)}
+instead.  The value of @code{libdir} should normally be
+@file{/usr/local/lib}, but write it as @file{$(exec_prefix)/lib}.
+(If you are using Autoconf, write it as @samp{@@libdir@@}.)
+
+@item infodir
+The directory for installing the Info files for this package.  By
+default, it should be @file{/usr/local/info}, but it should be written
+as @file{$(prefix)/info}.
+(If you are using Autoconf, write it as @samp{@@infodir@@}.)
+
+@item lispdir
+The directory for installing any Emacs Lisp files in this package.  By
+default, it should be @file{/usr/local/share/emacs/site-lisp}, but it
+should be written as @file{$(prefix)/share/emacs/site-lisp}.
+
+If you are using Autoconf, write the default as @samp{@@lispdir@@}.
+In order to make @samp{@@lispdir@@} work, you need the following lines
+in your @file{configure.in} file:
+
+@example
+lispdir='$@{datadir@}/emacs/site-lisp'
+AC_SUBST(lispdir)
+@end example
+
+@item includedir
+@c rewritten to avoid overfull hbox --roland
+The directory for installing header files to be included by user
+programs with the C @samp{#include} preprocessor directive.  This
+should normally be @file{/usr/local/include}, but write it as
+@file{$(prefix)/include}.
+(If you are using Autoconf, write it as @samp{@@includedir@@}.)
+
+Most compilers other than GCC do not look for header files in directory
+@file{/usr/local/include}.  So installing the header files this way is
+only useful with GCC.  Sometimes this is not a problem because some
+libraries are only really intended to work with GCC.  But some libraries
+are intended to work with other compilers.  They should install their
+header files in two places, one specified by @code{includedir} and one
+specified by @code{oldincludedir}.
+
+@item oldincludedir
+The directory for installing @samp{#include} header files for use with
+compilers other than GCC.  This should normally be @file{/usr/include}.
+(If you are using Autoconf, you can write it as @samp{@@oldincludedir@@}.)
+
+The Makefile commands should check whether the value of
+@code{oldincludedir} is empty.  If it is, they should not try to use
+it; they should cancel the second installation of the header files.
+
+A package should not replace an existing header in this directory unless
+the header came from the same package.  Thus, if your Foo package
+provides a header file @file{foo.h}, then it should install the header
+file in the @code{oldincludedir} directory if either (1) there is no
+@file{foo.h} there or (2) the @file{foo.h} that exists came from the Foo
+package.
+
+To tell whether @file{foo.h} came from the Foo package, put a magic
+string in the file---part of a comment---and @code{grep} for that string.
+@end table
+
+Unix-style man pages are installed in one of the following:
+
+@table @samp
+@item mandir
+The top-level directory for installing the man pages (if any) for this
+package.  It will normally be @file{/usr/local/man}, but you should
+write it as @file{$(prefix)/man}.
+(If you are using Autoconf, write it as @samp{@@mandir@@}.)
+
+@item man1dir
+The directory for installing section 1 man pages.  Write it as
+@file{$(mandir)/man1}.
+@item man2dir
+The directory for installing section 2 man pages.  Write it as
+@file{$(mandir)/man2}
+@item @dots{}
+
+@strong{Don't make the primary documentation for any GNU software be a
+man page.  Write a manual in Texinfo instead.  Man pages are just for
+the sake of people running GNU software on Unix, which is a secondary
+application only.}
+
+@item manext
+The file name extension for the installed man page.  This should contain
+a period followed by the appropriate digit; it should normally be @samp{.1}.
+
+@item man1ext
+The file name extension for installed section 1 man pages.
+@item man2ext
+The file name extension for installed section 2 man pages.
+@item @dots{}
+Use these names instead of @samp{manext} if the package needs to install man
+pages in more than one section of the manual.
+@end table
+
+And finally, you should set the following variable:
+
+@table @samp
+@item srcdir
+The directory for the sources being compiled.  The value of this
+variable is normally inserted by the @code{configure} shell script.
+(If you are using Autconf, use @samp{srcdir = @@srcdir@@}.)
+@end table
+
+For example:
+
+@smallexample
+@c I have changed some of the comments here slightly to fix an overfull
+@c hbox, so the make manual can format correctly. --roland
+# Common prefix for installation directories.
+# NOTE: This directory must exist when you start the install.
+prefix = /usr/local
+exec_prefix = $(prefix)
+# Where to put the executable for the command `gcc'.
+bindir = $(exec_prefix)/bin
+# Where to put the directories used by the compiler.
+libexecdir = $(exec_prefix)/libexec
+# Where to put the Info files.
+infodir = $(prefix)/info
+@end smallexample
+
+If your program installs a large number of files into one of the
+standard user-specified directories, it might be useful to group them
+into a subdirectory particular to that program.  If you do this, you
+should write the @code{install} rule to create these subdirectories.
+
+Do not expect the user to include the subdirectory name in the value of
+any of the variables listed above.  The idea of having a uniform set of
+variable names for installation directories is to enable the user to
+specify the exact same values for several different GNU packages.  In
+order for this to be useful, all the packages must be designed so that
+they will work sensibly when the user does so.
+
+@node Standard Targets
+@section Standard Targets for Users
+
+All GNU programs should have the following targets in their Makefiles:
+
+@table @samp
+@item all
+Compile the entire program.  This should be the default target.  This
+target need not rebuild any documentation files; Info files should
+normally be included in the distribution, and DVI files should be made
+only when explicitly asked for.
+
+By default, the Make rules should compile and link with @samp{-g}, so
+that executable programs have debugging symbols.  Users who don't mind
+being helpless can strip the executables later if they wish.
+
+@item install
+Compile the program and copy the executables, libraries, and so on to
+the file names where they should reside for actual use.  If there is a
+simple test to verify that a program is properly installed, this target
+should run that test.
+
+Do not strip executables when installing them.  Devil-may-care users can
+use the @code{install-strip} target to do that.
+
+If possible, write the @code{install} target rule so that it does not
+modify anything in the directory where the program was built, provided
+@samp{make all} has just been done.  This is convenient for building the
+program under one user name and installing it under another.
+
+The commands should create all the directories in which files are to be
+installed, if they don't already exist.  This includes the directories
+specified as the values of the variables @code{prefix} and
+@code{exec_prefix}, as well as all subdirectories that are needed.
+One way to do this is by means of an @code{installdirs} target
+as described below.
+
+Use @samp{-} before any command for installing a man page, so that
+@code{make} will ignore any errors.  This is in case there are systems
+that don't have the Unix man page documentation system installed.
+
+The way to install Info files is to copy them into @file{$(infodir)}
+with @code{$(INSTALL_DATA)} (@pxref{Command Variables}), and then run
+the @code{install-info} program if it is present.  @code{install-info}
+is a program that edits the Info @file{dir} file to add or update the
+menu entry for the given Info file; it is part of the Texinfo package.
+Here is a sample rule to install an Info file:
+
+@comment This example has been carefully formatted for the Make manual.
+@comment Please do not reformat it without talking to roland@gnu.ai.mit.edu.
+@smallexample
+$(DESTDIR)$(infodir)/foo.info: foo.info
+        $(POST_INSTALL)
+# There may be a newer info file in . than in srcdir.
+        -if test -f foo.info; then d=.; \
+         else d=$(srcdir); fi; \
+        $(INSTALL_DATA) $$d/foo.info $(DESTDIR)$@@; \
+# Run install-info only if it exists.
+# Use `if' instead of just prepending `-' to the
+# line so we notice real errors from install-info.
+# We use `$(SHELL) -c' because some shells do not
+# fail gracefully when there is an unknown command.
+        if $(SHELL) -c 'install-info --version' \
+           >/dev/null 2>&1; then \
+          install-info --dir-file=$(DESTDIR)$(infodir)/dir \
+                       $(DESTDIR)$(infodir)/foo.info; \
+        else true; fi
+@end smallexample
+
+When writing the @code{install} target, you must classify all the
+commands into three categories: normal ones, @dfn{pre-installation}
+commands and @dfn{post-installation} commands.  @xref{Install Command
+Categories}.
+
+@item uninstall
+Delete all the installed files---the copies that the @samp{install}
+target creates.
+
+This rule should not modify the directories where compilation is done,
+only the directories where files are installed.
+
+The uninstallation commands are divided into three categories, just like
+the installation commands.  @xref{Install Command Categories}.
+
+@item install-strip
+Like @code{install}, but strip the executable files while installing
+them.  In many cases, the definition of this target can be very simple:
+
+@smallexample
+install-strip:
+        $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
+                install
+@end smallexample
+
+Normally we do not recommend stripping an executable unless you are sure
+the program has no bugs.  However, it can be reasonable to install a
+stripped executable for actual execution while saving the unstripped
+executable elsewhere in case there is a bug.
+
+@comment The gratuitous blank line here is to make the table look better
+@comment in the printed Make manual.  Please leave it in.
+@item clean
+
+Delete all files from the current directory that are normally created by
+building the program.  Don't delete the files that record the
+configuration.  Also preserve files that could be made by building, but
+normally aren't because the distribution comes with them.
+
+Delete @file{.dvi} files here if they are not part of the distribution.
+
+@item distclean
+Delete all files from the current directory that are created by
+configuring or building the program.  If you have unpacked the source
+and built the program without creating any other files, @samp{make
+distclean} should leave only the files that were in the distribution.
+
+@item mostlyclean
+Like @samp{clean}, but may refrain from deleting a few files that people
+normally don't want to recompile.  For example, the @samp{mostlyclean}
+target for GCC does not delete @file{libgcc.a}, because recompiling it
+is rarely necessary and takes a lot of time.
+
+@item maintainer-clean
+Delete almost everything from the current directory that can be
+reconstructed with this Makefile.  This typically includes everything
+deleted by @code{distclean}, plus more: C source files produced by
+Bison, tags tables, Info files, and so on.
+
+The reason we say ``almost everything'' is that running the command
+@samp{make maintainer-clean} should not delete @file{configure} even if
+@file{configure} can be remade using a rule in the Makefile.  More generally,
+@samp{make maintainer-clean} should not delete anything that needs to
+exist in order to run @file{configure} and then begin to build the
+program.  This is the only exception; @code{maintainer-clean} should
+delete everything else that can be rebuilt.
+
+The @samp{maintainer-clean} target is intended to be used by a maintainer of
+the package, not by ordinary users.  You may need special tools to
+reconstruct some of the files that @samp{make maintainer-clean} deletes.
+Since these files are normally included in the distribution, we don't
+take care to make them easy to reconstruct.  If you find you need to
+unpack the full distribution again, don't blame us.
+
+To help make users aware of this, the commands for the special
+@code{maintainer-clean} target should start with these two:
+
+@smallexample
+@@echo 'This command is intended for maintainers to use; it'
+@@echo 'deletes files that may need special tools to rebuild.'
+@end smallexample
+
+@item TAGS
+Update a tags table for this program.
+@c ADR: how?
+
+@item info
+Generate any Info files needed.  The best way to write the rules is as
+follows:
+
+@smallexample
+info: foo.info
+
+foo.info: foo.texi chap1.texi chap2.texi
+        $(MAKEINFO) $(srcdir)/foo.texi
+@end smallexample
+
+@noindent
+You must define the variable @code{MAKEINFO} in the Makefile.  It should
+run the @code{makeinfo} program, which is part of the Texinfo
+distribution.
+
+Normally a GNU distribution comes with Info files, and that means the
+Info files are present in the source directory.  Therefore, the Make
+rule for an info file should update it in the source directory.  When
+users build the package, ordinarily Make will not update the Info files
+because they will already be up to date.
+
+@item dvi
+Generate DVI files for all Texinfo documentation.
+For example:
+
+@smallexample
+dvi: foo.dvi
+
+foo.dvi: foo.texi chap1.texi chap2.texi
+        $(TEXI2DVI) $(srcdir)/foo.texi
+@end smallexample
+
+@noindent
+You must define the variable @code{TEXI2DVI} in the Makefile.  It should
+run the program @code{texi2dvi}, which is part of the Texinfo
+distribution.@footnote{@code{texi2dvi} uses @TeX{} to do the real work
+of formatting. @TeX{} is not distributed with Texinfo.}  Alternatively,
+write just the dependencies, and allow GNU @code{make} to provide the command.
+
+@item dist
+Create a distribution tar file for this program.  The tar file should be
+set up so that the file names in the tar file start with a subdirectory
+name which is the name of the package it is a distribution for.  This
+name can include the version number.
+
+For example, the distribution tar file of GCC version 1.40 unpacks into
+a subdirectory named @file{gcc-1.40}.
+
+The easiest way to do this is to create a subdirectory appropriately
+named, use @code{ln} or @code{cp} to install the proper files in it, and
+then @code{tar} that subdirectory.
+
+Compress the tar file file with @code{gzip}.  For example, the actual
+distribution file for GCC version 1.40 is called @file{gcc-1.40.tar.gz}.
+
+The @code{dist} target should explicitly depend on all non-source files
+that are in the distribution, to make sure they are up to date in the
+distribution.
+@ifset CODESTD
+@xref{Releases, , Making Releases}.
+@end ifset
+@ifclear CODESTD
+@xref{Releases, , Making Releases, standards, GNU Coding Standards}.
+@end ifclear
+
+@item check
+Perform self-tests (if any).  The user must build the program before
+running the tests, but need not install the program; you should write
+the self-tests so that they work when the program is built but not
+installed.
+@end table
+
+The following targets are suggested as conventional names, for programs
+in which they are useful.
+
+@table @code
+@item installcheck
+Perform installation tests (if any).  The user must build and install
+the program before running the tests.  You should not assume that
+@file{$(bindir)} is in the search path.
+
+@item installdirs
+It's useful to add a target named @samp{installdirs} to create the
+directories where files are installed, and their parent directories.
+There is a script called @file{mkinstalldirs} which is convenient for
+this; you can find it in the Texinfo package.
+@c It's in /gd/gnu/lib/mkinstalldirs.
+You can use a rule like this:
+
+@comment This has been carefully formatted to look decent in the Make manual.
+@comment Please be sure not to make it extend any further to the right.--roland
+@smallexample
+# Make sure all installation directories (e.g. $(bindir))
+# actually exist by making them if necessary.
+installdirs: mkinstalldirs
+        $(srcdir)/mkinstalldirs $(bindir) $(datadir) \
+                                $(libdir) $(infodir) \
+                                $(mandir)
+@end smallexample
+
+This rule should not modify the directories where compilation is done.
+It should do nothing but create installation directories.
+@end table
+
+@node Install Command Categories
+@section Install Command Categories
+
+@cindex pre-installation commands
+@cindex post-installation commands
+When writing the @code{install} target, you must classify all the
+commands into three categories: normal ones, @dfn{pre-installation}
+commands and @dfn{post-installation} commands.
+
+Normal commands move files into their proper places, and set their
+modes.  They may not alter any files except the ones that come entirely
+from the package they belong to.
+
+Pre-installation and post-installation commands may alter other files;
+in particular, they can edit global configuration files or data bases.
+
+Pre-installation commands are typically executed before the normal
+commands, and post-installation commands are typically run after the
+normal commands.
+
+The most common use for a post-installation command is to run
+@code{install-info}.  This cannot be done with a normal command, since
+it alters a file (the Info directory) which does not come entirely and
+solely from the package being installed.  It is a post-installation
+command because it needs to be done after the normal command which
+installs the package's Info files.
+
+Most programs don't need any pre-installation commands, but we have the
+feature just in case it is needed.
+
+To classify the commands in the @code{install} rule into these three
+categories, insert @dfn{category lines} among them.  A category line
+specifies the category for the commands that follow.
+
+A category line consists of a tab and a reference to a special Make
+variable, plus an optional comment at the end.  There are three
+variables you can use, one for each category; the variable name
+specifies the category.  Category lines are no-ops in ordinary execution
+because these three Make variables are normally undefined (and you
+@emph{should not} define them in the makefile).
+
+Here are the three possible category lines, each with a comment that
+explains what it means:
+
+@smallexample
+        $(PRE_INSTALL)     # @r{Pre-install commands follow.}
+        $(POST_INSTALL)    # @r{Post-install commands follow.}
+        $(NORMAL_INSTALL)  # @r{Normal commands follow.}
+@end smallexample
+
+If you don't use a category line at the beginning of the @code{install}
+rule, all the commands are classified as normal until the first category
+line.  If you don't use any category lines, all the commands are
+classified as normal.
+
+These are the category lines for @code{uninstall}:
+
+@smallexample
+        $(PRE_UNINSTALL)     # @r{Pre-uninstall commands follow.}
+        $(POST_UNINSTALL)    # @r{Post-uninstall commands follow.}
+        $(NORMAL_UNINSTALL)  # @r{Normal commands follow.}
+@end smallexample
+
+Typically, a pre-uninstall command would be used for deleting entries
+from the Info directory.
+
+If the @code{install} or @code{uninstall} target has any dependencies
+which act as subroutines of installation, then you should start
+@emph{each} dependency's commands with a category line, and start the
+main target's commands with a category line also.  This way, you can
+ensure that each command is placed in the right category regardless of
+which of the dependencies actually run.
+
+Pre-installation and post-installation commands should not run any
+programs except for these:
+
+@example
+[ basename bash cat chgrp chmod chown cmp cp dd diff echo
+egrep expand expr false fgrep find getopt grep gunzip gzip
+hostname install install-info kill ldconfig ln ls md5sum
+mkdir mkfifo mknod mv printenv pwd rm rmdir sed sort tee
+test touch true uname xargs yes
+@end example
+
+@cindex binary packages
+The reason for distinguishing the commands in this way is for the sake
+of making binary packages.  Typically a binary package contains all the
+executables and other files that need to be installed, and has its own
+method of installing them---so it does not need to run the normal
+installation commands.  But installing the binary package does need to
+execute the pre-installation and post-installation commands.
+
+Programs to build binary packages work by extracting the
+pre-installation and post-installation commands.  Here is one way of
+extracting the pre-installation commands:
+
+@smallexample
+make -n install -o all \
+      PRE_INSTALL=pre-install \
+      POST_INSTALL=post-install \
+      NORMAL_INSTALL=normal-install \
+  | gawk -f pre-install.awk
+@end smallexample
+
+@noindent
+where the file @file{pre-install.awk} could contain this:
+
+@smallexample
+$0 ~ /^\t[ \t]*(normal_install|post_install)[ \t]*$/ @{on = 0@}
+on @{print $0@}
+$0 ~ /^\t[ \t]*pre_install[ \t]*$/ @{on = 1@}
+@end smallexample
+
+The resulting file of pre-installation commands is executed as a shell
+script as part of installing the binary package.
diff --git a/etc/standards.texi b/etc/standards.texi
new file mode 100644 (file)
index 0000000..910bf8b
--- /dev/null
@@ -0,0 +1,3093 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename standards.info
+@settitle GNU Coding Standards
+@c This date is automagically updated when you save this file:
+@set lastupdate March 13, 1998
+@c %**end of header
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Standards: (standards).        GNU coding standards.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@c @setchapternewpage odd
+@setchapternewpage off
+
+@c This is used by a cross ref in make-stds.texi
+@set CODESTD  1
+@iftex
+@set CHAPTER chapter
+@end iftex
+@ifinfo
+@set CHAPTER node
+@end ifinfo
+
+@ifinfo
+GNU Coding Standards
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Free Software Foundation.
+@end ifinfo
+
+@titlepage
+@title GNU Coding Standards
+@author Richard Stallman
+@author last updated @value{lastupdate}
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992, 1993, 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Free Software Foundation.
+@end titlepage
+
+@ifinfo
+@node Top, Preface, (dir), (dir)
+@top Version
+
+Last updated @value{lastupdate}.
+@end ifinfo
+
+@menu
+* Preface::                     About the GNU Coding Standards
+* Intellectual Property::       Keeping Free Software Free
+* Design Advice::               General Program Design
+* Program Behavior::            Program Behavior for All Programs
+* Writing C::                   Making The Best Use of C
+* Documentation::               Documenting Programs
+* Managing Releases::           The Release Process
+@end menu
+
+@node Preface
+@chapter About the GNU Coding Standards
+
+The GNU Coding Standards were written by Richard Stallman and other GNU
+Project volunteers.  Their purpose is to make the GNU system clean,
+consistent, and easy to install.  This document can also be read as a
+guide to writing portable, robust and reliable programs.  It focuses on
+programs written in C, but many of the rules and principles are useful
+even if you write in another programming language.  The rules often
+state reasons for writing in a certain way.
+
+Corrections or suggestions for this document should be sent to
+@email{gnu@@gnu.org}.  If you make a suggestion, please include a
+suggested new wording for it; our time is limited.  We prefer a context
+diff to the @file{standards.texi} or @file{make-stds.texi} files, but if
+you don't have those files, please mail your suggestion anyway.
+
+This release of the GNU Coding Standards was last updated
+@value{lastupdate}.
+
+@node Intellectual Property
+@chapter Keeping Free Software Free
+
+This @value{CHAPTER} discusses how you can make sure that GNU software
+remains unencumbered.
+
+@menu
+* Reading Non-Free Code::       Referring to Proprietary Programs
+* Contributions::               Accepting Contributions
+@end menu
+
+@node Reading Non-Free Code
+@section Referring to Proprietary Programs
+
+Don't in any circumstances refer to Unix source code for or during
+your work on GNU!  (Or to any other proprietary programs.)
+
+If you have a vague recollection of the internals of a Unix program,
+this does not absolutely mean you can't write an imitation of it, but
+do try to organize the imitation internally along different lines,
+because this is likely to make the details of the Unix version
+irrelevant and dissimilar to your results.
+
+For example, Unix utilities were generally optimized to minimize
+memory use; if you go for speed instead, your program will be very
+different.  You could keep the entire input file in core and scan it
+there instead of using stdio.  Use a smarter algorithm discovered more
+recently than the Unix program.  Eliminate use of temporary files.  Do
+it in one pass instead of two (we did this in the assembler).
+
+Or, on the contrary, emphasize simplicity instead of speed.  For some
+applications, the speed of today's computers makes simpler algorithms
+adequate.
+
+Or go for generality.  For example, Unix programs often have static
+tables or fixed-size strings, which make for arbitrary limits; use
+dynamic allocation instead.  Make sure your program handles NULs and
+other funny characters in the input files.  Add a programming language
+for extensibility and write part of the program in that language.
+
+Or turn some parts of the program into independently usable libraries.
+Or use a simple garbage collector instead of tracking precisely when
+to free memory, or use a new GNU facility such as obstacks.
+
+
+@node Contributions
+@section Accepting Contributions
+
+If someone else sends you a piece of code to add to the program you are
+working on, we need legal papers to use it---the same sort of legal
+papers we will need to get from you.  @emph{Each} significant
+contributor to a program must sign some sort of legal papers in order
+for us to have clear title to the program.  The main author alone is not
+enough.
+
+So, before adding in any contributions from other people, please tell
+us, so we can arrange to get the papers.  Then wait until we tell you
+that we have received the signed papers, before you actually use the
+contribution.
+
+This applies both before you release the program and afterward.  If
+you receive diffs to fix a bug, and they make significant changes, we
+need legal papers for that change.
+
+This also applies to comments and documentation files.  For copyright
+law, comments and code are just text.  Copyright applies to all kinds of
+text, so we need legal papers for all kinds.
+
+You don't need papers for changes of a few lines here or there, since
+they are not significant for copyright purposes.  Also, you don't need
+papers if all you get from the suggestion is some ideas, not actual code
+which you use.  For example, if you write a different solution to the
+problem, you don't need to get papers.
+
+We know this is frustrating; it's frustrating for us as well.  But if
+you don't wait, you are going out on a limb---for example, what if the
+contributor's employer won't sign a disclaimer?  You might have to take
+that code out again!
+
+The very worst thing is if you forget to tell us about the other
+contributor.  We could be very embarrassed in court some day as a
+result.
+
+We have more detailed advice for maintainers of programs; if you have
+reached the stage of actually maintaining a program for GNU (whether
+released or not), please ask us for a copy.
+
+@node Design Advice
+@chapter General Program Design
+
+This @value{CHAPTER} discusses some of the issues you should take into
+account when designing your program.
+
+@menu
+* Compatibility::               Compatibility with other implementations
+* Using Extensions::            Using non-standard features
+* ANSI C::                      Using ANSI C features
+* Source Language::             Using languages other than C
+@end menu
+
+@node Compatibility
+@section Compatibility with Other Implementations
+
+With occasional exceptions, utility programs and libraries for GNU
+should be upward compatible with those in Berkeley Unix, and upward
+compatible with @sc{ansi} C if @sc{ansi} C specifies their behavior, and
+upward compatible with @sc{POSIX} if @sc{POSIX} specifies their
+behavior.
+
+When these standards conflict, it is useful to offer compatibility
+modes for each of them.
+
+@sc{ansi} C and @sc{POSIX} prohibit many kinds of extensions.  Feel free
+to make the extensions anyway, and include a @samp{--ansi},
+@samp{--posix}, or @samp{--compatible} option to turn them off.
+However, if the extension has a significant chance of breaking any real
+programs or scripts, then it is not really upward compatible.  Try to
+redesign its interface.
+
+Many GNU programs suppress extensions that conflict with POSIX if the
+environment variable @code{POSIXLY_CORRECT} is defined (even if it is
+defined with a null value).  Please make your program recognize this
+variable if appropriate.
+
+When a feature is used only by users (not by programs or command
+files), and it is done poorly in Unix, feel free to replace it
+completely with something totally different and better.  (For example,
+@code{vi} is replaced with Emacs.)  But it is nice to offer a compatible
+feature as well.  (There is a free @code{vi} clone, so we offer it.)
+
+Additional useful features not in Berkeley Unix are welcome.
+
+@node Using Extensions
+@section Using Non-standard Features
+
+Many GNU facilities that already exist support a number of convenient
+extensions over the comparable Unix facilities.  Whether to use these
+extensions in implementing your program is a difficult question.
+
+On the one hand, using the extensions can make a cleaner program.
+On the other hand, people will not be able to build the program
+unless the other GNU tools are available.  This might cause the
+program to work on fewer kinds of machines.
+
+With some extensions, it might be easy to provide both alternatives.
+For example, you can define functions with a ``keyword'' @code{INLINE}
+and define that as a macro to expand into either @code{inline} or
+nothing, depending on the compiler.
+
+In general, perhaps it is best not to use the extensions if you can
+straightforwardly do without them, but to use the extensions if they
+are a big improvement.
+
+An exception to this rule are the large, established programs (such as
+Emacs) which run on a great variety of systems.  Such programs would
+be broken by use of GNU extensions.
+
+Another exception is for programs that are used as part of
+compilation: anything that must be compiled with other compilers in
+order to bootstrap the GNU compilation facilities.  If these require
+the GNU compiler, then no one can compile them without having them
+installed already.  That would be no good.
+
+@node ANSI C
+@section @sc{ansi} C and pre-@sc{ansi} C
+
+Do not ever use the ``trigraph'' feature of @sc{ansi} C.
+
+@sc{ansi} C is widespread enough now that it is ok to write new programs
+that use @sc{ansi} C features (and therefore will not work in
+non-@sc{ansi} compilers).  And if a program is already written in
+@sc{ansi} C, there's no need to convert it to support non-@sc{ansi}
+compilers.
+
+However, it is easy to support non-@sc{ansi} compilers in most programs,
+so you might still consider doing so when you write a program.  Instead
+of writing function definitions in @sc{ansi} prototype form,
+
+@example
+int
+foo (int x, int y)
+@dots{}
+@end example
+
+@noindent
+write the definition in pre-@sc{ansi} style like this,
+
+@example
+int
+foo (x, y)
+     int x, y;
+@dots{}
+@end example
+
+@noindent
+and use a separate declaration to specify the argument prototype:
+
+@example
+int foo (int, int);
+@end example
+
+You need such a declaration anyway, in a header file, to get the benefit
+of @sc{ansi} C prototypes in all the files where the function is called.
+And once you have it, you lose nothing by writing the function
+definition in the pre-@sc{ansi} style.
+
+If you don't know non-@sc{ansi} C, there's no need to learn it; just
+write in @sc{ansi} C.
+
+@node Source Language
+@section Using Languages Other Than C
+
+Using a language other than C is like using a non-standard feature: it
+will cause trouble for users.  Even if GCC supports the other language,
+users may find it inconvenient to have to install the compiler for that
+other language in order to build your program.  For example, if you
+write your program in C++, people will have to install the C++ compiler
+in order to compile your program.  Thus, it is better if you write in C.
+
+But there are three situations when there is no disadvantage in using
+some other language:
+
+@itemize @bullet
+@item
+It is okay to use another language if your program contains an
+interpreter for that language.
+
+For example, if your program links with GUILE, it is ok to write part of
+the program in Scheme or another language supported by GUILE.
+
+@item
+It is okay to use another language in a tool specifically intended for
+use with that language.
+
+This is okay because the only people who want to build the tool will be
+those who have installed the other language anyway.
+
+@item
+If an application is of interest to a narrow community, then perhaps
+it's not important if the application is inconvenient to install.
+@end itemize
+
+C has one other advantage over C++ and other compiled languages: more
+people know C, so more people will find it easy to read and modify the
+program if it is written in C.
+
+@node Program Behavior
+@chapter Program Behavior for All Programs
+
+This @value{CHAPTER} describes how to write robust software. It also
+describes general standards for error messages, the command line interface,
+and how libraries should behave.
+
+@menu
+* Semantics::                   Writing robust programs
+* Libraries::                   Library behavior
+* Errors::                      Formatting error messages
+* User Interfaces::             Standards for command line interfaces
+* Option Table::                Table of long options.
+* Memory Usage::                When and how to care about memory needs
+@end menu
+
+@node Semantics
+@section Writing Robust Programs
+
+Avoid arbitrary limits on the length or number of @emph{any} data
+structure, including file names, lines, files, and symbols, by allocating
+all data structures dynamically.  In most Unix utilities, ``long lines
+are silently truncated''.  This is not acceptable in a GNU utility.
+
+Utilities reading files should not drop NUL characters, or any other
+nonprinting characters @emph{including those with codes above 0177}.  The
+only sensible exceptions would be utilities specifically intended for
+interface to certain types of printers that can't handle those characters.
+
+Check every system call for an error return, unless you know you wish to
+ignore errors.  Include the system error text (from @code{perror} or
+equivalent) in @emph{every} error message resulting from a failing
+system call, as well as the name of the file if any and the name of the
+utility.  Just ``cannot open foo.c'' or ``stat failed'' is not
+sufficient.
+
+Check every call to @code{malloc} or @code{realloc} to see if it
+returned zero.  Check @code{realloc} even if you are making the block
+smaller; in a system that rounds block sizes to a power of 2,
+@code{realloc} may get a different block if you ask for less space.
+
+In Unix, @code{realloc} can destroy the storage block if it returns
+zero.  GNU @code{realloc} does not have this bug: if it fails, the
+original block is unchanged.  Feel free to assume the bug is fixed.  If
+you wish to run your program on Unix, and wish to avoid lossage in this
+case, you can use the GNU @code{malloc}.
+
+You must expect @code{free} to alter the contents of the block that was
+freed.  Anything you want to fetch from the block, you must fetch before
+calling @code{free}.
+
+If @code{malloc} fails in a noninteractive program, make that a fatal
+error.  In an interactive program (one that reads commands from the
+user), it is better to abort the command and return to the command
+reader loop.  This allows the user to kill other processes to free up
+virtual memory, and then try the command again.
+
+Use @code{getopt_long} to decode arguments, unless the argument syntax
+makes this unreasonable.
+
+When static storage is to be written in during program execution, use
+explicit C code to initialize it.  Reserve C initialized declarations
+for data that will not be changed.
+@c ADR: why?
+
+Try to avoid low-level interfaces to obscure Unix data structures (such
+as file directories, utmp, or the layout of kernel memory), since these
+are less likely to work compatibly.  If you need to find all the files
+in a directory, use @code{readdir} or some other high-level interface.
+These will be supported compatibly by GNU.
+
+By default, the GNU system will provide the signal handling functions of
+@sc{BSD} and of @sc{POSIX}.  So GNU software should be written to use
+these.
+
+In error checks that detect ``impossible'' conditions, just abort.
+There is usually no point in printing any message.  These checks
+indicate the existence of bugs.  Whoever wants to fix the bugs will have
+to read the source code and run a debugger.  So explain the problem with
+comments in the source.  The relevant data will be in variables, which
+are easy to examine with the debugger, so there is no point moving them
+elsewhere.
+
+Do not use a count of errors as the exit status for a program.
+@emph{That does not work}, because exit status values are limited to 8
+bits (0 through 255).  A single run of the program might have 256
+errors; if you try to return 256 as the exit status, the parent process
+will see 0 as the status, and it will appear that the program succeeded.
+
+If you make temporary files, check the @code{TMPDIR} environment
+variable; if that variable is defined, use the specified directory
+instead of @file{/tmp}.
+
+@node Libraries
+@section Library Behavior
+
+Try to make library functions reentrant.  If they need to do dynamic
+storage allocation, at least try to avoid any nonreentrancy aside from
+that of @code{malloc} itself.
+
+Here are certain name conventions for libraries, to avoid name
+conflicts.
+
+Choose a name prefix for the library, more than two characters long.
+All external function and variable names should start with this
+prefix.  In addition, there should only be one of these in any given
+library member.  This usually means putting each one in a separate
+source file.
+
+An exception can be made when two external symbols are always used
+together, so that no reasonable program could use one without the
+other; then they can both go in the same file.
+
+External symbols that are not documented entry points for the user
+should have names beginning with @samp{_}.  They should also contain
+the chosen name prefix for the library, to prevent collisions with
+other libraries.  These can go in the same files with user entry
+points if you like.
+
+Static functions and variables can be used as you like and need not
+fit any naming convention.
+
+@node Errors
+@section Formatting Error Messages
+
+Error messages from compilers should look like this:
+
+@example
+@var{source-file-name}:@var{lineno}: @var{message}
+@end example
+
+Error messages from other noninteractive programs should look like this:
+
+@example
+@var{program}:@var{source-file-name}:@var{lineno}: @var{message}
+@end example
+
+@noindent
+when there is an appropriate source file, or like this:
+
+@example
+@var{program}: @var{message}
+@end example
+
+@noindent
+when there is no relevant source file.
+
+In an interactive program (one that is reading commands from a
+terminal), it is better not to include the program name in an error
+message.  The place to indicate which program is running is in the
+prompt or with the screen layout.  (When the same program runs with
+input from a source other than a terminal, it is not interactive and
+would do best to print error messages using the noninteractive style.)
+
+The string @var{message} should not begin with a capital letter when
+it follows a program name and/or file name.  Also, it should not end
+with a period.
+
+Error messages from interactive programs, and other messages such as
+usage messages, should start with a capital letter.  But they should not
+end with a period.
+
+@node User Interfaces
+@section Standards for Command Line Interfaces
+
+Please don't make the behavior of a utility depend on the name used
+to invoke it.  It is useful sometimes to make a link to a utility
+with a different name, and that should not change what it does.
+
+Instead, use a run time option or a compilation switch or both
+to select among the alternate behaviors.
+
+Likewise, please don't make the behavior of the program depend on the
+type of output device it is used with.  Device independence is an
+important principle of the system's design; do not compromise it
+merely to save someone from typing an option now and then.
+
+If you think one behavior is most useful when the output is to a
+terminal, and another is most useful when the output is a file or a
+pipe, then it is usually best to make the default behavior the one that
+is useful with output to a terminal, and have an option for the other
+behavior.
+
+Compatibility requires certain programs to depend on the type of output
+device.  It would be disastrous if @code{ls} or @code{sh} did not do so
+in the way all users expect.  In some of these cases, we supplement the
+program with a preferred alternate version that does not depend on the
+output device type.  For example, we provide a @code{dir} program much
+like @code{ls} except that its default output format is always
+multi-column format.
+
+It is a good idea to follow the @sc{POSIX} guidelines for the
+command-line options of a program.  The easiest way to do this is to use
+@code{getopt} to parse them.  Note that the GNU version of @code{getopt}
+will normally permit options anywhere among the arguments unless the
+special argument @samp{--} is used.  This is not what @sc{POSIX}
+specifies; it is a GNU extension.
+
+Please define long-named options that are equivalent to the
+single-letter Unix-style options.  We hope to make GNU more user
+friendly this way.  This is easy to do with the GNU function
+@code{getopt_long}.
+
+One of the advantages of long-named options is that they can be
+consistent from program to program.  For example, users should be able
+to expect the ``verbose'' option of any GNU program which has one, to be
+spelled precisely @samp{--verbose}.  To achieve this uniformity, look at
+the table of common long-option names when you choose the option names
+for your program (@pxref{Option Table}).
+
+It is usually a good idea for file names given as ordinary arguments to
+be input files only; any output files would be specified using options
+(preferably @samp{-o} or @samp{--output}).  Even if you allow an output
+file name as an ordinary argument for compatibility, try to provide an
+option as another way to specify it.  This will lead to more consistency
+among GNU utilities, and fewer idiosyncracies for users to remember.
+
+All programs should support two standard options: @samp{--version}
+and @samp{--help}.
+
+@table @code
+@item --version
+This option should direct the program to information about its name,
+version, origin and legal status, all on standard output, and then exit
+successfully.  Other options and arguments should be ignored once this
+is seen, and the program should not perform its normal function.
+
+The first line is meant to be easy for a program to parse; the version
+number proper starts after the last space.  In addition, it contains
+the canonical name for this program, in this format:
+
+@example
+GNU Emacs 19.30
+@end example
+
+@noindent
+The program's name should be a constant string; @emph{don't} compute it
+from @code{argv[0]}.  The idea is to state the standard or canonical
+name for the program, not its file name.  There are other ways to find
+out the precise file name where a command is found in @code{PATH}.
+
+If the program is a subsidiary part of a larger package, mention the
+package name in parentheses, like this:
+
+@example
+emacsserver (GNU Emacs) 19.30
+@end example
+
+@noindent
+If the package has a version number which is different from this
+program's version number, you can mention the package version number
+just before the close-parenthesis.
+
+If you @strong{need} to mention the version numbers of libraries which
+are distributed separately from the package which contains this program,
+you can do so by printing an additional line of version info for each
+library you want to mention.  Use the same format for these lines as for
+the first line.
+
+Please do not mention all of the libraries that the program uses ``just
+for completeness''---that would produce a lot of unhelpful clutter.
+Please mention library version numbers only if you find in practice that
+they are very important to you in debugging.
+
+The following line, after the version number line or lines, should be a
+copyright notice.  If more than one copyright notice is called for, put
+each on a separate line.
+
+Next should follow a brief statement that the program is free software,
+and that users are free to copy and change it on certain conditions.  If
+the program is covered by the GNU GPL, say so here.  Also mention that
+there is no warranty, to the extent permitted by law.
+
+It is ok to finish the output with a list of the major authors of the
+program, as a way of giving credit.
+
+Here's an example of output that follows these rules:
+
+@smallexample
+GNU Emacs 19.34.5
+Copyright (C) 1996 Free Software Foundation, Inc.
+GNU Emacs comes with NO WARRANTY,
+to the extent permitted by law.
+You may redistribute copies of GNU Emacs
+under the terms of the GNU General Public License.
+For more information about these matters,
+see the files named COPYING.
+@end smallexample
+
+You should adapt this to your program, of course, filling in the proper
+year, copyright holder, name of program, and the references to
+distribution terms, and changing the rest of the wording as necessary.
+
+This copyright notice only needs to mention the most recent year in
+which changes were made---there's no need to list the years for previous
+versions' changes.  You don't have to mention the name of the program in
+these notices, if that is inconvenient, since it appeared in the first
+line.
+
+@item --help
+This option should output brief documentation for how to invoke the
+program, on standard output, then exit successfully.  Other options and
+arguments should be ignored once this is seen, and the program should
+not perform its normal function.
+
+Near the end of the @samp{--help} option's output there should be a line
+that says where to mail bug reports.  It should have this format:
+
+@example
+Report bugs to @var{mailing-address}.
+@end example
+@end table
+
+@node Option Table
+@section Table of Long Options
+
+Here is a table of long options used by GNU programs.  It is surely
+incomplete, but we aim to list all the options that a new program might
+want to be compatible with.  If you use names not already in the table,
+please send @email{gnu@@gnu.org} a list of them, with their
+meanings, so we can update the table.
+
+@c Please leave newlines between items in this table; it's much easier
+@c to update when it isn't completely squashed together and unreadable.
+@c When there is more than one short option for a long option name, put
+@c a semicolon between the lists of the programs that use them, not a
+@c period.   --friedman
+
+@table @samp
+@item after-date
+@samp{-N} in @code{tar}.
+
+@item all
+@samp{-a} in @code{du}, @code{ls}, @code{nm}, @code{stty}, @code{uname},
+and @code{unexpand}.
+
+@item all-text
+@samp{-a} in @code{diff}.
+
+@item almost-all
+@samp{-A} in @code{ls}.
+
+@item append
+@samp{-a} in @code{etags}, @code{tee}, @code{time};
+@samp{-r} in @code{tar}.
+
+@item archive
+@samp{-a} in @code{cp}.
+
+@item archive-name
+@samp{-n} in @code{shar}.
+
+@item arglength
+@samp{-l} in @code{m4}.
+
+@item ascii
+@samp{-a} in @code{diff}.
+
+@item assign
+@samp{-v} in @code{gawk}.
+
+@item assume-new
+@samp{-W} in Make.
+
+@item assume-old
+@samp{-o} in Make.
+
+@item auto-check
+@samp{-a} in @code{recode}.
+
+@item auto-pager
+@samp{-a} in @code{wdiff}.
+
+@item auto-reference
+@samp{-A} in @code{ptx}.
+
+@item avoid-wraps
+@samp{-n} in @code{wdiff}.
+
+@item backward-search
+@samp{-B} in @code{ctags}.
+
+@item basename
+@samp{-f} in @code{shar}.
+
+@item batch
+Used in GDB.
+
+@item baud
+Used in GDB.
+
+@item before
+@samp{-b} in @code{tac}.
+
+@item binary
+@samp{-b} in @code{cpio} and @code{diff}.
+
+@item bits-per-code
+@samp{-b} in @code{shar}.
+
+@item block-size
+Used in @code{cpio} and @code{tar}.
+
+@item blocks
+@samp{-b} in @code{head} and @code{tail}.
+
+@item break-file
+@samp{-b} in @code{ptx}.
+
+@item brief
+Used in various programs to make output shorter.
+
+@item bytes
+@samp{-c} in @code{head}, @code{split}, and @code{tail}.
+
+@item c@t{++}
+@samp{-C} in @code{etags}.
+
+@item catenate
+@samp{-A} in @code{tar}.
+
+@item cd
+Used in various programs to specify the directory to use.
+
+@item changes
+@samp{-c} in @code{chgrp} and @code{chown}.
+
+@item classify
+@samp{-F} in @code{ls}.
+
+@item colons
+@samp{-c} in @code{recode}.
+
+@item command
+@samp{-c} in @code{su};
+@samp{-x} in GDB.
+
+@item compare
+@samp{-d} in @code{tar}.
+
+@item compat
+Used in @code{gawk}.
+
+@item compress
+@samp{-Z} in @code{tar} and @code{shar}.
+
+@item concatenate
+@samp{-A} in @code{tar}.
+
+@item confirmation
+@samp{-w} in @code{tar}.
+
+@item context
+Used in @code{diff}.
+
+@item copyleft
+@samp{-W copyleft} in @code{gawk}.
+
+@item copyright
+@samp{-C} in @code{ptx}, @code{recode}, and @code{wdiff};
+@samp{-W copyright} in @code{gawk}.
+
+@item core
+Used in GDB.
+
+@item count
+@samp{-q} in @code{who}.
+
+@item count-links
+@samp{-l} in @code{du}.
+
+@item create
+Used in @code{tar} and @code{cpio}.
+
+@item cut-mark
+@samp{-c} in @code{shar}.
+
+@item cxref
+@samp{-x} in @code{ctags}.
+
+@item date
+@samp{-d} in @code{touch}.
+
+@item debug
+@samp{-d} in Make and @code{m4};
+@samp{-t} in Bison.
+
+@item define
+@samp{-D} in @code{m4}.
+
+@item defines
+@samp{-d} in Bison and @code{ctags}.
+
+@item delete
+@samp{-D} in @code{tar}.
+
+@item dereference
+@samp{-L} in @code{chgrp}, @code{chown}, @code{cpio}, @code{du},
+@code{ls}, and @code{tar}.
+
+@item dereference-args
+@samp{-D} in @code{du}.
+
+@item diacritics
+@samp{-d} in @code{recode}.
+
+@item dictionary-order
+@samp{-d} in @code{look}.
+
+@item diff
+@samp{-d} in @code{tar}.
+
+@item digits
+@samp{-n} in @code{csplit}.
+
+@item directory
+Specify the directory to use, in various programs.  In @code{ls}, it
+means to show directories themselves rather than their contents.  In
+@code{rm} and @code{ln}, it means to not treat links to directories
+specially.
+
+@item discard-all
+@samp{-x} in @code{strip}.
+
+@item discard-locals
+@samp{-X} in @code{strip}.
+
+@item dry-run
+@samp{-n} in Make.
+
+@item ed
+@samp{-e} in @code{diff}.
+
+@item elide-empty-files
+@samp{-z} in @code{csplit}.
+
+@item end-delete
+@samp{-x} in @code{wdiff}.
+
+@item end-insert
+@samp{-z} in @code{wdiff}.
+
+@item entire-new-file
+@samp{-N} in @code{diff}.
+
+@item environment-overrides
+@samp{-e} in Make.
+
+@item eof
+@samp{-e} in @code{xargs}.
+
+@item epoch
+Used in GDB.
+
+@item error-limit
+Used in @code{makeinfo}.
+
+@item error-output
+@samp{-o} in @code{m4}.
+
+@item escape
+@samp{-b} in @code{ls}.
+
+@item exclude-from
+@samp{-X} in @code{tar}.
+
+@item exec
+Used in GDB.
+
+@item exit
+@samp{-x} in @code{xargs}.
+
+@item exit-0
+@samp{-e} in @code{unshar}.
+
+@item expand-tabs
+@samp{-t} in @code{diff}.
+
+@item expression
+@samp{-e} in @code{sed}.
+
+@item extern-only
+@samp{-g} in @code{nm}.
+
+@item extract
+@samp{-i} in @code{cpio};
+@samp{-x} in @code{tar}.
+
+@item faces
+@samp{-f} in @code{finger}.
+
+@item fast
+@samp{-f} in @code{su}.
+
+@item fatal-warnings
+@samp{-E} in @code{m4}.
+
+@item file
+@samp{-f} in @code{info}, @code{gawk}, Make, @code{mt}, and @code{tar};
+@samp{-n} in @code{sed};
+@samp{-r} in @code{touch}.
+
+@item field-separator
+@samp{-F} in @code{gawk}.
+
+@item file-prefix
+@samp{-b} in Bison.
+
+@item file-type
+@samp{-F} in @code{ls}.
+
+@item files-from
+@samp{-T} in @code{tar}.
+
+@item fill-column
+Used in @code{makeinfo}.
+
+@item flag-truncation
+@samp{-F} in @code{ptx}.
+
+@item fixed-output-files
+@samp{-y} in Bison.
+
+@item follow
+@samp{-f} in @code{tail}.
+
+@item footnote-style
+Used in @code{makeinfo}.
+
+@item force
+@samp{-f} in @code{cp}, @code{ln}, @code{mv}, and @code{rm}.
+
+@item force-prefix
+@samp{-F} in @code{shar}.
+
+@item format
+Used in @code{ls}, @code{time}, and @code{ptx}.
+
+@item freeze-state
+@samp{-F} in @code{m4}.
+
+@item fullname
+Used in GDB.
+
+@item gap-size
+@samp{-g} in @code{ptx}.
+
+@item get
+@samp{-x} in @code{tar}.
+
+@item graphic
+@samp{-i} in @code{ul}.
+
+@item graphics
+@samp{-g} in @code{recode}.
+
+@item group
+@samp{-g} in @code{install}.
+
+@item gzip
+@samp{-z} in @code{tar} and @code{shar}.
+
+@item hashsize
+@samp{-H} in @code{m4}.
+
+@item header
+@samp{-h} in @code{objdump} and @code{recode}
+
+@item heading
+@samp{-H} in @code{who}.
+
+@item help
+Used to ask for brief usage information.
+
+@item here-delimiter
+@samp{-d} in @code{shar}.
+
+@item hide-control-chars
+@samp{-q} in @code{ls}.
+
+@item idle
+@samp{-u} in @code{who}.
+
+@item ifdef
+@samp{-D} in @code{diff}.
+
+@item ignore
+@samp{-I} in @code{ls};
+@samp{-x} in @code{recode}.
+
+@item ignore-all-space
+@samp{-w} in @code{diff}.
+
+@item ignore-backups
+@samp{-B} in @code{ls}.
+
+@item ignore-blank-lines
+@samp{-B} in @code{diff}.
+
+@item ignore-case
+@samp{-f} in @code{look} and @code{ptx};
+@samp{-i} in @code{diff} and @code{wdiff}.
+
+@item ignore-errors
+@samp{-i} in Make.
+
+@item ignore-file
+@samp{-i} in @code{ptx}.
+
+@item ignore-indentation
+@samp{-I} in @code{etags}.
+
+@item ignore-init-file
+@samp{-f} in Oleo.
+
+@item ignore-interrupts
+@samp{-i} in @code{tee}.
+
+@item ignore-matching-lines
+@samp{-I} in @code{diff}.
+
+@item ignore-space-change
+@samp{-b} in @code{diff}.
+
+@item ignore-zeros
+@samp{-i} in @code{tar}.
+
+@item include
+@samp{-i} in @code{etags};
+@samp{-I} in @code{m4}.
+
+@item include-dir
+@samp{-I} in Make.
+
+@item incremental
+@samp{-G} in @code{tar}.
+
+@item info
+@samp{-i}, @samp{-l}, and @samp{-m} in Finger.
+
+@item initial
+@samp{-i} in @code{expand}.
+
+@item initial-tab
+@samp{-T} in @code{diff}.
+
+@item inode
+@samp{-i} in @code{ls}.
+
+@item interactive
+@samp{-i} in @code{cp}, @code{ln}, @code{mv}, @code{rm};
+@samp{-e} in @code{m4};
+@samp{-p} in @code{xargs};
+@samp{-w} in @code{tar}.
+
+@item intermix-type
+@samp{-p} in @code{shar}.
+
+@item jobs
+@samp{-j} in Make.
+
+@item just-print
+@samp{-n} in Make.
+
+@item keep-going
+@samp{-k} in Make.
+
+@item keep-files
+@samp{-k} in @code{csplit}.
+
+@item kilobytes
+@samp{-k} in @code{du} and @code{ls}.
+
+@item language
+@samp{-l} in @code{etags}.
+
+@item less-mode
+@samp{-l} in @code{wdiff}.
+
+@item level-for-gzip
+@samp{-g} in @code{shar}.
+
+@item line-bytes
+@samp{-C} in @code{split}.
+
+@item lines
+Used in @code{split}, @code{head}, and @code{tail}.
+
+@item link
+@samp{-l} in @code{cpio}.
+
+@item lint
+@itemx lint-old
+Used in @code{gawk}.
+
+@item list
+@samp{-t} in @code{cpio};
+@samp{-l} in @code{recode}.
+
+@item list
+@samp{-t} in @code{tar}.
+
+@item literal
+@samp{-N} in @code{ls}.
+
+@item load-average
+@samp{-l} in Make.
+
+@item login
+Used in @code{su}.
+
+@item machine
+No listing of which programs already use this;
+someone should check to
+see if any actually do, and tell @email{gnu@@gnu.org}.
+
+@item macro-name
+@samp{-M} in @code{ptx}.
+
+@item mail
+@samp{-m} in @code{hello} and @code{uname}.
+
+@item make-directories
+@samp{-d} in @code{cpio}.
+
+@item makefile
+@samp{-f} in Make.
+
+@item mapped
+Used in GDB.
+
+@item max-args
+@samp{-n} in @code{xargs}.
+
+@item max-chars
+@samp{-n} in @code{xargs}.
+
+@item max-lines
+@samp{-l} in @code{xargs}.
+
+@item max-load
+@samp{-l} in Make.
+
+@item max-procs
+@samp{-P} in @code{xargs}.
+
+@item mesg
+@samp{-T} in @code{who}.
+
+@item message
+@samp{-T} in @code{who}.
+
+@item minimal
+@samp{-d} in @code{diff}.
+
+@item mixed-uuencode
+@samp{-M} in @code{shar}.
+
+@item mode
+@samp{-m} in @code{install}, @code{mkdir}, and @code{mkfifo}.
+
+@item modification-time
+@samp{-m} in @code{tar}.
+
+@item multi-volume
+@samp{-M} in @code{tar}.
+
+@item name-prefix
+@samp{-a} in Bison.
+
+@item nesting-limit
+@samp{-L} in @code{m4}.
+
+@item net-headers
+@samp{-a} in @code{shar}.
+
+@item new-file
+@samp{-W} in Make.
+
+@item no-builtin-rules
+@samp{-r} in Make.
+
+@item no-character-count
+@samp{-w} in @code{shar}.
+
+@item no-check-existing
+@samp{-x} in @code{shar}.
+
+@item no-common
+@samp{-3} in @code{wdiff}.
+
+@item no-create
+@samp{-c} in @code{touch}.
+
+@item no-defines
+@samp{-D} in @code{etags}.
+
+@item no-deleted
+@samp{-1} in @code{wdiff}.
+
+@item no-dereference
+@samp{-d} in @code{cp}.
+
+@item no-inserted
+@samp{-2} in @code{wdiff}.
+
+@item no-keep-going
+@samp{-S} in Make.
+
+@item no-lines
+@samp{-l} in Bison.
+
+@item no-piping
+@samp{-P} in @code{shar}.
+
+@item no-prof
+@samp{-e} in @code{gprof}.
+
+@item no-regex
+@samp{-R} in @code{etags}.
+
+@item no-sort
+@samp{-p} in @code{nm}.
+
+@item no-split
+Used in @code{makeinfo}.
+
+@item no-static
+@samp{-a} in @code{gprof}.
+
+@item no-time
+@samp{-E} in @code{gprof}.
+
+@item no-timestamp
+@samp{-m} in @code{shar}.
+
+@item no-validate
+Used in @code{makeinfo}.
+
+@item no-wait
+Used in @code{emacsclient}.
+
+@item no-warn
+Used in various programs to inhibit warnings.
+
+@item node
+@samp{-n} in @code{info}.
+
+@item nodename
+@samp{-n} in @code{uname}.
+
+@item nonmatching
+@samp{-f} in @code{cpio}.
+
+@item nstuff
+@samp{-n} in @code{objdump}.
+
+@item null
+@samp{-0} in @code{xargs}.
+
+@item number
+@samp{-n} in @code{cat}.
+
+@item number-nonblank
+@samp{-b} in @code{cat}.
+
+@item numeric-sort
+@samp{-n} in @code{nm}.
+
+@item numeric-uid-gid
+@samp{-n} in @code{cpio} and @code{ls}.
+
+@item nx
+Used in GDB.
+
+@item old-archive
+@samp{-o} in @code{tar}.
+
+@item old-file
+@samp{-o} in Make.
+
+@item one-file-system
+@samp{-l} in @code{tar}, @code{cp}, and @code{du}.
+
+@item only-file
+@samp{-o} in @code{ptx}.
+
+@item only-prof
+@samp{-f} in @code{gprof}.
+
+@item only-time
+@samp{-F} in @code{gprof}.
+
+@item output
+In various programs, specify the output file name.
+
+@item output-prefix
+@samp{-o} in @code{shar}.
+
+@item override
+@samp{-o} in @code{rm}.
+
+@item overwrite
+@samp{-c} in @code{unshar}.
+
+@item owner
+@samp{-o} in @code{install}.
+
+@item paginate
+@samp{-l} in @code{diff}.
+
+@item paragraph-indent
+Used in @code{makeinfo}.
+
+@item parents
+@samp{-p} in @code{mkdir} and @code{rmdir}.
+
+@item pass-all
+@samp{-p} in @code{ul}.
+
+@item pass-through
+@samp{-p} in @code{cpio}.
+
+@item port
+@samp{-P} in @code{finger}.
+
+@item portability
+@samp{-c} in @code{cpio} and @code{tar}.
+
+@item posix
+Used in @code{gawk}.
+
+@item prefix-builtins
+@samp{-P} in @code{m4}.
+
+@item prefix
+@samp{-f} in @code{csplit}.
+
+@item preserve
+Used in @code{tar} and @code{cp}.
+
+@item preserve-environment
+@samp{-p} in @code{su}.
+
+@item preserve-modification-time
+@samp{-m} in @code{cpio}.
+
+@item preserve-order
+@samp{-s} in @code{tar}.
+
+@item preserve-permissions
+@samp{-p} in @code{tar}.
+
+@item print
+@samp{-l} in @code{diff}.
+
+@item print-chars
+@samp{-L} in @code{cmp}.
+
+@item print-data-base
+@samp{-p} in Make.
+
+@item print-directory
+@samp{-w} in Make.
+
+@item print-file-name
+@samp{-o} in @code{nm}.
+
+@item print-symdefs
+@samp{-s} in @code{nm}.
+
+@item printer
+@samp{-p} in @code{wdiff}.
+
+@item prompt
+@samp{-p} in @code{ed}.
+
+@item query-user
+@samp{-X} in @code{shar}.
+
+@item question
+@samp{-q} in Make.
+
+@item quiet
+Used in many programs to inhibit the usual output.  @strong{Note:} every
+program accepting @samp{--quiet} should accept @samp{--silent} as a
+synonym.
+
+@item quiet-unshar
+@samp{-Q} in @code{shar}
+
+@item quote-name
+@samp{-Q} in @code{ls}.
+
+@item rcs
+@samp{-n} in @code{diff}.
+
+@item re-interval
+Used in @code{gawk}.
+
+@item read-full-blocks
+@samp{-B} in @code{tar}.
+
+@item readnow
+Used in GDB.
+
+@item recon
+@samp{-n} in Make.
+
+@item record-number
+@samp{-R} in @code{tar}.
+
+@item recursive
+Used in @code{chgrp}, @code{chown}, @code{cp}, @code{ls}, @code{diff},
+and @code{rm}.
+
+@item reference-limit
+Used in @code{makeinfo}.
+
+@item references
+@samp{-r} in @code{ptx}.
+
+@item regex
+@samp{-r} in @code{tac} and @code{etags}.
+
+@item release
+@samp{-r} in @code{uname}.
+
+@item reload-state
+@samp{-R} in @code{m4}.
+
+@item relocation
+@samp{-r} in @code{objdump}.
+
+@item rename
+@samp{-r} in @code{cpio}.
+
+@item replace
+@samp{-i} in @code{xargs}.
+
+@item report-identical-files
+@samp{-s} in @code{diff}.
+
+@item reset-access-time
+@samp{-a} in @code{cpio}.
+
+@item reverse
+@samp{-r} in @code{ls} and @code{nm}.
+
+@item reversed-ed
+@samp{-f} in @code{diff}.
+
+@item right-side-defs
+@samp{-R} in @code{ptx}.
+
+@item same-order
+@samp{-s} in @code{tar}.
+
+@item same-permissions
+@samp{-p} in @code{tar}.
+
+@item save
+@samp{-g} in @code{stty}.
+
+@item se
+Used in GDB.
+
+@item sentence-regexp
+@samp{-S} in @code{ptx}.
+
+@item separate-dirs
+@samp{-S} in @code{du}.
+
+@item separator
+@samp{-s} in @code{tac}.
+
+@item sequence
+Used by @code{recode} to chose files or pipes for sequencing passes.
+
+@item shell
+@samp{-s} in @code{su}.
+
+@item show-all
+@samp{-A} in @code{cat}.
+
+@item show-c-function
+@samp{-p} in @code{diff}.
+
+@item show-ends
+@samp{-E} in @code{cat}.
+
+@item show-function-line
+@samp{-F} in @code{diff}.
+
+@item show-tabs
+@samp{-T} in @code{cat}.
+
+@item silent
+Used in many programs to inhibit the usual output.
+@strong{Note:} every program accepting
+@samp{--silent} should accept @samp{--quiet} as a synonym.
+
+@item size
+@samp{-s} in @code{ls}.
+
+@item sort
+Used in @code{ls}.
+
+@item source
+@samp{-W source} in @code{gawk}.
+
+@item sparse
+@samp{-S} in @code{tar}.
+
+@item speed-large-files
+@samp{-H} in @code{diff}.
+
+@item split-at
+@samp{-E} in @code{unshar}.
+
+@item split-size-limit
+@samp{-L} in @code{shar}.
+
+@item squeeze-blank
+@samp{-s} in @code{cat}.
+
+@item start-delete
+@samp{-w} in @code{wdiff}.
+
+@item start-insert
+@samp{-y} in @code{wdiff}.
+
+@item starting-file
+Used in @code{tar} and @code{diff} to specify which file within
+a directory to start processing with.
+
+@item statistics
+@samp{-s} in @code{wdiff}.
+
+@item stdin-file-list
+@samp{-S} in @code{shar}.
+
+@item stop
+@samp{-S} in Make.
+
+@item strict
+@samp{-s} in @code{recode}.
+
+@item strip
+@samp{-s} in @code{install}.
+
+@item strip-all
+@samp{-s} in @code{strip}.
+
+@item strip-debug
+@samp{-S} in @code{strip}.
+
+@item submitter
+@samp{-s} in @code{shar}.
+
+@item suffix
+@samp{-S} in @code{cp}, @code{ln}, @code{mv}.
+
+@item suffix-format
+@samp{-b} in @code{csplit}.
+
+@item sum
+@samp{-s} in @code{gprof}.
+
+@item summarize
+@samp{-s} in @code{du}.
+
+@item symbolic
+@samp{-s} in @code{ln}.
+
+@item symbols
+Used in GDB and @code{objdump}.
+
+@item synclines
+@samp{-s} in @code{m4}.
+
+@item sysname
+@samp{-s} in @code{uname}.
+
+@item tabs
+@samp{-t} in @code{expand} and @code{unexpand}.
+
+@item tabsize
+@samp{-T} in @code{ls}.
+
+@item terminal
+@samp{-T} in @code{tput} and @code{ul}.
+@samp{-t} in @code{wdiff}.
+
+@item text
+@samp{-a} in @code{diff}.
+
+@item text-files
+@samp{-T} in @code{shar}.
+
+@item time
+Used in @code{ls} and @code{touch}.
+
+@item to-stdout
+@samp{-O} in @code{tar}.
+
+@item total
+@samp{-c} in @code{du}.
+
+@item touch
+@samp{-t} in Make, @code{ranlib}, and @code{recode}.
+
+@item trace
+@samp{-t} in @code{m4}.
+
+@item traditional
+@samp{-t} in @code{hello};
+@samp{-W traditional} in @code{gawk};
+@samp{-G} in @code{ed}, @code{m4}, and @code{ptx}.
+
+@item tty
+Used in GDB.
+
+@item typedefs
+@samp{-t} in @code{ctags}.
+
+@item typedefs-and-c++
+@samp{-T} in @code{ctags}.
+
+@item typeset-mode
+@samp{-t} in @code{ptx}.
+
+@item uncompress
+@samp{-z} in @code{tar}.
+
+@item unconditional
+@samp{-u} in @code{cpio}.
+
+@item undefine
+@samp{-U} in @code{m4}.
+
+@item undefined-only
+@samp{-u} in @code{nm}.
+
+@item update
+@samp{-u} in @code{cp}, @code{ctags}, @code{mv}, @code{tar}.
+
+@item usage
+Used in @code{gawk}; same as @samp{--help}.
+
+@item uuencode
+@samp{-B} in @code{shar}.
+
+@item vanilla-operation
+@samp{-V} in @code{shar}.
+
+@item verbose
+Print more information about progress.  Many programs support this.
+
+@item verify
+@samp{-W} in @code{tar}.
+
+@item version
+Print the version number.
+
+@item version-control
+@samp{-V} in @code{cp}, @code{ln}, @code{mv}.
+
+@item vgrind
+@samp{-v} in @code{ctags}.
+
+@item volume
+@samp{-V} in @code{tar}.
+
+@item what-if
+@samp{-W} in Make.
+
+@item whole-size-limit
+@samp{-l} in @code{shar}.
+
+@item width
+@samp{-w} in @code{ls} and @code{ptx}.
+
+@item word-regexp
+@samp{-W} in @code{ptx}.
+
+@item writable
+@samp{-T} in @code{who}.
+
+@item zeros
+@samp{-z} in @code{gprof}.
+@end table
+
+@node Memory Usage
+@section Memory Usage
+
+If it typically uses just a few meg of memory, don't bother making any
+effort to reduce memory usage.  For example, if it is impractical for
+other reasons to operate on files more than a few meg long, it is
+reasonable to read entire input files into core to operate on them.
+
+However, for programs such as @code{cat} or @code{tail}, that can
+usefully operate on very large files, it is important to avoid using a
+technique that would artificially limit the size of files it can handle.
+If a program works by lines and could be applied to arbitrary
+user-supplied input files, it should keep only a line in memory, because
+this is not very hard and users will want to be able to operate on input
+files that are bigger than will fit in core all at once.
+
+If your program creates complicated data structures, just make them in
+core and give a fatal error if @code{malloc} returns zero.
+
+@node Writing C
+@chapter Making The Best Use of C
+
+This @value{CHAPTER} provides advice on how best to use the C language
+when writing GNU software.
+
+@menu
+* Formatting::                  Formatting Your Source Code
+* Comments::                    Commenting Your Work
+* Syntactic Conventions::       Clean Use of C Constructs
+* Names::                       Naming Variables and Functions
+* System Portability::          Portability between different operating systems
+* CPU Portability::             Supporting the range of CPU types
+* System Functions::            Portability and ``standard'' library functions
+* Internationalization::        Techniques for internationalization
+* Mmap::                        How you can safely use @code{mmap}.
+@end menu
+
+@node Formatting
+@section Formatting Your Source Code
+
+It is important to put the open-brace that starts the body of a C
+function in column zero, and avoid putting any other open-brace or
+open-parenthesis or open-bracket in column zero.  Several tools look
+for open-braces in column zero to find the beginnings of C functions.
+These tools will not work on code not formatted that way.
+
+It is also important for function definitions to start the name of the
+function in column zero.  This helps people to search for function
+definitions, and may also help certain tools recognize them.  Thus,
+the proper format is this:
+
+@example
+static char *
+concat (s1, s2)        /* Name starts in column zero here */
+     char *s1, *s2;
+@{                     /* Open brace in column zero here */
+  @dots{}
+@}
+@end example
+
+@noindent
+or, if you want to use @sc{ansi} C, format the definition like this:
+
+@example
+static char *
+concat (char *s1, char *s2)
+@{
+  @dots{}
+@}
+@end example
+
+In @sc{ansi} C, if the arguments don't fit nicely on one line,
+split it like this:
+
+@example
+int
+lots_of_args (int an_integer, long a_long, short a_short,
+              double a_double, float a_float)
+@dots{}
+@end example
+
+For the body of the function, we prefer code formatted like this:
+
+@example
+if (x < foo (y, z))
+  haha = bar[4] + 5;
+else
+  @{
+    while (z)
+      @{
+        haha += foo (z, z);
+        z--;
+      @}
+    return ++x + bar ();
+  @}
+@end example
+
+We find it easier to read a program when it has spaces before the
+open-parentheses and after the commas.  Especially after the commas.
+
+When you split an expression into multiple lines, split it
+before an operator, not after one.  Here is the right way:
+
+@example
+if (foo_this_is_long && bar > win (x, y, z)
+    && remaining_condition)
+@end example
+
+Try to avoid having two operators of different precedence at the same
+level of indentation.  For example, don't write this:
+
+@example
+mode = (inmode[j] == VOIDmode
+        || GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j])
+        ? outmode[j] : inmode[j]);
+@end example
+
+Instead, use extra parentheses so that the indentation shows the nesting:
+
+@example
+mode = ((inmode[j] == VOIDmode
+         || (GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j])))
+        ? outmode[j] : inmode[j]);
+@end example
+
+Insert extra parentheses so that Emacs will indent the code properly.
+For example, the following indentation looks nice if you do it by hand,
+but Emacs would mess it up:
+
+@example
+v = rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000
+    + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000;
+@end example
+
+But adding a set of parentheses solves the problem:
+
+@example
+v = (rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000
+     + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000);
+@end example
+
+Format do-while statements like this:
+
+@example
+do
+  @{
+    a = foo (a);
+  @}
+while (a > 0);
+@end example
+
+Please use formfeed characters (control-L) to divide the program into
+pages at logical places (but not within a function).  It does not matter
+just how long the pages are, since they do not have to fit on a printed
+page.  The formfeeds should appear alone on lines by themselves.
+
+
+@node Comments
+@section Commenting Your Work
+
+Every program should start with a comment saying briefly what it is for.
+Example: @samp{fmt - filter for simple filling of text}.
+
+Please write the comments in a GNU program in English, because English
+is the one language that nearly all programmers in all countries can
+read.  If you do not write English well, please write comments in
+English as well as you can, then ask other people to help rewrite them.
+If you can't write comments in English, please find someone to work with
+you and translate your comments into English.
+
+Please put a comment on each function saying what the function does,
+what sorts of arguments it gets, and what the possible values of
+arguments mean and are used for.  It is not necessary to duplicate in
+words the meaning of the C argument declarations, if a C type is being
+used in its customary fashion.  If there is anything nonstandard about
+its use (such as an argument of type @code{char *} which is really the
+address of the second character of a string, not the first), or any
+possible values that would not work the way one would expect (such as,
+that strings containing newlines are not guaranteed to work), be sure
+to say so.
+
+Also explain the significance of the return value, if there is one.
+
+Please put two spaces after the end of a sentence in your comments, so
+that the Emacs sentence commands will work.  Also, please write
+complete sentences and capitalize the first word.  If a lower-case
+identifier comes at the beginning of a sentence, don't capitalize it!
+Changing the spelling makes it a different identifier.  If you don't
+like starting a sentence with a lower case letter, write the sentence
+differently (e.g., ``The identifier lower-case is @dots{}'').
+
+The comment on a function is much clearer if you use the argument
+names to speak about the argument values.  The variable name itself
+should be lower case, but write it in upper case when you are speaking
+about the value rather than the variable itself.  Thus, ``the inode
+number NODE_NUM'' rather than ``an inode''.
+
+There is usually no purpose in restating the name of the function in
+the comment before it, because the reader can see that for himself.
+There might be an exception when the comment is so long that the function
+itself would be off the bottom of the screen.
+
+There should be a comment on each static variable as well, like this:
+
+@example
+/* Nonzero means truncate lines in the display;
+   zero means continue them.  */
+int truncate_lines;
+@end example
+
+Every @samp{#endif} should have a comment, except in the case of short
+conditionals (just a few lines) that are not nested.  The comment should
+state the condition of the conditional that is ending, @emph{including
+its sense}.  @samp{#else} should have a comment describing the condition
+@emph{and sense} of the code that follows.  For example:
+
+@example
+@group
+#ifdef foo
+  @dots{}
+#else /* not foo */
+  @dots{}
+#endif /* not foo */
+@end group
+@group
+#ifdef foo
+  @dots{}
+#endif /* foo */
+@end group
+@end example
+
+@noindent
+but, by contrast, write the comments this way for a @samp{#ifndef}:
+
+@example
+@group
+#ifndef foo
+  @dots{}
+#else /* foo */
+  @dots{}
+#endif /* foo */
+@end group
+@group
+#ifndef foo
+  @dots{}
+#endif /* not foo */
+@end group
+@end example
+
+@node Syntactic Conventions
+@section Clean Use of C Constructs
+
+Please explicitly declare all arguments to functions.
+Don't omit them just because they are @code{int}s.
+
+Declarations of external functions and functions to appear later in the
+source file should all go in one place near the beginning of the file
+(somewhere before the first function definition in the file), or else
+should go in a header file.  Don't put @code{extern} declarations inside
+functions.
+
+It used to be common practice to use the same local variables (with
+names like @code{tem}) over and over for different values within one
+function.  Instead of doing this, it is better declare a separate local
+variable for each distinct purpose, and give it a name which is
+meaningful.  This not only makes programs easier to understand, it also
+facilitates optimization by good compilers.  You can also move the
+declaration of each local variable into the smallest scope that includes
+all its uses.  This makes the program even cleaner.
+
+Don't use local variables or parameters that shadow global identifiers.
+
+Don't declare multiple variables in one declaration that spans lines.
+Start a new declaration on each line, instead.  For example, instead
+of this:
+
+@example
+@group
+int    foo,
+       bar;
+@end group
+@end example
+
+@noindent
+write either this:
+
+@example
+int foo, bar;
+@end example
+
+@noindent
+or this:
+
+@example
+int foo;
+int bar;
+@end example
+
+@noindent
+(If they are global variables, each should have a comment preceding it
+anyway.)
+
+When you have an @code{if}-@code{else} statement nested in another
+@code{if} statement, always put braces around the @code{if}-@code{else}.
+Thus, never write like this:
+
+@example
+if (foo)
+  if (bar)
+    win ();
+  else
+    lose ();
+@end example
+
+@noindent
+always like this:
+
+@example
+if (foo)
+  @{
+    if (bar)
+      win ();
+    else
+      lose ();
+  @}
+@end example
+
+If you have an @code{if} statement nested inside of an @code{else}
+statement, either write @code{else if} on one line, like this,
+
+@example
+if (foo)
+  @dots{}
+else if (bar)
+  @dots{}
+@end example
+
+@noindent
+with its @code{then}-part indented like the preceding @code{then}-part,
+or write the nested @code{if} within braces like this:
+
+@example
+if (foo)
+  @dots{}
+else
+  @{
+    if (bar)
+      @dots{}
+  @}
+@end example
+
+Don't declare both a structure tag and variables or typedefs in the
+same declaration.  Instead, declare the structure tag separately
+and then use it to declare the variables or typedefs.
+
+Try to avoid assignments inside @code{if}-conditions.  For example,
+don't write this:
+
+@example
+if ((foo = (char *) malloc (sizeof *foo)) == 0)
+  fatal ("virtual memory exhausted");
+@end example
+
+@noindent
+instead, write this:
+
+@example
+foo = (char *) malloc (sizeof *foo);
+if (foo == 0)
+  fatal ("virtual memory exhausted");
+@end example
+
+Don't make the program ugly to placate @code{lint}.  Please don't insert any
+casts to @code{void}.  Zero without a cast is perfectly fine as a null
+pointer constant, except when calling a varargs function.
+
+@node  Names
+@section Naming Variables and Functions
+
+The names of global variables and functions in a program serve as
+comments of a sort.  So don't choose terse names---instead, look for
+names that give useful information about the meaning of the variable or
+function.  In a GNU program, names should be English, like other
+comments.
+
+Local variable names can be shorter, because they are used only within
+one context, where (presumably) comments explain their purpose.
+
+Please use underscores to separate words in a name, so that the Emacs
+word commands can be useful within them.  Stick to lower case; reserve
+upper case for macros and @code{enum} constants, and for name-prefixes
+that follow a uniform convention.
+
+For example, you should use names like @code{ignore_space_change_flag};
+don't use names like @code{iCantReadThis}.
+
+Variables that indicate whether command-line options have been
+specified should be named after the meaning of the option, not after
+the option-letter.  A comment should state both the exact meaning of
+the option and its letter.  For example,
+
+@example
+@group
+/* Ignore changes in horizontal whitespace (-b).  */
+int ignore_space_change_flag;
+@end group
+@end example
+
+When you want to define names with constant integer values, use
+@code{enum} rather than @samp{#define}.  GDB knows about enumeration
+constants.
+
+Use file names of 14 characters or less, to avoid creating gratuitous
+problems on older System V systems.  You can use the program
+@code{doschk} to test for this.  @code{doschk} also tests for potential
+name conflicts if the files were loaded onto an MS-DOS file
+system---something you may or may not care about.
+
+@node System Portability
+@section Portability between System Types
+
+In the Unix world, ``portability'' refers to porting to different Unix
+versions.  For a GNU program, this kind of portability is desirable, but
+not paramount.
+
+The primary purpose of GNU software is to run on top of the GNU kernel,
+compiled with the GNU C compiler, on various types of @sc{cpu}.  The
+amount and kinds of variation among GNU systems on different @sc{cpu}s
+will be comparable to the variation among Linux-based GNU systems or
+among BSD systems today.  So the kinds of portability that are absolutely
+necessary are quite limited.
+
+But many users do run GNU software on non-GNU Unix or Unix-like systems.
+So supporting a variety of Unix-like systems is desirable, although not
+paramount.
+
+The easiest way to achieve portability to most Unix-like systems is to
+use Autoconf.  It's unlikely that your program needs to know more
+information about the host platform than Autoconf can provide, simply
+because most of the programs that need such knowledge have already been
+written.
+
+Avoid using the format of semi-internal data bases (e.g., directories)
+when there is a higher-level alternative (@code{readdir}).
+
+As for systems that are not like Unix, such as MSDOS, Windows, the
+Macintosh, VMS, and MVS, supporting them is usually so much work that it
+is better if you don't.
+
+The planned GNU kernel is not finished yet, but you can tell which
+facilities it will provide by looking at the GNU C Library Manual.  The
+GNU kernel is based on Mach, so the features of Mach will also be
+available.  However, if you use Mach features, you'll probably have
+trouble debugging your program today.
+
+@node CPU Portability
+@section Portability between @sc{cpu}s
+
+Even GNU systems will differ because of differences among @sc{cpu}
+types---for example, difference in byte ordering and alignment
+requirements.  It is absolutely essential to handle these differences.
+However, don't make any effort to cater to the possibility that an
+@code{int} will be less than 32 bits.  We don't support 16-bit machines
+in GNU.
+
+Don't assume that the address of an @code{int} object is also the
+address of its least-significant byte.  This is false on big-endian
+machines.  Thus, don't make the following mistake:
+
+@example
+int c;
+@dots{}
+while ((c = getchar()) != EOF)
+  write(file_descriptor, &c, 1);
+@end example
+
+When calling functions, you need not worry about the difference between
+pointers of various types, or between pointers and integers.  On most
+machines, there's no difference anyway.  As for the few machines where
+there is a difference, all of them support @sc{ansi} C, so you can use
+prototypes (conditionalized to be active only in @sc{ansi} C) to make
+the code work on those systems.
+
+In certain cases, it is ok to pass integer and pointer arguments
+indiscriminately to the same function, and use no prototype on any
+system.  For example, many GNU programs have error-reporting functions
+that pass their arguments along to @code{printf} and friends:
+
+@example
+error (s, a1, a2, a3)
+     char *s;
+     int a1, a2, a3;
+@{
+  fprintf (stderr, "error: ");
+  fprintf (stderr, s, a1, a2, a3);
+@}
+@end example
+
+@noindent
+In practice, this works on all machines, and it is much simpler than any
+``correct'' alternative.  Be sure @emph{not} to use a prototype
+for such functions.
+
+However, avoid casting pointers to integers unless you really need to.
+These assumptions really reduce portability, and in most programs they
+are easy to avoid.  In the cases where casting pointers to integers is
+essential---such as, a Lisp interpreter which stores type information as
+well as an address in one word---it is ok to do so, but you'll have to
+make explicit provisions to handle different word sizes.
+
+@node System Functions
+@section Calling System Functions
+
+C implementations differ substantially.  @sc{ansi} C reduces but does not
+eliminate the incompatibilities; meanwhile, many users wish to compile
+GNU software with pre-@sc{ansi} compilers.  This chapter gives
+recommendations for how to use the more or less standard C library
+functions to avoid unnecessary loss of portability.
+
+@itemize @bullet
+@item
+Don't use the value of @code{sprintf}.  It returns the number of
+characters written on some systems, but not on all systems.
+
+@item
+@code{main} should be declared to return type @code{int}.  It should
+terminate either by calling @code{exit} or by returning the integer
+status code; make sure it cannot ever return an undefined value.
+
+@item
+Don't declare system functions explicitly.
+
+Almost any declaration for a system function is wrong on some system.
+To minimize conflicts, leave it to the system header files to declare
+system functions.  If the headers don't declare a function, let it
+remain undeclared.
+
+While it may seem unclean to use a function without declaring it, in
+practice this works fine for most system library functions on the
+systems where this really happens; thus, the disadvantage is only
+theoretical.  By contrast, actual declarations have frequently caused
+actual conflicts.
+
+@item
+If you must declare a system function, don't specify the argument types.
+Use an old-style declaration, not an @sc{ansi} prototype.  The more you
+specify about the function, the more likely a conflict.
+
+@item
+In particular, don't unconditionally declare @code{malloc} or
+@code{realloc}.
+
+Most GNU programs use those functions just once, in functions
+conventionally named @code{xmalloc} and @code{xrealloc}.  These
+functions call @code{malloc} and @code{realloc}, respectively, and
+check the results.
+
+Because @code{xmalloc} and @code{xrealloc} are defined in your program,
+you can declare them in other files without any risk of type conflict.
+
+On most systems, @code{int} is the same length as a pointer; thus, the
+calls to @code{malloc} and @code{realloc} work fine.  For the few
+exceptional systems (mostly 64-bit machines), you can use
+@strong{conditionalized} declarations of @code{malloc} and
+@code{realloc}---or put these declarations in configuration files
+specific to those systems.
+
+@item
+The string functions require special treatment.  Some Unix systems have
+a header file @file{string.h}; others have @file{strings.h}.  Neither
+file name is portable.  There are two things you can do: use Autoconf to
+figure out which file to include, or don't include either file.
+
+@item
+If you don't include either strings file, you can't get declarations for
+the string functions from the header file in the usual way.
+
+That causes less of a problem than you might think.  The newer @sc{ansi}
+string functions should be avoided anyway because many systems still
+don't support them.  The string functions you can use are these:
+
+@example
+strcpy   strncpy   strcat   strncat
+strlen   strcmp    strncmp
+strchr   strrchr
+@end example
+
+The copy and concatenate functions work fine without a declaration as
+long as you don't use their values.  Using their values without a
+declaration fails on systems where the width of a pointer differs from
+the width of @code{int}, and perhaps in other cases.  It is trivial to
+avoid using their values, so do that.
+
+The compare functions and @code{strlen} work fine without a declaration
+on most systems, possibly all the ones that GNU software runs on.
+You may find it necessary to declare them @strong{conditionally} on a
+few systems.
+
+The search functions must be declared to return @code{char *}.  Luckily,
+there is no variation in the data type they return.  But there is
+variation in their names.  Some systems give these functions the names
+@code{index} and @code{rindex}; other systems use the names
+@code{strchr} and @code{strrchr}.  Some systems support both pairs of
+names, but neither pair works on all systems.
+
+You should pick a single pair of names and use it throughout your
+program.  (Nowadays, it is better to choose @code{strchr} and
+@code{strrchr} for new programs, since those are the standard @sc{ansi}
+names.)  Declare both of those names as functions returning @code{char
+*}.  On systems which don't support those names, define them as macros
+in terms of the other pair.  For example, here is what to put at the
+beginning of your file (or in a header) if you want to use the names
+@code{strchr} and @code{strrchr} throughout:
+
+@example
+#ifndef HAVE_STRCHR
+#define strchr index
+#endif
+#ifndef HAVE_STRRCHR
+#define strrchr rindex
+#endif
+
+char *strchr ();
+char *strrchr ();
+@end example
+@end itemize
+
+Here we assume that @code{HAVE_STRCHR} and @code{HAVE_STRRCHR} are
+macros defined in systems where the corresponding functions exist.
+One way to get them properly defined is to use Autoconf.
+
+@node Internationalization
+@section Internationalization
+
+GNU has a library called GNU gettext that makes it easy to translate the
+messages in a program into various languages.  You should use this
+library in every program.  Use English for the messages as they appear
+in the program, and let gettext provide the way to translate them into
+other languages.
+
+Using GNU gettext involves putting a call to the @code{gettext} macro
+around each string that might need translation---like this:
+
+@example
+printf (gettext ("Processing file `%s'..."));
+@end example
+
+@noindent
+This permits GNU gettext to replace the string @code{"Processing file
+`%s'..."} with a translated version.
+
+Once a program uses gettext, please make a point of writing calls to
+@code{gettext} when you add new strings that call for translation.
+
+Using GNU gettext in a package involves specifying a @dfn{text domain
+name} for the package.  The text domain name is used to separate the
+translations for this package from the translations for other packages.
+Normally, the text domain name should be the same as the name of the
+package---for example, @samp{fileutils} for the GNU file utilities.
+
+To enable gettext to work well, avoid writing code that makes
+assumptions about the structure of words or sentences.  When you want
+the precise text of a sentence to vary depending on the data, use two or
+more alternative string constants each containing a complete sentences,
+rather than inserting conditionalized words or phrases into a single
+sentence framework.
+
+Here is an example of what not to do:
+
+@example
+printf ("%d file%s processed", nfiles,
+        nfiles != 1 ? "s" : "");
+@end example
+
+@noindent
+The problem with that example is that it assumes that plurals are made
+by adding `s'.  If you apply gettext to the format string, like this,
+
+@example
+printf (gettext ("%d file%s processed"), nfiles,
+        nfiles != 1 ? "s" : "");
+@end example
+
+@noindent
+the message can use different words, but it will still be forced to use
+`s' for the plural.  Here is a better way:
+
+@example
+printf ((nfiles != 1 ? "%d files processed"
+         : "%d file processed"),
+        nfiles);
+@end example
+
+@noindent
+This way, you can apply gettext to each of the two strings
+independently:
+
+@example
+printf ((nfiles != 1 ? gettext ("%d files processed")
+         : gettext ("%d file processed")),
+        nfiles);
+@end example
+
+@noindent
+This can be any method of forming the plural of the word for ``file'', and
+also handles languages that require agreement in the word for
+``processed''.
+
+A similar problem appears at the level of sentence structure with this
+code:
+
+@example
+printf ("#  Implicit rule search has%s been done.\n",
+        f->tried_implicit ? "" : " not");
+@end example
+
+@noindent
+Adding @code{gettext} calls to this code cannot give correct results for
+all languages, because negation in some languages requires adding words
+at more than one place in the sentence.  By contrast, adding
+@code{gettext} calls does the job straightfowardly if the code starts
+out like this:
+
+@example
+printf (f->tried_implicit
+        ? "#  Implicit rule search has been done.\n",
+        : "#  Implicit rule search has not been done.\n");
+@end example
+
+@node Mmap
+@section Mmap
+
+Don't assume that @code{mmap} either works on all files or fails
+for all files.  It may work on some files and fail on others.
+
+The proper way to use @code{mmap} is to try it on the specific file for
+which you want to use it---and if @code{mmap} doesn't work, fall back on
+doing the job in another way using @code{read} and @code{write}.
+
+The reason this precaution is needed is that the GNU kernel (the HURD)
+provides a user-extensible file system, in which there can be many
+different kinds of ``ordinary files.''  Many of them support
+@code{mmap}, but some do not.  It is important to make programs handle
+all these kinds of files.
+
+@node Documentation
+@chapter Documenting Programs
+
+@menu
+* GNU Manuals::                 Writing proper manuals.
+* Manual Structure Details::    Specific structure conventions.
+* NEWS File::                   NEWS files supplement manuals.
+* Change Logs::                 Recording Changes
+* Man Pages::                   Man pages are secondary.
+* Reading other Manuals::       How far you can go in learning
+                                from other manuals.
+@end menu
+
+@node GNU Manuals
+@section GNU Manuals
+
+The preferred way to document part of the GNU system is to write a
+manual in the Texinfo formatting language.  See the Texinfo manual,
+either the hardcopy, or the on-line version available through
+@code{info} or the Emacs Info subsystem (@kbd{C-h i}).
+
+Programmers often find it most natural to structure the documentation
+following the structure of the implementation, which they know.  But
+this structure is not necessarily good for explaining how to use the
+program; it may be irrelevant and confusing for a user.
+
+At every level, from the sentences in a paragraph to the grouping of
+topics into separate manuals, the right way to structure documentation
+is according to the concepts and questions that a user will have in mind
+when reading it.  Sometimes this structure of ideas matches the
+structure of the implementation of the software being documented---but
+often they are different.  Often the most important part of learning to
+write good documentation is learning to notice when you are structuring
+the documentation like the implementation, and think about better
+alternatives.
+
+For example, each program in the GNU system probably ought to be
+documented in one manual; but this does not mean each program should
+have its own manual.  That would be following the structure of the
+implementation, rather than the structure that helps the user
+understand.
+
+Instead, each manual should cover a coherent @emph{topic}.  For example,
+instead of a manual for @code{diff} and a manual for @code{diff3}, we
+have one manual for ``comparison of files'' which covers both of those
+programs, as well as @code{cmp}.  By documenting these programs
+together, we can make the whole subject clearer.
+
+The manual which discusses a program should document all of the
+program's command-line options and all of its commands.  It should give
+examples of their use.  But don't organize the manual as a list of
+features.  Instead, organize it logically, by subtopics.  Address the
+questions that a user will ask when thinking about the job that the
+program does.
+
+In general, a GNU manual should serve both as tutorial and reference.
+It should be set up for convenient access to each topic through Info,
+and for reading straight through (appendixes aside).  A GNU manual
+should give a good introduction to a beginner reading through from the
+start, and should also provide all the details that hackers want.
+
+That is not as hard as it first sounds.  Arrange each chapter as a
+logical breakdown of its topic, but order the sections, and write their
+text, so that reading the chapter straight through makes sense.  Do
+likewise when structuring the book into chapters, and when structuring a
+section into paragraphs.  The watchword is, @emph{at each point, address
+the most fundamental and important issue raised by the preceding text.}
+
+If necessary, add extra chapters at the beginning of the manual which
+are purely tutorial and cover the basics of the subject.  These provide
+the framework for a beginner to understand the rest of the manual.  The
+Bison manual provides a good example of how to do this.
+
+Don't use Unix man pages as a model for how to write GNU documentation;
+most of them are terse, badly structured, and give inadequate
+explanation of the underlying concepts.  (There are, of course
+exceptions.)  Also Unix man pages use a particular format which is
+different from what we use in GNU manuals.
+
+Please do not use the term ``pathname'' that is used in Unix
+documentation; use ``file name'' (two words) instead.  We use the term
+``path'' only for search paths, which are lists of file names.
+
+Please do not use the term ``illegal'' to refer to erroneous input to a
+computer program.  Please use ``invalid'' for this, and reserve the term
+``illegal'' for violations of law.
+
+@node Manual Structure Details
+@section Manual Structure Details
+
+The title page of the manual should state the version of the programs or
+packages documented in the manual.  The Top node of the manual should
+also contain this information.  If the manual is changing more
+frequently than or independent of the program, also state a version
+number for the manual in both of these places.
+
+Each program documented in the manual should should have a node named
+@samp{@var{program} Invocation} or @samp{Invoking @var{program}}.  This
+node (together with its subnodes, if any) should describe the program's
+command line arguments and how to run it (the sort of information people
+would look in a man page for).  Start with an @samp{@@example}
+containing a template for all the options and arguments that the program
+uses.
+
+Alternatively, put a menu item in some menu whose item name fits one of
+the above patterns.  This identifies the node which that item points to
+as the node for this purpose, regardless of the node's actual name.
+
+There will be automatic features for specifying a program name and
+quickly reading just this part of its manual.
+
+If one manual describes several programs, it should have such a node for
+each program described.
+
+@node NEWS File
+@section The NEWS File
+
+In addition to its manual, the package should have a file named
+@file{NEWS} which contains a list of user-visible changes worth
+mentioning.  In each new release, add items to the front of the file and
+identify the version they pertain to.  Don't discard old items; leave
+them in the file after the newer items.  This way, a user upgrading from
+any previous version can see what is new.
+
+If the @file{NEWS} file gets very long, move some of the older items
+into a file named @file{ONEWS} and put a note at the end referring the
+user to that file.
+
+@node Change Logs
+@section Change Logs
+
+Keep a change log to describe all the changes made to program source
+files.  The purpose of this is so that people investigating bugs in the
+future will know about the changes that might have introduced the bug.
+Often a new bug can be found by looking at what was recently changed.
+More importantly, change logs can help you eliminate conceptual
+inconsistencies between different parts of a program, by giving you a
+history of how the conflicting concepts arose and who they came from.
+
+@menu
+* Change Log Concepts::         
+* Style of Change Logs::        
+* Simple Changes::              
+* Conditional Changes::         
+@end menu
+
+@node Change Log Concepts
+@subsection Change Log Concepts
+
+You can think of the change log as a conceptual ``undo list'' which
+explains how earlier versions were different from the current version.
+People can see the current version; they don't need the change log
+to tell them what is in it.  What they want from a change log is a
+clear explanation of how the earlier version differed.
+
+The change log file is normally called @file{ChangeLog} and covers an
+entire directory.  Each directory can have its own change log, or a
+directory can use the change log of its parent directory--it's up to
+you.
+
+Another alternative is to record change log information with a version
+control system such as RCS or CVS.  This can be converted automatically
+to a @file{ChangeLog} file.
+
+There's no need to describe the full purpose of the changes or how they
+work together.  If you think that a change calls for explanation, you're
+probably right.  Please do explain it---but please put the explanation
+in comments in the code, where people will see it whenever they see the
+code.  For example, ``New function'' is enough for the change log when
+you add a function, because there should be a comment before the
+function definition to explain what it does.
+
+However, sometimes it is useful to write one line to describe the
+overall purpose of a batch of changes.
+
+The easiest way to add an entry to @file{ChangeLog} is with the Emacs
+command @kbd{M-x add-change-log-entry}.  An entry should have an
+asterisk, the name of the changed file, and then in parentheses the name
+of the changed functions, variables or whatever, followed by a colon.
+Then describe the changes you made to that function or variable.
+
+@node Style of Change Logs
+@subsection Style of Change Logs
+
+Here are some examples of change log entries:
+
+@example
+* register.el (insert-register): Return nil.
+(jump-to-register): Likewise.
+
+* sort.el (sort-subr): Return nil.
+
+* tex-mode.el (tex-bibtex-file, tex-file, tex-region):
+Restart the tex shell if process is gone or stopped.
+(tex-shell-running): New function.
+
+* expr.c (store_one_arg): Round size up for move_block_to_reg.
+(expand_call): Round up when emitting USE insns.
+* stmt.c (assign_parms): Round size up for move_block_from_reg.
+@end example
+
+It's important to name the changed function or variable in full.  Don't
+abbreviate function or variable names, and don't combine them.
+Subsequent maintainers will often search for a function name to find all
+the change log entries that pertain to it; if you abbreviate the name,
+they won't find it when they search.
+
+For example, some people are tempted to abbreviate groups of function
+names by writing @samp{* register.el (@{insert,jump-to@}-register)};
+this is not a good idea, since searching for @code{jump-to-register} or
+@code{insert-register} would not find that entry.
+
+Separate unrelated change log entries with blank lines.  When two
+entries represent parts of the same change, so that they work together,
+then don't put blank lines between them.  Then you can omit the file
+name and the asterisk when successive entries are in the same file.
+
+@node Simple Changes
+@subsection Simple Changes
+
+Certain simple kinds of changes don't need much detail in the change
+log.
+
+When you change the calling sequence of a function in a simple fashion,
+and you change all the callers of the function, there is no need to make
+individual entries for all the callers that you changed.  Just write in
+the entry for the function being called, ``All callers changed.''
+
+@example
+* keyboard.c (Fcommand_execute): New arg SPECIAL.
+All callers changed.
+@end example
+
+When you change just comments or doc strings, it is enough to write an
+entry for the file, without mentioning the functions.  Just ``Doc
+fixes'' is enough for the change log.
+
+There's no need to make change log entries for documentation files.
+This is because documentation is not susceptible to bugs that are hard
+to fix.  Documentation does not consist of parts that must interact in a
+precisely engineered fashion.  To correct an error, you need not know
+the history of the erroneous passage; it is enough to compare what the
+documentation says with the way the program actually works.
+
+@node Conditional Changes
+@subsection Conditional Changes
+
+C programs often contain compile-time @code{#if} conditionals.  Many
+changes are conditional; sometimes you add a new definition which is
+entirely contained in a conditional.  It is very useful to indicate in
+the change log the conditions for which the change applies.
+
+Our convention for indicating conditional changes is to use square
+brackets around the name of the condition.
+
+Here is a simple example, describing a change which is conditional but
+does not have a function or entity name associated with it:
+
+@example
+* xterm.c [SOLARIS2]: Include string.h.
+@end example
+
+Here is an entry describing a new definition which is entirely
+conditional.  This new definition for the macro @code{FRAME_WINDOW_P} is
+used only when @code{HAVE_X_WINDOWS} is defined:
+
+@example
+* frame.h [HAVE_X_WINDOWS] (FRAME_WINDOW_P): Macro defined.
+@end example
+
+Here is an entry for a change within the function @code{init_display},
+whose definition as a whole is unconditional, but the changes themselves
+are contained in a @samp{#ifdef HAVE_LIBNCURSES} conditional:
+
+@example
+* dispnew.c (init_display) [HAVE_LIBNCURSES]: If X, call tgetent.
+@end example
+
+Here is an entry for a change that takes affect only when
+a certain macro is @emph{not} defined:
+
+@example
+(gethostname) [!HAVE_SOCKETS]: Replace with winsock version.
+@end example
+
+@node Man Pages
+@section Man Pages
+
+In the GNU project, man pages are secondary.  It is not necessary or
+expected for every GNU program to have a man page, but some of them do.
+It's your choice whether to include a man page in your program.
+
+When you make this decision, consider that supporting a man page
+requires continual effort each time the program is changed.  The time
+you spend on the man page is time taken away from more useful work.
+
+For a simple program which changes little, updating the man page may be
+a small job.  Then there is little reason not to include a man page, if
+you have one.
+
+For a large program that changes a great deal, updating a man page may
+be a substantial burden.  If a user offers to donate a man page, you may
+find this gift costly to accept.  It may be better to refuse the man
+page unless the same person agrees to take full responsibility for
+maintaining it---so that you can wash your hands of it entirely.  If
+this volunteer later ceases to do the job, then don't feel obliged to
+pick it up yourself; it may be better to withdraw the man page from the
+distribution until someone else agrees to update it.
+
+When a program changes only a little, you may feel that the
+discrepancies are small enough that the man page remains useful without
+updating.  If so, put a prominent note near the beginning of the man
+page explaining that you don't maintain it and that the Texinfo manual
+is more authoritative.  The note should say how to access the Texinfo
+documentation.
+
+@node Reading other Manuals
+@section Reading other Manuals
+
+There may be non-free books or documentation files that describe the
+program you are documenting.
+
+It is ok to use these documents for reference, just as the author of a
+new algebra textbook can read other books on algebra.  A large portion
+of any non-fiction book consists of facts, in this case facts about how
+a certain program works, and these facts are necessarily the same for
+everyone who writes about the subject.  But be careful not to copy your
+outline structure, wording, tables or examples from preexisting non-free
+documentation.  Copying from free documentation may be ok; please check
+with the FSF about the individual case.
+
+@node Managing Releases
+@chapter The Release Process
+
+Making a release is more than just bundling up your source files in a
+tar file and putting it up for FTP.  You should set up your software so
+that it can be configured to run on a variety of systems.  Your Makefile
+should conform to the GNU standards described below, and your directory
+layout should also conform to the standards discussed below.  Doing so
+makes it easy to include your package into the larger framework of
+all GNU software.
+
+@menu
+* Configuration::               How Configuration Should Work
+* Makefile Conventions::       Makefile Conventions
+* Releases::                    Making Releases
+@end menu
+
+@node Configuration
+@section How Configuration Should Work
+
+Each GNU distribution should come with a shell script named
+@code{configure}.  This script is given arguments which describe the
+kind of machine and system you want to compile the program for.
+
+The @code{configure} script must record the configuration options so
+that they affect compilation.
+
+One way to do this is to make a link from a standard name such as
+@file{config.h} to the proper configuration file for the chosen system.
+If you use this technique, the distribution should @emph{not} contain a
+file named @file{config.h}.  This is so that people won't be able to
+build the program without configuring it first.
+
+Another thing that @code{configure} can do is to edit the Makefile.  If
+you do this, the distribution should @emph{not} contain a file named
+@file{Makefile}.  Instead, it should include a file @file{Makefile.in} which
+contains the input used for editing.  Once again, this is so that people
+won't be able to build the program without configuring it first.
+
+If @code{configure} does write the @file{Makefile}, then @file{Makefile}
+should have a target named @file{Makefile} which causes @code{configure}
+to be rerun, setting up the same configuration that was set up last
+time.  The files that @code{configure} reads should be listed as
+dependencies of @file{Makefile}.
+
+All the files which are output from the @code{configure} script should
+have comments at the beginning explaining that they were generated
+automatically using @code{configure}.  This is so that users won't think
+of trying to edit them by hand.
+
+The @code{configure} script should write a file named @file{config.status}
+which describes which configuration options were specified when the
+program was last configured.  This file should be a shell script which,
+if run, will recreate the same configuration.
+
+The @code{configure} script should accept an option of the form
+@samp{--srcdir=@var{dirname}} to specify the directory where sources are found
+(if it is not the current directory).  This makes it possible to build
+the program in a separate directory, so that the actual source directory
+is not modified.
+
+If the user does not specify @samp{--srcdir}, then @code{configure} should
+check both @file{.} and @file{..} to see if it can find the sources.  If
+it finds the sources in one of these places, it should use them from
+there.  Otherwise, it should report that it cannot find the sources, and
+should exit with nonzero status.
+
+Usually the easy way to support @samp{--srcdir} is by editing a
+definition of @code{VPATH} into the Makefile.  Some rules may need to
+refer explicitly to the specified source directory.  To make this
+possible, @code{configure} can add to the Makefile a variable named
+@code{srcdir} whose value is precisely the specified directory.
+
+The @code{configure} script should also take an argument which specifies the
+type of system to build the program for.  This argument should look like
+this:
+
+@example
+@var{cpu}-@var{company}-@var{system}
+@end example
+
+For example, a Sun 3 might be @samp{m68k-sun-sunos4.1}.
+
+The @code{configure} script needs to be able to decode all plausible
+alternatives for how to describe a machine.  Thus, @samp{sun3-sunos4.1}
+would be a valid alias.  For many programs, @samp{vax-dec-ultrix} would
+be an alias for @samp{vax-dec-bsd}, simply because the differences
+between Ultrix and @sc{BSD} are rarely noticeable, but a few programs
+might need to distinguish them.
+@c Real 4.4BSD now runs on some Suns.
+
+There is a shell script called @file{config.sub} that you can use
+as a subroutine to validate system types and canonicalize aliases.
+
+Other options are permitted to specify in more detail the software
+or hardware present on the machine, and include or exclude optional
+parts of the package:
+
+@table @samp
+@item --enable-@var{feature}@r{[}=@var{parameter}@r{]}
+Configure the package to build and install an optional user-level
+facility called @var{feature}.  This allows users to choose which
+optional features to include.  Giving an optional @var{parameter} of
+@samp{no} should omit @var{feature}, if it is built by default.
+
+No @samp{--enable} option should @strong{ever} cause one feature to
+replace another.  No @samp{--enable} option should ever substitute one
+useful behavior for another useful behavior.  The only proper use for
+@samp{--enable} is for questions of whether to build part of the program
+or exclude it.
+
+@item --with-@var{package}
+@c @r{[}=@var{parameter}@r{]}
+The package @var{package} will be installed, so configure this package
+to work with @var{package}.
+
+@c  Giving an optional @var{parameter} of
+@c @samp{no} should omit @var{package}, if it is used by default.
+
+Possible values of @var{package} include 
+@samp{gnu-as} (or @samp{gas}), @samp{gnu-ld}, @samp{gnu-libc},
+@samp{gdb},
+@samp{x}, 
+and
+@samp{x-toolkit}.
+
+Do not use a @samp{--with} option to specify the file name to use to
+find certain files.  That is outside the scope of what @samp{--with}
+options are for.
+
+@item --nfp
+The target machine has no floating point processor.
+
+@item --gas
+The target machine assembler is GAS, the GNU assembler.
+This is obsolete; users should use @samp{--with-gnu-as} instead.
+
+@item --x
+The target machine has the X Window System installed.
+This is obsolete; users should use @samp{--with-x} instead.
+@end table
+
+All @code{configure} scripts should accept all of these ``detail''
+options, whether or not they make any difference to the particular
+package at hand.  In particular, they should accept any option that
+starts with @samp{--with-} or @samp{--enable-}.  This is so users will
+be able to configure an entire GNU source tree at once with a single set
+of options.
+
+You will note that the categories @samp{--with-} and @samp{--enable-}
+are narrow: they @strong{do not} provide a place for any sort of option
+you might think of.  That is deliberate.  We want to limit the possible
+configuration options in GNU software.  We do not want GNU programs to
+have idiosyncratic configuration options.
+
+Packages that perform part of the compilation process may support cross-compilation.
+In such a case, the host and target machines for the program may be
+different.  The @code{configure} script should normally treat the
+specified type of system as both the host and the target, thus producing
+a program which works for the same type of machine that it runs on.
+
+The way to build a cross-compiler, cross-assembler, or what have you, is
+to specify the option @samp{--host=@var{hosttype}} when running
+@code{configure}.  This specifies the host system without changing the
+type of target system.  The syntax for @var{hosttype} is the same as
+described above.
+
+Bootstrapping a cross-compiler requires compiling it on a machine other
+than the host it will run on.  Compilation packages accept a
+configuration option @samp{--build=@var{hosttype}} for specifying the
+configuration on which you will compile them, in case that is different
+from the host.
+
+Programs for which cross-operation is not meaningful need not accept the
+@samp{--host} option, because configuring an entire operating system for
+cross-operation is not a meaningful thing.
+
+Some programs have ways of configuring themselves automatically.  If
+your program is set up to do this, your @code{configure} script can simply
+ignore most of its arguments.
+
+@comment The makefile standards are in a separate file that is also
+@comment included by make.texinfo.  Done by roland@gnu.ai.mit.edu on 1/6/93.
+@comment For this document, turn chapters into sections, etc.
+@lowersections
+@include make-stds.texi
+@raisesections
+
+@node Releases
+@section Making Releases
+
+Package the distribution of @code{Foo version 69.96} up in a gzipped tar
+file with the name @file{foo-69.96.tar.gz}.  It should unpack into a
+subdirectory named @file{foo-69.96}.
+
+Building and installing the program should never modify any of the files
+contained in the distribution.  This means that all the files that form
+part of the program in any way must be classified into @dfn{source
+files} and @dfn{non-source files}.  Source files are written by humans
+and never changed automatically; non-source files are produced from
+source files by programs under the control of the Makefile.
+
+Naturally, all the source files must be in the distribution.  It is okay
+to include non-source files in the distribution, provided they are
+up-to-date and machine-independent, so that building the distribution
+normally will never modify them.  We commonly include non-source files
+produced by Bison, @code{lex}, @TeX{}, and @code{makeinfo}; this helps avoid
+unnecessary dependencies between our distributions, so that users can
+install whichever packages they want to install.
+
+Non-source files that might actually be modified by building and
+installing the program should @strong{never} be included in the
+distribution.  So if you do distribute non-source files, always make
+sure they are up to date when you make a new distribution.
+
+Make sure that the directory into which the distribution unpacks (as
+well as any subdirectories) are all world-writable (octal mode 777).
+This is so that old versions of @code{tar} which preserve the
+ownership and permissions of the files from the tar archive will be
+able to extract all the files even if the user is unprivileged.
+
+Make sure that all the files in the distribution are world-readable.
+
+Make sure that no file name in the distribution is more than 14
+characters long.  Likewise, no file created by building the program
+should have a name longer than 14 characters.  The reason for this is
+that some systems adhere to a foolish interpretation of the POSIX
+standard, and refuse to open a longer name, rather than truncating as
+they did in the past.
+
+Don't include any symbolic links in the distribution itself.  If the tar
+file contains symbolic links, then people cannot even unpack it on
+systems that don't support symbolic links.  Also, don't use multiple
+names for one file in different directories, because certain file
+systems cannot handle this and that prevents unpacking the
+distribution.
+
+Try to make sure that all the file names will be unique on MS-DOS.  A
+name on MS-DOS consists of up to 8 characters, optionally followed by a
+period and up to three characters.  MS-DOS will truncate extra
+characters both before and after the period.  Thus,
+@file{foobarhacker.c} and @file{foobarhacker.o} are not ambiguous; they
+are truncated to @file{foobarha.c} and @file{foobarha.o}, which are
+distinct.
+
+Include in your distribution a copy of the @file{texinfo.tex} you used
+to test print any @file{*.texinfo} or @file{*.texi} files.
+
+Likewise, if your program uses small GNU software packages like regex,
+getopt, obstack, or termcap, include them in the distribution file.
+Leaving them out would make the distribution file a little smaller at
+the expense of possible inconvenience to a user who doesn't know what
+other files to get.
+
+@contents
+
+@bye
+Local variables:
+update-date-leading-regexp: "@c This date is automagically updated when you save this file:\n@set lastupdate "
+update-date-trailing-regexp: ""
+eval: (load "/gd/gnuorg/update-date.el")
+eval: (add-hook 'write-file-hooks 'update-date)
+End:
diff --git a/gprof/.gdbinit b/gprof/.gdbinit
new file mode 100644 (file)
index 0000000..e519472
--- /dev/null
@@ -0,0 +1 @@
+dir ..
diff --git a/gprof/ChangeLog b/gprof/ChangeLog
new file mode 100644 (file)
index 0000000..24626c2
--- /dev/null
@@ -0,0 +1,1319 @@
+1999-04-26  Tom Tromey  <tromey@cygnus.com>
+
+       * aclocal.m4, configure: Updated for new version of libtool.
+
+1999-04-06  Ian Lance Taylor  <ian@zembu.com>
+
+       * gprof.h (LC_MESSAGES): Never define.
+       * gprof.c (main): Don't pass LC_MESSAGES to setlocale if the
+       system does not define it.
+
+1999-04-05  H.J. Lu  <hjl@gnu.org>
+
+       * corefile.c (core_create_line_syms): Don't use fixed size array
+       for prev_name and prev_filename.
+
+1999-04-04  Michael Hohmuth  <hohmuth@innocent.com>
+
+       * gprof.h (FF_BSD44): Define.
+       * gmon.h (struct raw_phdr): Add version, profrate, and spare
+       fields unconditionally.
+       (struct old_raw_phdr): New struct.
+       * gprof.c (main): Handle -O 4.4bsd.
+       * gmon_io.c (gmon_out_read): Handle BSD 4.4 format, either
+       automatically or by user specification.
+       (gmon_out_write): Handle BSD 4.4 format.
+       * configure.in: Don't set BSD44_FORMAT.
+       * gprof.texi (Miscellaneous Options): Document -O 4.4bsd.
+       * configure, gconfig.in: Rebuild.
+
+Tue Feb 16 17:01:33 1999  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Change AC_PREREQ to 2.13.  Change AM_PROG_INSTALL
+       to AC_PROG_INSTALL.  Remove AM_CYGWIN32.  Change AM_EXEEXT to
+       AC_EXEEXT.  Add comment to AC_DEFINE.
+       * acconfig.h: Remove.
+       * aclocal.m4: Rebuild.
+       * configure: Rebuild.
+       * Makefile.in: Rebuild.
+       * gconfig.in: Rebuild.
+
+Sun Dec  6 21:57:50 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * gprof.texi (Symspecs): Mention that you have to add any
+       underscore yourself when naming a symbol.
+
+Mon Nov  2 15:05:33 1998  Geoffrey Noer  <noer@cygnus.com>
+
+        * configure.in: detect cygwin* instead of cygwin32*
+        * configure: regenerate
+
+Wed Aug 12 14:59:06 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       Avoid some overflow cases:
+       * basic_blocks.h (bb_min_calls): Change to unsigned long.
+       * call_graph.h (cg_tally): Change count parameter to unsigned
+       long.
+       * cg_arcs.h (Arc): Change count field to unsigned long.
+       (arc_add): Change count parameter to unsigned long.
+       * source.h (Source_File): Change ncalls field to unsigned long.
+       * symtab.h (Sym): Change fields ncalls, bb_calls, and
+       cg.self_calls to unsigned long.
+       * Many files: Update accordingly.
+
+       * configure, Makefile.in, aclocal.m4: Rebuild with current tools.
+
+Fri Jul 10 17:29:49 1998  Stan Cox  <scox@equinox.cygnus.com>
+
+       * configure.in (BSD44_FORMAT): Define for cygwin32, win32, mingw32
+       * configure: Rebuild.
+
+Fri Jun 12 13:40:05 1998  Tom Tromey  <tromey@cygnus.com>
+
+       * po/Make-in (all-yes): If maintainer mode, depend on .pot file.
+       ($(PACKAGE).pot): Unconditionally depend on POTFILES.
+
+Sun May 10 22:35:33 1998  Jeffrey A Law  (law@cygnus.com)
+
+       * po/Make-in (install-info): New target.
+
+Tue May  5 18:28:40 1998  Tom Tromey  <tromey@cygnus.com>
+
+       * gprof.h (_): Undefine BFD's version.
+
+Tue Apr 28 19:17:33 1998  Tom Tromey  <tromey@cygnus.com>
+
+       * gprof.c (main): Conditionally call setlocale.
+       * gprof.h: Include <locale.h> if HAVE_LOCALE_H.
+       (LC_MESSAGES): Now can be defined even when ENABLE_NLS.
+
+Tue Apr 28 19:50:09 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * corefile.c: Rename from core.c.
+       * corefile.h: Rename from core.h.
+       * Many .c files: Include corefile.h rather than core.h.
+       * Makefile.am (sources): Change core.c to corefile.c.
+       (noinst_HEADERS): Change core.h to corefile.h.
+       ($(OBJECTS)): Depend upon corefile.h rather than core.h.
+       (corefile.o): Rename target from core.o, depend upon corefile.c.
+       * Makefile.in, po/POTFILES.in: Rebuild.
+
+Mon Apr 27 16:50:40 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Change version number to 2.9.4
+       * configure: Rebuild.
+
+Wed Apr 22 16:01:17 1998  Tom Tromey  <tromey@cygnus.com>
+
+       * po/Make-in (MKINSTALLDIRS): Don't look in $(top_srcdir).
+
+Wed Apr 22 00:00:22 1998  Tom Tromey  <tromey@scribbles.cygnus.com>
+
+       * gprof.h: Added includes and defines for gettext.
+       * configure.in (ALL_LINGUAS): New macro.
+       Call CY_GNU_GETTEXT.  Create po/Makefile.in and po/Makefile.
+       * acconfig.h (ENABLE_NLS, HAVE_CATGETS, HAVE_GETTEXT, HAVE_STPCPY,
+       HAVE_LC_MESSAGES): Define.
+       * gprof.c (main): Call setlocale, bindtextdomain, textdomain.
+       * Makefile.am (SUBDIRS): New macro.
+       (INCLUDES): Look in intl dirs for headers.  Define LOCALEDIR.
+       (gprof_DEPENDENCIES): Added INTLDEPS.
+       (gprof_LDADD): Added INTLLLIBS.
+       (POTFILES): New macro.
+       (po/POTFILES.in): New target.
+       * Many files: Wrap user-visible strings with gettext invocation.
+
+Tue Apr  7 12:43:37 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       From hjl@lucon.org <H.J. Lu>:
+       * Makefile.am (diststuff): New target.
+       * Makefile.in: Rebuild.
+
+Mon Mar 30 12:47:48 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Set version to 2.9.1.
+       * configure: Rebuild.
+
+       * Branched binutils 2.9.
+
+Sat Mar 28 23:09:08 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       Fix some gcc -Wall warnings:
+       * cg_arcs.c (num_cycles): Change to unsigned int.
+       (numarcs): Likewise.
+       (arc_add): Change maxarcs to unsigned int.
+       (cg_assemble): Change index to unsigned int.
+       * cg_arcs.h (num_cycles, numarcs): Update declarations.
+       * cg_print.c (cg_print): Change index to unsigned int.
+       (cg_print_index): Change index, nnames, todo, i, and j to unsigned
+       int.
+       (cg_print_file_ordering): Change symbol_count and index2 to
+       unsigned int.
+       * core.c (symbol_map_count): Change to unsigned int.
+       (core_create_function_syms): Change j to unsigned int.
+       (core_create_line_syms): Add cast to avoid warning.
+       * hist.c (hist_assign_samples): Change j to unsigned int.
+       (hist_print): Change index to unsigned i nt.  Add cast to avoid
+       warning.
+       * sym_ids.c (parse_spec): Add casts to avoid warning.
+       * symtab.c (symtab_finalize): Change j to unsigned int.
+       (sym_lookup): Update printf format strings.
+       * symtab.h (Sym_Table): Change len to unsigned int.
+       * tahoe.c (tahoe_reladdr): Add casts to avoid warnings.
+
+Tue Mar 24 19:00:11 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       Add --demangle and --no-demangle options:
+       * gprof.h (demangle): Declare.
+       * gprof.c (demangle): New global variable.
+       (OPTION_DEMANGLE, OPTION_NO_DEMANGLE): Define.
+       (long_options): Add "demangle" and "no-demangle".
+       (usage): Mention --demangle and --no-demangle.
+       (main): Handle OPTION_DEMANGLE and OPTION_NO_DEMANGLE.
+       * utils.c (print_name_only): Only demangle symbol name if demangle
+       is true.
+       * gprof.texi (Output Options): Document new options.
+
+Fri Mar 20 19:21:56 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in: Rebuild with automake 1.2e.
+       * aclocal.m4, configure: Rebuild with libtool 1.2.
+
+Thu Feb 12 14:36:05 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * gprof.c (usage): Update bug-gnu-utils address.
+
+Sat Feb  7 15:43:12 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure, aclocal.m4: Rebuild with new libtool.
+
+Fri Feb  6 12:02:28 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * alpha.c (alpha_Instruction): Use int, not signed.
+
+Fri Feb  6 02:00:19 1998  Jeffrey A Law  (law@cygnus.com)
+
+       * core.c (core_init): Adding missing "break".
+
+Thu Feb  5 12:49:37 1998  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure, Makefile.in, aclocal.m4: Rebuild with new libtool.
+
+Tue Feb  3 14:25:25 1998  Brent Baccala  <baccala@freesoft.org>
+
+       * bbconv.pl: New file.
+       * Makefile.am (EXTRA_DIST): Add bbconv.pl.
+       * Makefile.in: Rebuild.
+
+       * gprof.texi: Extensive additions to document all arguments and
+       output formats.
+
+       * symtab.c (symtab_finalize): Prefer function symbols over line
+       symbols.
+       (dbg_sym_lookup): Correct debugging messages.
+
+       * gprof.c (main): --sum implies --line.
+
+       * cg_print.c (cg_print): When doing line by line profiling, don't
+       use a non-function as a main listing item.
+
+       * call_graph.c (cg_tally): When using line by line profiling, use
+       the function symbol as the child.
+
+       * symtab.h (NBBS): Define.
+       (Sym): Add bb_addr and bb_calls fields.
+       * basic_blocks.c (bb_read_rec): Save multiple basic blocks per
+       symbol.
+       (bb_write_blocks): Adjust for multiple basic blocks per symbol.
+       (print_exec_counts): Don't check whether a symbol is the start of
+       a basic block.  Print all basic blocks for a symbol.
+       (annotate_with_count): Rewrite to print all basic block counts and
+       to pay attention to width argument.
+       (print_annotated_source): Don't check whether symbol is the start
+       of a basic block.
+
+       Make it possible to build a cross gprof, although a few cases are
+       still not handled:
+       * configure.in: Don't set MY_TARGET.
+       * gprof.h: Don't include MACHINE_H.  Don't define FOPEN_RB or
+       FOPEN_WB; just get them from sysdep.h.
+       * core.h (min_insn_size, offset_to_code): Declare.
+       * core.c (MIN_INSN_SIZE): Don't define.
+       (min_insn_size, offset_to_code): New variables.
+       (core_init): Initialize min_insn_size and offset_to_code.
+       (find_call): New function.
+       (core_create_line_syms): Don't use min_dist.  Set is_static in
+       pass 2.
+       * hist.c (UNITS_TO_CODE): Define.
+       * gprof.c (default_excluded_list): Add "__mcount_internal".
+       * gmon.h: Change TARGET_alpha to __alpha__.
+       * hertz.h: Ifdef MACH, define hertz as HZ.
+       * alpha.c (alpha_Instruction): Rename from Instruction.  Change
+       all references.
+       (alpha_find_call): Rename from find_call.
+       * alpha.h: Remove.
+       * dummy.c, dummy.h: Remove.
+       * i386.c (i386_iscall): Rename from iscall.  Change all
+       references.  Check for call instruction, not jump or lcall.
+       (i386_find_call): Rename from find_call.  Correct for VMA.
+       Correct call destination computation.  Don't dereference symbol if
+       it is NULL.
+       * i386.h: Remove.
+       * ns532.c, ns532.h: Remove.
+       * sparc.c (CALL): Define.
+       (sparc_find_call): Rename from find_call.
+       * sparc.h: Remove.
+       * tahoe.c: Include cg_arcs.h, core.h, hist.h, and symtab.h.  Don't
+       include time_host.h.
+       (CALLF, PC): Define.
+       (enum tahoe_opermodes, tahoe_operandenum): Define.  Rename all
+       references to opermodes or operandenum to these.
+       (tahoe_operandmode): Rename from operandmode.  Call abort if
+       switch does not return.
+       (tahoe_operandname): Rename from operandname.  Call abort if
+       switch does not return.
+       (tahoe_operandlength): Rename from operandlength.  Call abort if
+       switch does not return.
+       (tahoe_reladdr): Rename from reladdr.
+       (tahoe_find_call): Rename from find_call.  Use core_text_space
+       rather than textspace.
+       * tahoe.h: Remove.
+       * vax.c (CALLS, PC): Define.
+       (enum opermodes, operandenum, struct modebyte): Define.
+       (vax_operandmode): Rename from operandmode.  Call abort if switch
+       does not return.
+       (vax_operandname): Rename from operandname.  Call abort if switch
+       does not return.
+       (vax_operandlength): Rename from operandlength.  Call abort if
+       switch does not return.
+       (vax_reladdr): Rename from reladdr.
+       (vax_find_call): Rename from find_call.
+       * vax.h: Remove.
+       * Makefile.am (AUTOMAKE_OPTIONS): Set to cygnus.
+       (MY_TARGET): Remove.
+       (INCLUDES): Remove -DTARGET_$(MY_TARGET) and -DMACHINE_H=
+       \"$(MY_TARGET).h\".
+       (gprof_SOURCES): Add i386.c, alpha.c, vax.c, tahoe.c, sparc.c.
+       (gprof_DEPENDENCIES): Remove $(MY_TARGET).o.
+       (gprof_LDADD): Likewise.
+       (noinst_HEADERS): Remove alpha.h, i386.h, ns532.h, sparc.h,
+       tahoe.h, vax.h, dummy.h.
+       (EXTRA_DIST): Remove alpha.c, i386.c, ns532.c, sparc.c, tahoe.c,
+       vax.c, dummy.c.
+       ($(OBJECTS)): Don't depend upon $(MY_TARGET).h.
+       ($(MY_TARGET).o): Remove target.
+       (i386.o, alpha.o, vax.o, tahoe.o, sparc.o): New targets.
+       * configure, Makefile.in, aclocal.m4: Rebuild.
+
+Mon Dec 29 14:17:08 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * core.c (core_sym_class): Treat weak symbols as text symbols.
+       From Dean Gaudet <dgaudet@arctic.org>.
+
+Wed Sep 24 11:35:43 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * aclocal.m4: Rebuild with new libtool.
+       * Makefile.in: Rebuild with current automake.
+       * configure: Rebuild.
+
+Sat Aug  9 16:25:01 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Change version number to 2.8.2.  Call
+       AM_PROG_LIBTOOL.  Remove shared library handling; now handled by
+       libtool.  Add AM_CONFIG_HEADER.  Change AC_PROG_INSTALL to
+       AM_PROG_INSTALL.  Add AM_EXEEXT.
+       * Makefile.am (LINK): Remove.
+       (gprof_LDFLAGS): Remove
+       (gprof_DEPENDENCIES): Change libbfd.a to libbfd.la.
+       (gprof_LDADD): Likewise.
+       ($(OBJECTS)): Depend upon gconfig.h and ../bfd/config.h.
+       * gprof.h: Undefine PACKAGE and VERSION after including BFD
+       sysdep.h file, then include new gconfig.h file.
+       * gprof.c (VERSION): Don't define.
+       * acconfig.h: New file.
+       * stamp-h.in: New file.
+       * gconfig.in: New file, created by autoheader.
+       * Makefile.in, configure, aclocal.m4: Rebuild.
+
+Sat Jun 28 23:20:42 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * aclocal.m4, configure, Makefile.in: Rebuild with automake 1.2.
+
+Mon Jun 16 15:31:39 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.am (INCLUDES): Add -DDEBUG.
+       * Makefile.in: Rebuild.
+
+Tue Apr 15 14:19:30 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       Change to use automake:
+       * Makefile.am: New file.
+       * configure.in: Run AM_INIT_AUTOMAKE, AM_MAINTAINER_MODE, and
+       AM_CYGWIN32.
+       * aclocal.m4: New file, created by aclocal.
+       * Makefile.in: Replace with file created by automake --cygnus.
+       * configure: Rebuild.
+
+Thu Apr  3 13:21:25 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * gprof.c (VERSION): Define as "2.8.1".
+
+       * Branched binutils 2.8.
+
+Thu Mar 27 17:15:23 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * gprof.c (main): Correct copyright message.
+
+Mon Mar 24 11:12:26 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (.c.o): Define TARGET_$(MY_TARGET) when compiling.
+       * gmon.h: Use bytes counts rather than sizeof in struct raw_phdr
+       and struct raw_arc.
+
+Mon Mar 17 10:54:47 1997  David Mosberger-Tang  <davidm@azstarnet.com>
+
+       * cg_arcs.c (arc_add): memset() newly alloced arc to ensure
+       all fields are initialized with 0.
+
+Sat Mar 15 19:17:31 1997  H.J. Lu  <hjl@lucon.org>
+
+       * symtab.h (find_call): Declare.
+       * cg_arcs.c (cg_assemble): Don't declare find_call.
+       * hist.c (scale_and_align_entries): Declare.
+
+Thu Feb 27 12:46:53 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Define BSD44_FORMAT if the target looks like a
+       BSD4.4 derived system.
+       * configure: Rebuild.
+       * Makefile.in (.c.o): Add @DEFS@.
+       * gmon_io.c (gmon_out_read): In BSD44_FORMAT code, get profrate
+       from profrate field, not version field.
+
+Thu Jan 16 17:42:54 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * dummy.c (find_call): Clear ignore_direct_calls.
+
+Tue Dec 31 15:44:10 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (.c.o): Add -D_GNU_SOURCE.  Put $(CFLAGS) at the
+       end.
+       (gprof): Put $(CFLAGS) after the other options.
+
+Tue Nov 26 17:08:38 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure: Rebuild with autoconf 2.12.
+
+Wed Oct  2 15:23:16 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * sparc.c (find_call): Align p_lowpc to avoid bus error.
+
+Tue Oct  1 15:58:10 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * gprof.c (usage): Print bug report address.
+       (main): Change version printing to match current GNU standards.
+
+Fri Aug 30 12:16:11 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * gmon.h: Replace #elif with #else/#endif.
+
+Thu Aug 29 17:04:10 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * configure.in (i[345]86-*-*): Recognize i686 for pentium pro.
+       * configure: Regenerate.
+
+Thu Aug 22 17:12:30 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Set and substitute HLDENV.
+       * configure: Rebuild.
+       * Makefile.in (HLDENV): New variable.
+       (gprof): Use $(HLDENV).
+
+Wed Aug  7 14:43:51 1996  Philippe De Muyter  <phdm@info.ucl.ac.be>
+
+       * core.c (read_function_mappings): Cast xmalloc return.
+
+Thu Jul  4 12:01:42 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * gprof.c (VERSION): Define as "2.7.1".
+
+       * Released binutils 2.7.
+
+       * bb_exit_func.c: Rename from __bb_exit_func.c, so that it can be
+       stored on a System V file system.
+
+Thu Jun 27 11:36:22 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Call AC_ISC_POSIX.
+       * configure: Rebuild.
+       * Makefile.in (gprof): Pass $(CFLAGS) during link.
+       * hertz.c: Don't include <sys/time.h>; let sysdep.h handle that.
+       If HAVE_SETITIMER is not defined, try using sysconf.
+
+Mon Jun 24 18:27:28 1996  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+
+       * Makefile.in (exec_prefix, bindir, libdir, mandir, infodir, datadir,
+       INSTALL_PROGRAM, INSTALL_DATA): Use autoconf-set values.
+       * configure.in (AC_PREREQ): autoconf 2.5 or higher.
+       (AC_PROG_INSTALL): added.
+       * configure: Rebuilt.
+
+Mon Jun 24 12:03:09 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: On alpha*-*-osf*, link against libbfd.a if not
+       using shared libraries.
+       * configure: Rebuild with autoconf 2.10.
+
+Tue Jun 18 17:35:58 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * core.c (core_create_line_syms): Use xstrdup rather than strdup.
+       * source.c (source_file_lookup_path): Likewise.
+
+Mon Apr  8 14:44:33 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Permit --enable-shared to specify a list of
+       directories.
+       * configure: Rebuild.
+
+Thu Mar 21 17:18:25 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * core.c (core_create_function_syms): Move filename and func_name
+       inside ifdef where they are used.
+
+       * core.c (core_sym_class): Parenthesize && within ||.
+       * symtab.c (symtab_finalize): Correct parenthesization.
+
+       * cg_print.h (cg_print_file_ordering): Declare.
+       (cg_print_function_ordering): Declare.
+
+       * __bb_exit_func.c (__bb_exit_func): Replace bcopy with memcpy.
+       * cg_arcs.c (arc_add): Likewise.
+       * cg_print.c (cg_print_function_ordering): Likewise.
+
+Thu Mar 21 17:02:02 1996  David Mosberger-Tang  <davidm@azstarnet.com>
+
+       * gprof.c (default_excluded_list): Add "__mcount".
+
+       * gprof.c (main): Change ifdef __osf__ to __alpha__.
+
+       * gmon_io.c (gmon_out_read): If BSD44_FORMAT is defined, get the
+       profiling rate from the header.
+
+       * gmon.h (struct raw_phdr): Only include pad if both __alpha__ and
+       __osf__ are defined.  Add new fields if BSD44_FORMAT is defined.
+
+       * alpha.h (MIN_INSN_SIZE): Define.
+       * core.c (MIN_INSN_SIZE): If not defined, define as 1.
+       (core_sym_class): Ignore debugging symbols.
+       (core_create_line_syms): Use MIN_INSN_SIZE when gathering line
+       information.
+
+Wed Mar 20 18:15:47 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * cg_print.c (cg_print_function_ordering): Fix __GNUC__ misspelled
+       as __GNU_C__.
+       (order_and_dump_functions_by_arcs): Likewise.
+
+Tue Mar 12 12:19:50 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure: Rebuild with autoconf 2.8.
+
+Sun Feb 18 15:06:18 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Check for 'do not mix' from native linker before
+       trying to use -rpath.
+       * configure: Rebuild.
+
+Tue Feb 13 15:32:53 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Set HDLFLAGS for *-*-hpux with --enable-shared.
+       * configure: Rebuild.
+
+Wed Feb  7 14:03:17 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       * configure.in: Don't set CC.  Look for --enable-shared.  Set
+       BFDLIB and HLDFLAGS and substitute them.
+       * configure: Rebuild.
+       * Makefile.in (LIBS): Use @BFDLIB@.
+       (HLDFLAGS): New variable.
+       (gprof): Use $(HLDFLAGS).
+
+Mon Feb  5 16:34:44 1996  Ian Lance Taylor  <ian@cygnus.com>
+
+       Support for building bfd and opcodes as shared libraries, based on
+       patches from Alan Modra <alan@spri.levels.unisa.edu.au>:
+       * Makefile.in (LIBDEPS): New variable.
+       (LIBS): Use -L../bfd -lbfd.
+       (gprof): Depend upon $(LIBDEPS) rather than $(LIBS).
+
+Sat Dec 30 10:11:03 1995  Jeffrey A Law  (law@cygnus.com)
+
+       * gprof.c (long_options): Add "--function-ordering" and
+       "--file-ordering" options.
+       (usage): Add new options to usage message.
+       (main): Handle new options.
+       * gprof.h (STYLE_FUNCTION_ORDER): Define.
+       (STYLE_FILE_ORDER): Define.
+       (function_mapping_file): Declare.
+       * cg_arcs.c (arcs, numarcs): New globals.
+       (arc_add): Put new arcs into the arc array so the function/file
+       ordering code can examine them.
+       * cg_arcs.h (struct arc): New field "has_been_placed".
+       (arcs, numarcs): Declare new globals.
+       * core.c (symbol_map, symbol_map_count): New globals.
+       (read_function_mappings): New function to read in a function
+       to object map file.
+       (core_init): Call read_function_mappings if a function mapping
+       file exists.
+       (core_create_function_syms): Handle function to object file
+       mappings.
+       * symtab.h (struct sym): New fields "mapped", "has_been_placed",
+       "nuses", "prev".
+       * cg_print.c (cmp_arc_count): New function for sorting arcs.
+       (cmp_fun_nuses): Likewise for functions.
+       (cg_print_function_ordering): New function to print a suggested
+       function ordering.
+       (cg_print_file_ordering): Likewise for ordering .o files.
+       (order_and_dump_functions_by_arcs): Helper function for function
+       and object file ordering code.
+
+Sun Dec 24 21:32:27 1995  Jeffrey A Law  (law@cygnus.com)
+
+       * core.c (core_sym_class): Ignore symbols without BSF_FUNCTION
+       set if ignore_non_function is set.
+       * gprof.h (ignore_non_functions): Declare.
+       * gprof.c (ignore_non_functions): Define.
+       (long_options): Add "ignore-non-functions".
+       (usage): Add new options.
+       (main): Recognize "-D" and "--ignore-non-functions" option.
+
+Tue Nov 21 13:24:39 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       * Makefile.in (.m.c): Strip out directory name from function
+       name.
+
+       * hist.c (scale_and_align_entries): Don't use DEFUN_VOID.  Do
+       UNITS_TO_CODE adjustment unconditionally; compiler can optimize
+       away zero-offset case.  Refer to scaled_addr, not aligned_addr.
+
+       * vax.c: Don't include vax.h here.
+
+Thu Nov 16 03:41:37 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       Version 2.6 released.
+
+Wed Nov  8 11:40:04 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * gprof.c (main): Cast getenv return value.
+
+Mon Nov  6 15:05:00 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       * Makefile.in (TAGS): New target.
+
+Wed Nov  1 12:51:21 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+       * Makefile.in (DISTSTUFF):  Rename to GEN_FILES, to avoid confusion.
+       (all):  Depend on $(GEN_FILES), not diststuff (which also depends
+       on info).
+
+Wed Nov  1 15:23:15 1995  Manfred Hollstein KS/EF4A 60/1F/110 #40283  <manfred@lts.sel.alcatel.de>
+
+       * sym_ids.c: Include <ctype.h>.
+
+Wed Oct 25 13:24:31 1995  Per Bothner  <bothner@kalessin.cygnus.com>
+
+       * Makefile.in (diststuff):  Also make info.
+       (mostlyclean):  Don't remove gprof.info*.
+       (maintainer-clean realclean):  Also remove *.info*.
+
+Fri Oct  6 16:25:32 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       Mon Sep 25 22:49:32 1995  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * Makefile.in: Add dependecies for $(OBJS) on header files.
+
+       * cg_print.c (print_cycle, print_members, cg_print_index): Fix new
+       style output format to make it consistent.
+       * dummy.c (find_call): Fix typo in error message.
+
+Wed Sep 20 13:21:02 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (maintainer-clean): New target, synonym for
+       realclean.
+
+Fri Sep  8 14:38:08 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * Makefile.in (install): Don't install in $(tooldir).
+
+Fri Aug 25 15:30:05 1995  Ken Raeburn  <raeburn@cygnus.com>
+
+       NS32K changes from Ian Dall:
+       * configure.in: Use ns32k, not ns532.
+       * ns532.c: Include symtab.h.
+       (find_call): Renamed from findcall.  Print a message.
+       * ns532.h: Remove dummy.h comments.
+
+Tue Aug 22 10:00:45 1995  Jeffrey A. Law  <law@rtl.cygnus.com>
+
+       * Makefile.in (install): Remove "brokensed" hack, unnecessary now
+       that we're using autoconf.
+
+Wed Jul 19 18:46:13 1995  Fred Fish  <fnf@cygnus.com>
+
+       * core.c (get_src_info): Cast arg 7 of bfd_find_nearest_line
+       to proper type of "unsigned int *".
+
+Fri Jun 16 15:29:36 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * configure.in: Use changequote around use of [].
+
+Mon Jun 12 12:14:52 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * Makefile.in (distclean, realclean): Remove config.cache and
+         config.log.
+
+Wed May 17 17:56:53 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * Makefile.in (Makefile): Added config.status to dependency list.
+         (config.status): New target.
+         (SHELL): New definition.
+
+Tue Apr 25 21:11:12 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in (install): Depend on "all".
+
+Thu Apr 20 17:29:07 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in: Change all references to MY_MACHINE to MY_TARGET,
+       to match configure script.
+
+Wed Apr 19 11:19:37 1995  J.T. Conklin  <jtc@rtl.cygnus.com>
+
+       * gen-c-prog.awk: Changed reference to "make-c-prog.awk" in
+         comment emitted by this script to gen-c-prog.awk.
+
+       * Makefile.in, configure.in: Converted to use autoconf.
+       * configure: New file, generated with autoconf 2.3.
+       * config/{mt-alpha, mt-dummy, mt-i386, mt-ns532, mt-sparc,
+         mt-tahoe, mt-vax}: Removed.
+
+Mon Mar 13 21:44:24 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * __bb_exit_func.c: New file, from David Mosberger-Tang.
+
+       Thu Feb  9 16:56:07 1995  David Mosberger-Tang  <davidm@piston.cs.arizona.edu>
+
+       * All *.c: More cleanup towards GNU format.
+
+       * gmon_out.h (struct gmon_hist_hdr, struct gmon_cg_arc_record): 
+       replaced sizeof (bfd_vma) by size (char*) because Ken tells me
+       that bfd_vma is only guaranteed to be at least as big as a pointer.
+
+       (GMON_Record_tag): added explicit enumeration values to ensure
+       compatibility across compilers.
+
+       * gmon_io.c (get_vma, put_vma): replaced sizeof(bfd_vma) by
+       sizeof(char*).
+
+Tue Feb  7 17:24:12 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * All *.c and *.h files: Ran "indent -gnu".  Cleaned up a couple
+       of constructs GNU indent couldn't handle.  Block comments not yet
+       rewritten in GNU format.
+
+       * gprof.c (VERSION): Changed to 2.6, to get in sync for next
+       binutils release.
+
+Sun Feb  5 16:19:46 1995  David Mosberger-Tang  <davidm@piston.cs.arizona.edu>
+
+       * symtab.c (symtab_finalize): ensure globals symbols really
+       are favored over static ones---even if their name looks less
+       preferable; this is important for HP-UX; for example, there
+       is a static label Ltext_something that aliases the global
+       symbol _start
+
+       * hist.c (hist_print): auto-scaling is now in effect for FSF-style
+       output only; also, auto-scaling is now performed based on
+       per-call, rather than total execution time, which is what it was
+       meant to be.
+
+       * gprof.h (File_Format): new type.
+
+       * gprof.c (VERSION): upped to 2.7---seems to be completely out of
+       sync with Cygnus version numbers though...
+
+       (long_options): renamed --gmon-info to --file-info, --width added,
+       renamed --old-file-format to --file-format
+       (main): dito; also added support to read prof files, but as
+       mon_out_read() is not implemented, it's #ifdef'd out for now
+
+       (usage): update to reflect new options.
+
+       * gmon_io.c: replaced "old_file_format" by more general
+        "file_format" option
+
+       * gmon.h (struct raw_phdr): fixed declaration for OSF/1.
+
+       * core.c (core_sym_class): added back check for __gnu_compiled and
+       ___gnu_compiled for the benefit of systems without
+       bfd_find_nearest_line() support
+
+       (get_src_info): now the libbfd is fixed, invoke bfd_find_nearest_line()
+       with section-relative addresses
+
+       (core_create_function_syms): get_src_info() calls are currently
+       enabled for OSF/1 only.  It appears to work allright for SunOS
+        4.1.x as well, but on SPARCs it gets painfully slow with the
+        current implementation of aout_32_find_nearest_line();
+        unfortunately, this means that static functions will not have their
+       filename printed in the call-graph function index; line-level
+       profiling should still work, but requires some patience
+
+       * cg_print.c (cg_print_index): sanitised printing of index when
+       using FSF-style output; in particular, output width is now controlled
+       via option --width and the function tries hard to keep columns
+       aligned even in the presence of (occasional) long names
+
+       * NOTES: a first shot at updating the documentation.
+
+Wed Feb  1 19:07:44 1995  David Mosberger-Tang  <davidm@piston.cs.arizona.edu>
+
+       * core.c (core_create_function_syms): fixed computation of min_vma
+       and max_vma.
+
+       * *.c: removed rcsid.
+
+Tue Jan 31 16:18:18 1995  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Lots of changes from David Mosberger-Tang:
+
+       Tue Oct 25 19:20:14 1994  David Mosberger-Tang  <davidm@piston.cs.arizona.edu>
+
+       * gprof.c (main): put parentheses around & within &&.
+
+       * basic_blocks.c (bb_read_rec): print warning message (once) when
+       ignoring basic-block execution counts.
+
+       * source.c (source_file_lookup_name): corrected second argument to
+       strcmp().
+
+       * hist.c (print_header): merged Fri Oct 21 18:58:02 1994 change by
+       Ken Raeburn <raeburn@cujo.cygnus.com> from binutils-2.5.1.
+
+       * gmon_io.c (gmon_out_read): the output stule STYLE_GMON_INFO is now
+       supported both for old and new (versioned) gmon.out files.  Old
+       files are identified as version 0.
+
+       * gmon.h (struct raw_arc): count field is now sizeof(long) bytes
+       long (instead of 4) because that is what OSF/1 v3.0 uses.
+
+       * core.c: minor fixes and debugging info changes.
+
+       Sun Sep 11 18:47:47 1994  David Mosberger-Tang  (davidm@piston.cs.arizona.edu)
+
+       * core.c (core_init): if .text cannot be found, try $CODE$ (the
+       name of the text-section under HP-UX).
+
+       * hist.c (hist_assign_samples): fixed off-by-one bug: highpc
+       points one past the last sampling bin, so hist_scale should be
+       computed as "hist_scale /= hist_num_bins", not "hist_scale /=
+       hist_num_bins - 1".
+
+       * gmon_io.c, hist.c, hist.h: renamed hist_num_samples to
+       hist_num_bins.
+
+       * configure.in: added alpha-*-*) for per-target config.
+
+       * alpha.c, alpha.h: created.
+
+       * gprof.c (default_excluded_list): <locore>, <hicore> added.
+
+       * core.c (core_create_function_syms, core_create_line_syms):
+       explicitly keep two sentinels "<locore>" and "<hicore>" that catch
+       all addresses outside the text-space.  Thus, sym_lookup(&symtab,
+       addr) continues to guarantee not to return 0 on any address.  It
+       also avoids incorrectly crediting the first/last symbol in the
+       text-space.
+
+       * core.c (core_create_line_syms): always create function symbols
+       first, then merge in line symbols; this is so that if parts of the
+       program were compiled without -g, function-level symbols are
+       available still.
+
+       * utils.c (print_name_only): support for print_path added.
+
+       * symtab.c (cmp_addr): also use is_func flag in comparison.
+       (symtab_finalize): return immediately when table empty; now
+       more careful about getting rid of the right duplicate symbol.
+
+       * sparc.c (find_call): many fixes---this function was rather
+       botched in binutils-2.4 already; it should work again.
+
+       * source.c (source_file_lookup_path): PATH is now strdup'ed (it is
+       not good to rely on get_src_info() to return distinct string
+       pointers).
+
+       * search_list.c (search_list_append): added cast for xmalloc().
+
+       * hist.c: added explicit initialization to some of the global
+       variables; fixed SItab (scales were off by a factor of 10).
+
+       * hist.h: include of bfd.h added.
+
+       * gprof.c, gprof.h (print_path): added.
+
+       * gprof.h (MAX): fixed.
+
+       * gmon_out.h: renamed gmon_time_hist_hdr to gmon_hist_hdr.
+
+       * gmon_io.c: added some casts to (long) so we can always print as %lx
+
+       * core.c (core_get_text_space): fixed to make it work.
+
+       * cg_print.c (cg_print_index): added support for print_path option.
+
+       * cg_dfn.h (cg_dfn): wrap prototype in PARAMS().
+
+       * call_graph.c, gmon_io.c, hist.c: avoid taking address of array
+       as some compilers complain (e.g., DEC's OSF/1 compiler)
+
+       * basic_blocks.c, gmon_io.c, hist.c, source.c, sym_ids.c,
+       symtab.c: calls to memset() had 2nd and 3rd args reversed.
+
+       Sat Sep 10 21:53:13 1994  David Mosberger-Tang  (davidm@piston.cs.arizona.edu)
+
+       * gprof.c: added "_mcount" to default_excluded_list.
+       (main): if output_style==0 and there is either a histogram or a
+       call-graph, always generate flat and call-graph, no matter what
+       line_granularity is set to.
+
+       * source.c (source_file_lookup_name): if searching for sf->name
+       fails, try again with filename obtained after stripping off any
+       partial path from sf->name.
+
+       * gprof.h (SRCDEBUG): added.
+
+       * search_list.c (search_list_append): directories were added in wrong
+       order.
+
+       * reimplemented selection mechanism from ground up; it is now possible
+       to accurately control what gets included/excluded in each of the
+       output styles;  a "symbol-specification" (spec) is the basic means
+       to select a set of symbols; a spec has the syntax:
+
+         spec == (FILENAME:(FUNCNAME|LINE_NUM) | NAME).
+         arc == spec/spec.
+
+       any of the terminal symbols can be empty, in which case they
+       match anything (wildcards).  NAME is interpreted as a FILENAME
+       if it contains a dot (e.g., foo.c), as LINE_NUM if it starts
+       with a digit, and as FUNCNAME otherwise.
+
+       For example, to get a call-graph display that ignores arcs
+       from foo() to bar(), you'd say "--no-graph=foo/bar"; to
+       show only arcs into bar() (no matter what the caller),
+       you'd say "--graph=/bar"; and to get a call-graph without
+       any arc info, you'd say "--graph=/";  similarly, to
+       get a flat profile without mcount, you'd say "--no-flat=mcount"
+       and to get a flat profile that shows includes all functions
+       you'd say "--flat=""" (i.e., an empty spec)
+
+       * hist.c (hist_print): top_time wasn't initialized to 0.0.
+
+       Fri Sep  9 01:10:21 1994  David Mosberger-Tang  (davidm@piston.cs.arizona.edu)
+
+       * gmon_out.h: all headers now declared in terms of characters
+         to avoid getting into trouble with different compilers introducing
+         different amount of padding; the code already accessed the fields
+         through bfd functions, so that didn't have to change.
+
+       * hist.c (hist_read_rec, hist_write_rec): added support for
+         collection pc histograms measuring quantities other than time;
+         the histogram header now includes a field that specifies the
+         dimension of the quantity measured by the histogram bins
+         (normally, this is "seconds", but other meaningful dimensions
+          include such things as "I-cache misses", "instruction issue stalls"
+          etc.); there is also a field to specify a one-character
+         abbreviation for the dimension; in the case of time, this would
+         be 's'; in most other cases it probably would be '1' (not a physical
+         dimension).
+
+       Thu Sep  8 16:05:08 1994  David Mosberger-Tang  (davidm@piston.cs.arizona.edu)
+
+       * gprof.c, gmon_io.[ch]: BSD_COMPATIBLE is gone and new_file_version
+         has become old_file_version; gmon_io.c now always supports old-style
+         gmon.out files; it first tries to read gmon.out as a new version
+         file, if that fails, it tries to read it in the old format;
+         although not very likely, it is possible for gprof to mistake an
+         old-style file as a new one (the first 4 bytes would have to
+         be "gmon"---including the trailing '\0'); in that case, it is
+         necessary to specify --old-file-version
+
+       * gprof.h: removed dependency on SYSV; the code now always uses
+         strrchr(), memset(), and memcpy() and does not include either
+         of string.h or strings.h; this should make gprof compile on
+         any (Unix) system without configuration (per suggestion of
+         raeburn@cygnus.com)
+
+       * gprof.c (usage): fixed location of --new-file-format option.
+
+       * cg_arcs.c (propagate_flags): fixed typo in declaration.
+
+       * flat_bl.m: removed formfeed at end of file; the form-feed
+         is now printed cg_print.c only when necessary.
+
+       * major rewrite of gprof---too many changes to mention all of
+         them.  new features:
+
+       + -l now requests profiling at the line level (as opposed
+         to function level); in this mode, gprof creates a "symbol"
+         (aka name-list entry) for each line of source code, instead
+          of one per function)
+
+       + support for a new gmon.out file format; the new format 
+         consists of a header with a magic and a version number,
+         followed by a sequence of profile data; profile data
+         can any of: (a) PC histogram, (b) call-graph arcs, or
+         (c) basic-block execution counts; the version number makes
+         it possible to extend gmon.out in a backwards compatible
+         fashion
+
+       + support for tcov style annotated output: if the gmon.out file
+         contains basic-block execution counts, the user can request
+         the generation of annotated source files, much like Sun's
+         tcov used to do
+
+       + long options
+
+       + new scheme to suppress symbols that aren't function names
+         (e.g., avoids mistaking a goto label as a function)
+
+       + reorganized source code to make it more managable; as a
+         side effect, gprof now compiles cleanly with "gcc -Wall"
+
+       Thu Sep  1 15:46:49 1994  David Mosberger-Tang  (davidm@piston.cs.arizona.edu)
+
+       * gprof.c (funcsymbol): bfd_find_nearest_line() is now used as a
+       final cross-check to determine whether a static symbol should be
+       considered as a function-name.
+
+       Fri Aug  5 19:32:36 1994  David Mosberger-Tang  (davidm@piston.cs.arizona.edu)
+
+       * gmon_io.c (gmon_out_read): recognize "-" as the filename for
+       stdin; this is useful if you wanna keep gmon.out files compressed;
+       this way you can "gzcat" the compressed file into gprof.
+
+       * gprof.c: flag_min_count now initialized with 1 instead of 0.
+
+       * basic_blocks.c (bb_annotate_source): added support for creating
+       .tcov files when option flag_annotate_make_files is TRUE.
+       (annotate_with_count): all counts less than the minimum count
+       specified by -m are now annotated with hash-marks.
+
+       * gprof.c (main): -A is now followed by a string of option chars.
+
+       * basic_blocks.c (annotate_with_count): replaced b->count with
+       cnt.
+
+       * source.c: flag_annotate_source replaced by source_lock_map.
+
+       * source.h: source_lock_map added.
+
+       * gprof.c (main): new command-line syntax: -S simply specifies
+       which source-files user is interested in; -A requests annotated
+       source files and -AA requests that all lines in a source file
+       are annotated.
+
+       Thu Aug  4 23:27:03 1994  David Mosberger-Tang  (davidm@piston.cs.arizona.edu)
+
+       * basic_blocks.c (PATH_MAX): if undefined, define as 1024.
+
+       * sparc.c, i386.c, tahoe.c, vax.c: added include of "time_hist.h"
+       so s_lowpc etc. get declared.
+
+       * arcs.h (doarcs): created.
+
+       * arcs.c: reordered static functions such that they get defined
+       before use.
+
+       * gprof.c (main): added options:
+          -A: request annotation of all source lines (with -S)
+          -m: minimum execution count (with default basic-block display)
+          -N: force new file format (only if BSD_COMPATIBLE is defined)
+          -S: annotate source file
+          -t: set table length (with -S)
+
+       * Makefile (OBJS): added basic_blocks.o call_graph.o gmon_io.o
+       source.o time_hist.o
+
+       Fri Jul  1 15:23:50 1994  David Mosberger-Tang  (davidm@piston.cs.arizona.edu)
+
+       * gprof.c (asgnsamples): computation of "pcl" and "pch" depended
+       on the fact being able to store a long in a double without loss of
+       precision; this does not hold on machines with 64 bit longs and 64
+       bit doubles.
+
+Fri Oct 21 18:58:02 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * printgprof.c (flatprofheader): Always set totime to 1.0 if not
+       greater than 0.0.  Suggested by Harold Assink
+       <carlo@sg.tn.tudelft.nl>.
+
+Fri Sep 23 15:06:45 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * printgprof.c (printprof): Use free, not cfree.
+       (printgprof, printindex): Ditto.
+
+Thu Sep  1 10:40:45 1994  Jeff Law  (law@snake.cs.utah.edu)
+
+       * gprof.h (kfromlist, ktolist, flist, Flist, elist, Elist): Make
+       decls extern to keep native HP compiler quiet.
+
+Tue Aug 30 11:12:13 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * gprof.c (funcsymbol): Ignore ___gnu_compiled as well as
+       __gnu_compiled, for the benefit of systems which add a leading
+       underscore.
+
+Wed Aug 24 12:49:13 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * configure.in: Change i386-*-* to i[345]86-*-*.
+
+Sun Jul 10 00:35:31 1994  Ian Dall  (dall@hfrd.dsto.gov.au)
+
+       * ns532.c, ns532.h: New Files. ns532 support.
+
+       * config/mt-ns532: New File. ns532 support.
+
+       * gprof.c: user register int i instead of defaulting the int.
+       Allows compilation with -Dregister= for debugging.
+
+       * configure.in: Add ns532 support.
+
+Thu Jun 23 11:22:41 1994  Jeff Law  (law@snake.cs.utah.edu)
+
+       * Makefile.in (gprof): Depend on $(LIBS).
+
+Fri May 27 12:24:57 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       From binutils-2.4 release:
+
+       Wed May 11 22:32:00 1994  DJ Delorie (dj@ctron.com)
+
+       * configure.bat: [new] build makefile from makefile.in (dos)
+       * hertz.c: allow static HERTZ (msdos needs it)
+       * gprof.c: allow target to select "r" or "rb" for fopen
+       * gprof.c: ignore __gnu_compiled symbols
+       * i386.h: dfine FOPEN_RB to "rb" for dos.
+
+Tue May 17 15:30:22 1994  E. Michael Smith (ems@cygnus.com)
+
+       * Makefile.in (.m.c:):  Added .SUFFIXES : .m 
+       so flat_bl.c would make from flat_bl.m file.
+
+Thu May  5 19:23:24 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * Makefile.in (install-info): Check for gprof.info in build dir,
+       fall back to srcdir.  Depend on it.
+
+       * gprof.h (TRUE, FALSE): Always use undef before defining them.
+
+Mon Apr  4 23:47:30 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * Makefile.in (MY_MACHINE): Renamed from MACHINE to avoid losing
+       makes (osf1) in which the value of MACHINE can not be changed.
+       * config/*.mt: Changed appropriately.
+
+Wed Mar 30 16:12:40 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * gprof.c (getsymtab): Change nosyms to long.  Rename
+       get_symtab_upper_bound to bfd_get_symtab_upper_bound.  Check for
+       errors from bfd_get_symtab_upper_bound and
+       bfd_canonicalize_symtab.
+
+Tue Mar 22 10:50:52 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * gprof.c (funcsymbol): Use bfd_get_symbol_info instead of
+       bfd_decode_symclass.
+
+Sun Mar 20 15:40:21 1994  Jeffrey A. Law  (law@snake.cs.utah.edu)
+
+       * Makefile.in: Avoid bug in hpux sed.
+
+Wed Dec 15 20:16:40 1993  david d `zoo' zuhn  (zoo@andros.cygnus.com)
+
+       * gprof.texi (Invoking): add text about -v flag
+
+       * gprof.1: add text about -v flag
+
+Wed Dec  8 16:55:06 1993  david d `zoo' zuhn  (zoo@andros.cygnus.com)
+
+       * gprof.c (VERSION): defined a version macro, print the value 
+       when the -v option is used
+
+Tue Jul  6 10:11:56 1993  Steve Chamberlain  (sac@phydeaux.cygnus.com)
+
+       * Makefile.in: Install correctly.
+
+Thu Jun 24 14:43:22 1993  David J. Mackenzie  (djm@thepub.cygnus.com)
+
+       * gprof.c (main): Get whoami from argv, instead of hardcoding.
+       Use it in usage message.  Split usage message to fit in 80 cols.
+
+Sun Jun 20 20:58:02 1993  Ken Raeburn  (raeburn@poseidon.cygnus.com)
+
+       * Makefile.in: Undo 15 June change.
+
+Wed Jun 16 12:54:53 1993  Steve Chamberlain  (sac@phydeaux.cygnus.com)
+
+       * gmon.h, gprof.h: structs of chars used to hold external
+       representations.
+       * gprof.c (getpfile, openpfile, readsamples): Swap data in using
+       new structures.
+
+Tue Jun 15 23:09:17 1993  Ken Raeburn  (raeburn@cambridge.cygnus.com)
+
+       * Makefile.in (.c.o): Look in ../include, not ../bfd, for bfd.h.
+
+Mon Jun 14 16:22:59 1993  david d `zoo' zuhn  (zoo at rtl.cygnus.com)
+
+       * Makefile.in: remove parentdir support
+
+Mon Jun  7 12:56:17 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * Makefile.in (INCLUDES):  Add -I../bfd for sysdep.h and bfd.h.
+       * configure.in:  No longer need to configure to get sysdep.h.
+
+Tue May 18 21:44:11 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in (install): should not depend on install-info
+
+Mon Apr 26 12:37:46 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * gprof.h: Include ansidecl.h before sysdep.h.  Undefine hz.
+
+Tue Apr 13 16:14:03 1993  Per Bothner  (bothner@cygnus.com)
+
+       * M Makefile.in:  Add -g to CFLAGS.
+       Ads LDFLAGS and use in place of CFLAGS where appropriate.
+       * configure.in:  Make a sysdep.hlink in the same way other
+       bfd-based directories do.
+       * gprof.h (UNIT):  Replace non-standard 'u_short' by 'unsigned
+       short'.
+       * gprof.h:  #include sysdep.h instead of a bunch of stuff.
+       * gprof.c (main):  Fix typo gproff->gprof.
+
+Thu Mar 25 19:00:37 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * gprof.texi: add INFO-DIR-ENTRY
+
+Tue Mar 23 00:03:11 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: add installcheck target
+
+Sat Feb 27 18:17:10 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * gprof.c (funcsymbol):  Invert test for aflag.
+
+Thu Feb 25 16:01:50 1993  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * printgprof (xmalloc, xrealloc):  Cast results of malloc
+       and realloc to PTR.
+
+Wed Feb  3 13:55:33 1993  Jeffrey Osier  (jeffrey@fowanton.cygnus.com)
+
+       * Makefile.in: created info, install-info, dvi
+
+Wed Jan  6 00:58:09 1993  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: fix install rule for $(PROG)
+
+Fri Oct  9 11:25:41 1992  Mark Eichin  (eichin@cygnus.com)
+
+       * gprof.1: updated SYNOPSIS to match actual behavior.
+
+Mon Oct  5 17:50:16 1992  Per Bothner  (bothner@cygnus.com)
+
+       * gen-c-prog.awk:  New awk script, lightly changed from
+       previously deleted make-c-prog.awk.  Converts a text file
+       to a c function that prints that text.
+       * flat_bl.m, fsf_callg_bl.m, bsd_callg_bl.m:  New files.
+       Inputs to gen-c-prog.awk, containing text describing
+       gprof output.
+       * blurbs.c:  Removed.  Use *_bl.c instead.
+       * Makefile.in: Use gen-cprog.awk to generate *_bl.c files
+       from *_bl.m files.  Also, improve *clean rules.
+       * printgprof.c (printgprof):  Usw new function names from *_bl.c.
+       
+
+Sun Aug 30 19:54:53 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       * gprof.h, gprof.c, printfgprof.c:  Add support for two
+       output styles:  The default is similar to the old FSF gprof,
+       while -T sets the variable bsd_style_output, which causes
+       output matching Berkeley's gprof.  The biggest differences
+       are that with the FSF style output, the flat profile comes
+       before the call graph; numbers come before explanations;
+       and there is less gratuitous white space.
+       * gprof.h, gprof.c, printfgprof.c:  New discard_underscores
+       variable causes discarding of initial underscores when
+       printing symbol names.  It is set unless there is a "main"
+       symbol (without an underscore).
+       * printfgprof.c:  New function printnameonly(), called
+       by printname().  It handles stripping of initial '_',
+       as well as C++ name-demangling.
+       * gprof.callg, gprof.flat, make-c-prog.awk:  Removed.
+       It is just as convenient to edit blurbs.c directly.
+       * Makefile.in:  Removed rule for making blurbs.c.
+       * blurbs.c:  This is now a true source file (as opposed
+       to being generated from gprof.callg and gprof.flat).
+       Change style to use one long string literal, instead of
+       one literal per output line.  Add FSF-style blurb for call graph.
+
+Wed Aug 19 14:36:39 1992  Ian Lance Taylor  (ian@cygnus.com)
+
+       * Makefile.in: always create installation directories.
+
+Wed Aug 12 15:14:14 1992  Mark Eichin  (eichin@cygnus.com)
+
+       * Makefile.in: change ${MACHINE} to $(MACHINE).
+
+Sun Jul 19 17:34:01 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in:  removed installation of the now useless
+       call.{flag,callg} files.  
+
+       * gprof.1: now uses the standard man macros instead of the new BSD
+       mandoc macros. 
+
+Sun Jul 12 19:06:00 1992  John Gilmore  (gnu at cygnus.com)
+
+       * configure.in:  Remove host section, expand target section.
+       * config/mt-{tahoe,vax}:  Add, to match existing support files.
+       * config/tmake-*:  Remove leftover crud.
+
+       * blurbs.c:  New file, created from gprof.flat and gprof.callg by
+       * make-c-prog.awk:  which processes text files into C programs.
+       * printgprof.c (flatprofheader, gprofheader):  Call new functions
+       to print blurbs.
+       (printblurb):  Remove.
+       * Makefile.in:  Infrastructure to build blurbs.
+       * pathnames.h:  has been removed.  Gprof now has no filename
+       dependencies in it.
+       * gprof.c:  Lint.
+
+Sat Jul 11 18:07:21 1992  david d `zoo' zuhn  (zoo at cirdan.cygnus.com)
+
+       * Makefile.in: define man1dir and install the man page
+
+Fri Jul 10 21:14:08 1992  david d `zoo' zuhn (zoo@cygnus.com)
+
+       * Makefile.in: added dummy info and install-info targets
+
+Thu Jun  4 11:34:02 1992  Mark Eichin  (eichin at cygnus.com)
+
+       * lookup.c: fixed fencepost in nllookup and added dbg_nllookup for
+       help in debugging the problem (with -DDEBUG)
+       * gprof.c: symbol values are now real values, don't add the vma
+       anymore. (done for solaris; should verify this on other platforms)
+       * ChangeLog: created.
diff --git a/gprof/Makefile.am b/gprof/Makefile.am
new file mode 100644 (file)
index 0000000..7ae1492
--- /dev/null
@@ -0,0 +1,74 @@
+## Process this file with automake to generate Makefile.in
+
+AUTOMAKE_OPTIONS = cygnus
+
+SUFFIXES = .m
+
+SUBDIRS = po
+
+INCLUDES = -D_GNU_SOURCE -DDEBUG -I../bfd -I$(srcdir)/../include -I$(srcdir)/../bfd -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
+
+bin_PROGRAMS = gprof
+
+## Convenience var listing pure sources.
+sources = basic_blocks.c call_graph.c cg_arcs.c cg_dfn.c \
+       cg_print.c corefile.c gmon_io.c gprof.c hertz.c hist.c source.c \
+       search_list.c symtab.c sym_ids.c utils.c \
+       i386.c alpha.c vax.c tahoe.c sparc.c
+gprof_SOURCES = $(sources) flat_bl.c bsd_callg_bl.c fsf_callg_bl.c
+gprof_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a $(INTLDEPS)
+gprof_LDADD = ../bfd/libbfd.la ../libiberty/libiberty.a $(INTLLIBS)
+
+noinst_HEADERS = \
+       basic_blocks.h call_graph.h cg_arcs.h cg_dfn.h cg_print.h \
+       corefile.h gmon.h gmon_io.h gmon_out.h gprof.h hertz.h hist.h \
+       search_list.h source.h sym_ids.h symtab.h utils.h
+
+EXTRA_DIST = flat_bl.c bsd_callg_bl.c fsf_callg_bl.c bbconv.pl
+
+BUILT_SOURCES = flat_bl.c bsd_callg_bl.c fsf_callg_bl.c
+
+diststuff: $(BUILT_SOURCES) info
+
+.m.c:
+       awk -f $(srcdir)/gen-c-prog.awk > ./$*.c \
+           FUNCTION=`(echo $*|sed -e 's,.*/,,g' -e 's/_bl//')`_blurb \
+           FILE=$*.m $(srcdir)/$*.m
+
+POTFILES = $(sources) $(noinst_HEADERS)
+po/POTFILES.in: @MAINT@ Makefile
+       for file in $(POTFILES); do echo $$file; done | sort > tmp \
+         && mv tmp $(srcdir)/po/POTFILES.in
+
+info_TEXINFOS = gprof.texi
+man_MANS = gprof.1
+
+# Dependencies.
+$(OBJECTS): ../bfd/bfd.h call_graph.h cg_arcs.h cg_print.h \
+       corefile.h gmon_io.h gmon_out.h gprof.h hertz.h hist.h \
+       search_list.h source.h sym_ids.h symtab.h utils.h \
+       $(srcdir)/../include/libiberty.h $(srcdir)/../bfd/sysdep.h \
+       gconfig.h ../bfd/config.h
+basic_blocks.o: basic_blocks.c
+bsd_call_bl.o: bsd_call_bl.c
+call_graph.o: call_graph.c
+cg_arcs.o: cg_arcs.c
+cg_dfn.o: cg_dfn.c
+cg_print.o: cg_print.c
+corefile.o: corefile.c
+flat_bl.o: flat_bl.c
+fsf_callg_bl.o: fsf_callg_bl.c
+gmon_io.o: gmon_io.c
+gprof.o: gprof.c
+hertz.o: hertz.c
+hist.o: hist.c
+search_list.o: search_list.c
+source.o: source.c
+symtab.o: symtab.c
+sym_ids.o: sym_ids.c
+utils.o: utils.c
+i386.o: i386.c
+alpha.o: alpha.c
+vax.o: vax.c
+tahoe.o: tahoe.c
+sparc.o: sparc.c
diff --git a/gprof/Makefile.in b/gprof/Makefile.in
new file mode 100644 (file)
index 0000000..4aadd88
--- /dev/null
@@ -0,0 +1,726 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AS = @AS@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+DATADIRNAME = @DATADIRNAME@
+DLLTOOL = @DLLTOOL@
+EXEEXT = @EXEEXT@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GT_NO = @GT_NO@
+GT_YES = @GT_YES@
+INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
+INSTOBJEXT = @INSTOBJEXT@
+INTLDEPS = @INTLDEPS@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+NM = @NM@
+PACKAGE = @PACKAGE@
+POFILES = @POFILES@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+USE_SYMBOL_UNDERSCORE = @USE_SYMBOL_UNDERSCORE@
+VERSION = @VERSION@
+l = @l@
+
+AUTOMAKE_OPTIONS = cygnus
+
+SUFFIXES = .m
+
+SUBDIRS = po
+
+INCLUDES = -D_GNU_SOURCE -DDEBUG -I../bfd -I$(srcdir)/../include -I$(srcdir)/../bfd -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\""
+
+bin_PROGRAMS = gprof
+
+sources = basic_blocks.c call_graph.c cg_arcs.c cg_dfn.c \
+       cg_print.c corefile.c gmon_io.c gprof.c hertz.c hist.c source.c \
+       search_list.c symtab.c sym_ids.c utils.c \
+       i386.c alpha.c vax.c tahoe.c sparc.c
+
+gprof_SOURCES = $(sources) flat_bl.c bsd_callg_bl.c fsf_callg_bl.c
+gprof_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a $(INTLDEPS)
+gprof_LDADD = ../bfd/libbfd.la ../libiberty/libiberty.a $(INTLLIBS)
+
+noinst_HEADERS = \
+       basic_blocks.h call_graph.h cg_arcs.h cg_dfn.h cg_print.h \
+       corefile.h gmon.h gmon_io.h gmon_out.h gprof.h hertz.h hist.h \
+       search_list.h source.h sym_ids.h symtab.h utils.h
+
+
+EXTRA_DIST = flat_bl.c bsd_callg_bl.c fsf_callg_bl.c bbconv.pl
+
+BUILT_SOURCES = flat_bl.c bsd_callg_bl.c fsf_callg_bl.c
+
+POTFILES = $(sources) $(noinst_HEADERS)
+
+info_TEXINFOS = gprof.texi
+man_MANS = gprof.1
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = gconfig.h
+CONFIG_CLEAN_FILES = 
+bin_PROGRAMS =  gprof$(EXEEXT)
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I.
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+gprof_OBJECTS =  basic_blocks.o call_graph.o cg_arcs.o cg_dfn.o \
+cg_print.o corefile.o gmon_io.o gprof.o hertz.o hist.o source.o \
+search_list.o symtab.o sym_ids.o utils.o i386.o alpha.o vax.o tahoe.o \
+sparc.o flat_bl.o bsd_callg_bl.o fsf_callg_bl.o
+gprof_LDFLAGS = 
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+TEXI2DVI = `if test -f $(top_srcdir)/../texinfo/util/texi2dvi; then echo $(top_srcdir)/../texinfo/util/texi2dvi; else echo texi2dvi; fi`
+TEXINFO_TEX = $(top_srcdir)/../texinfo/texinfo.tex
+INFO_DEPS = gprof.info
+DVIS = gprof.dvi
+TEXINFOS = gprof.texi
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
+HEADERS =  $(noinst_HEADERS)
+
+DIST_COMMON =  ./stamp-h.in ChangeLog Makefile.am Makefile.in TODO \
+aclocal.m4 configure configure.in gconfig.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(gprof_SOURCES)
+OBJECTS = $(gprof_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .dvi .info .lo .m .o .ps .s .texi .texinfo .txi
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in 
+       cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+       cd $(srcdir) && $(AUTOCONF)
+
+gconfig.h: stamp-h
+       @if test ! -f $@; then \
+               rm -f stamp-h; \
+               $(MAKE) stamp-h; \
+       else :; fi
+stamp-h: $(srcdir)/gconfig.in $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES= CONFIG_HEADERS=gconfig.h:gconfig.in \
+            $(SHELL) ./config.status
+       @echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/gconfig.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in
+       @if test ! -f $@; then \
+               rm -f $(srcdir)/stamp-h.in; \
+               $(MAKE) $(srcdir)/stamp-h.in; \
+       else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOHEADER)
+       @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+       -rm -f gconfig.h
+
+maintainer-clean-hdr:
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+       -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(bindir)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+           $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       list='$(bin_PROGRAMS)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+       done
+
+.c.o:
+       $(COMPILE) -c $<
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+       $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+gprof$(EXEEXT): $(gprof_OBJECTS) $(gprof_DEPENDENCIES)
+       @rm -f gprof$(EXEEXT)
+       $(LINK) $(gprof_LDFLAGS) $(gprof_OBJECTS) $(gprof_LDADD) $(LIBS)
+
+gprof.info: gprof.texi
+gprof.dvi: gprof.texi
+
+
+DVIPS = dvips
+
+.texi.info:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.texi.dvi:
+       TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.texi:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo.info:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.texinfo.dvi:
+       TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.txi.info:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+
+.txi.dvi:
+       TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.txi:
+       @rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       $(MAKEINFO) -I $(srcdir) $<
+.dvi.ps:
+       $(DVIPS) $< -o $@
+
+install-info-am: $(INFO_DEPS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(infodir)
+       @list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \
+           if test -f $$d/$$ifile; then \
+             echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \
+             $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \
+           else : ; fi; \
+         done; \
+       done
+       @$(POST_INSTALL)
+       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+         list='$(INFO_DEPS)'; \
+         for file in $$list; do \
+           echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\
+           install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\
+         done; \
+       else : ; fi
+
+uninstall-info:
+       $(PRE_UNINSTALL)
+       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+         ii=yes; \
+       else ii=; fi; \
+       list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         test -z "$ii" \
+           || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file; \
+       done
+       @$(NORMAL_UNINSTALL)
+       list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \
+       done
+
+dist-info: $(INFO_DEPS)
+       list='$(INFO_DEPS)'; \
+       for base in $$list; do \
+         if test -f $$base; then d=.; else d=$(srcdir); fi; \
+         for file in `cd $$d && eval echo $$base*`; do \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file; \
+         done; \
+       done
+
+mostlyclean-aminfo:
+       -rm -f gprof.aux gprof.cp gprof.cps gprof.dvi gprof.fn gprof.fns \
+         gprof.ky gprof.kys gprof.ps gprof.log gprof.pg gprof.toc \
+         gprof.tp gprof.tps gprof.vr gprof.vrs gprof.op gprof.tr \
+         gprof.cv gprof.cn
+
+clean-aminfo:
+
+distclean-aminfo:
+
+maintainer-clean-aminfo:
+       for i in $(INFO_DEPS); do \
+         rm -f $$i; \
+         if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \
+           rm -f $$i-[0-9]*; \
+         fi; \
+       done
+clean-info: mostlyclean-aminfo
+
+install-man1:
+       $(mkinstalldirs) $(DESTDIR)$(man1dir)
+       @list='$(man1_MANS)'; \
+       l2='$(man_MANS)'; for i in $$l2; do \
+         case "$$i" in \
+           *.1*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+         else file=$$i; fi; \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+         $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+       done
+
+uninstall-man1:
+       @list='$(man1_MANS)'; \
+       l2='$(man_MANS)'; for i in $$l2; do \
+         case "$$i" in \
+           *.1*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+         rm -f $(DESTDIR)$(man1dir)/$$inst; \
+       done
+install-man: $(MANS)
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-man1
+uninstall-man:
+       @$(NORMAL_UNINSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive install-info-recursive \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+         rev="$$subdir $$rev"; \
+         test "$$subdir" = "." && dot_seen=yes; \
+       done; \
+       test "$$dot_seen" = "no" && rev=". $$rev"; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) gconfig.in $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+   if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+   fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)gconfig.in$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags gconfig.in $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       -rm -rf $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
+       mkdir $(distdir)/=build
+       mkdir $(distdir)/=inst
+       dc_install_base=`cd $(distdir)/=inst && pwd`; \
+       cd $(distdir)/=build \
+         && ../configure --srcdir=.. --prefix=$$dc_install_base \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) dist
+       -rm -rf $(distdir)
+       @banner="$(distdir).tar.gz is ready for distribution"; \
+       dashes=`echo "$$banner" | sed s/./=/g`; \
+       echo "$$dashes"; \
+       echo "$$banner"; \
+       echo "$$dashes"
+dist: distdir
+       -chmod -R a+r $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+       -rm -rf $(distdir)
+dist-all: distdir
+       -chmod -R a+r $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+       -rm -rf $(distdir)
+distdir: $(DISTFILES)
+       -rm -rf $(distdir)
+       mkdir $(distdir)
+       -chmod 777 $(distdir)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           cp -pr $$/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+       for subdir in $(SUBDIRS); do \
+         if test "$$subdir" = .; then :; else \
+           test -d $(distdir)/$$subdir \
+           || mkdir $(distdir)/$$subdir \
+           || exit 1; \
+           chmod 777 $(distdir)/$$subdir; \
+           (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+             || exit 1; \
+         fi; \
+       done
+       $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info
+info-am: $(INFO_DEPS)
+info: info-recursive
+dvi-am: $(DVIS)
+dvi: dvi-recursive
+check-am:
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+install-info-am: 
+install-info: install-info-recursive
+all-recursive-am: gconfig.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-recursive
+
+install-data-am: install-man
+install-data: install-data-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+uninstall: uninstall-recursive
+all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS) gconfig.h
+all-redirect: all-recursive-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+       $(mkinstalldirs)  $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean-am:  mostlyclean-hdr mostlyclean-binPROGRAMS \
+               mostlyclean-compile mostlyclean-libtool \
+               mostlyclean-aminfo mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am:  clean-hdr clean-binPROGRAMS clean-compile clean-libtool \
+               clean-aminfo clean-tags clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am:  distclean-hdr distclean-binPROGRAMS distclean-compile \
+               distclean-libtool distclean-aminfo distclean-tags \
+               distclean-generic clean-am
+       -rm -f libtool
+
+distclean: distclean-recursive
+       -rm -f config.status
+
+maintainer-clean-am:  maintainer-clean-hdr maintainer-clean-binPROGRAMS \
+               maintainer-clean-compile maintainer-clean-libtool \
+               maintainer-clean-aminfo maintainer-clean-tags \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool install-info-am uninstall-info \
+mostlyclean-aminfo distclean-aminfo clean-aminfo \
+maintainer-clean-aminfo install-man1 uninstall-man1 install-man \
+uninstall-man install-data-recursive uninstall-data-recursive \
+install-exec-recursive uninstall-exec-recursive installdirs-recursive \
+uninstalldirs-recursive all-recursive check-recursive \
+installcheck-recursive info-recursive dvi-recursive \
+mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-info-am \
+install-info all-recursive-am install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs-am installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+diststuff: $(BUILT_SOURCES) info
+
+.m.c:
+       awk -f $(srcdir)/gen-c-prog.awk > ./$*.c \
+           FUNCTION=`(echo $*|sed -e 's,.*/,,g' -e 's/_bl//')`_blurb \
+           FILE=$*.m $(srcdir)/$*.m
+po/POTFILES.in: @MAINT@ Makefile
+       for file in $(POTFILES); do echo $$file; done | sort > tmp \
+         && mv tmp $(srcdir)/po/POTFILES.in
+
+# Dependencies.
+$(OBJECTS): ../bfd/bfd.h call_graph.h cg_arcs.h cg_print.h \
+       corefile.h gmon_io.h gmon_out.h gprof.h hertz.h hist.h \
+       search_list.h source.h sym_ids.h symtab.h utils.h \
+       $(srcdir)/../include/libiberty.h $(srcdir)/../bfd/sysdep.h \
+       gconfig.h ../bfd/config.h
+basic_blocks.o: basic_blocks.c
+bsd_call_bl.o: bsd_call_bl.c
+call_graph.o: call_graph.c
+cg_arcs.o: cg_arcs.c
+cg_dfn.o: cg_dfn.c
+cg_print.o: cg_print.c
+corefile.o: corefile.c
+flat_bl.o: flat_bl.c
+fsf_callg_bl.o: fsf_callg_bl.c
+gmon_io.o: gmon_io.c
+gprof.o: gprof.c
+hertz.o: hertz.c
+hist.o: hist.c
+search_list.o: search_list.c
+source.o: source.c
+symtab.o: symtab.c
+sym_ids.o: sym_ids.c
+utils.o: utils.c
+i386.o: i386.c
+alpha.o: alpha.c
+vax.o: vax.c
+tahoe.o: tahoe.c
+sparc.o: sparc.c
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gprof/NOTES b/gprof/NOTES
new file mode 100644 (file)
index 0000000..511af30
--- /dev/null
@@ -0,0 +1,438 @@
+Sun Feb  5 16:09:16 1995
+
+This file documents the changes and new features available with this
+version of GNU gprof.
+
+* New Features
+
+ o Long options
+
+ o Supports generalized file format, without breaking backward compatibility:
+   new file format supports basic-block execution counts and non-realtime
+   histograms (see below)
+
+ o Supports profiling at the line level: flat profiles, call-graph profiles,
+   and execution-counts can all be displayed at a level that identifies
+   individual lines rather than just functions
+
+ o Test-coverage support (similar to Sun tcov program): source files
+   can be annotated with the number of times a function was invoked
+   or with the number of times each basic-block in a function was
+   executed
+
+ o Generalized histograms: not just execution-time, but arbitrary
+   histograms are support (for example, performance counter based
+   profiles)
+
+ o Powerful mechanism to select data to be included/excluded from
+   analysis and/or output
+
+ o Support for DEC OSF/1 v3.0
+
+ o Full cross-platform profiling support: gprof uses BFD to support
+   arbitrary, non-native object file formats and non-native byte-orders
+   (this feature has not been tested yet)
+
+ o In the call-graph function index, static function names are now
+   printed together with the filename in which the function was defined
+   (required bfd_find_nearest_line() support and symbolic debugging
+    information to be present in the executable file)
+
+ o Major overhaul of source code (compiles cleanly with -Wall, etc.)
+
+* Supported Platforms
+
+The current version is known to work on:
+
+ o DEC OSF/1 v3.0
+       All features supported.
+
+ o SunOS 4.1.x
+       All features supported.
+
+ o Solaris 2.3
+       Line-level profiling unsupported because bfd_find_nearest_line()
+       is not fully implemented for Elf binaries.
+
+ o HP-UX 9.01
+       Line-level profiling unsupported because bfd_find_nearest_line()
+       is not fully implemented for SOM binaries.
+
+* Detailed Description
+
+** User Interface Changes
+
+The command-line interface is backwards compatible with earlier
+versions of GNU gprof and Berkeley gprof.  The only exception is
+the option to delete arcs from the call graph.  The old syntax
+was:
+
+       -k fromname toname
+
+while the new syntax is:
+
+       -k fromname/toname
+
+This change was necessary to be compatible with long-option parsing.
+Also, "fromname" and "toname" can now be arbitrary symspecs rather
+than just function names (see below for an explanation of symspecs).
+For example, option "-k gprof.c/" suppresses all arcs due to calls out
+of file "gprof.c".
+
+*** Sym Specs
+
+It is often necessary to apply gprof only to specific parts of a
+program.  GNU gprof has a simple but powerful mechanism to achieve
+this.  So called {\em symspecs\/} provide the foundation for this
+mechanism.  A symspec selects the parts of a profiled program to which
+an operation should be applied to.  The syntax of a symspec is
+simple:
+
+         filename_containing_a_dot
+       | funcname_not_containing_a_dot
+       | linenumber
+       | ( [ any_filename ] `:' ( any_funcname | linenumber ) )
+
+Here are some examples:
+
+       main.c                  Selects everything in file "main.c"---the
+                               dot in the string tells gprof to interpret
+                               the string as a filename, rather than as
+                               a function name.  To select a file whose
+                               name does contain a dot, a trailing colon
+                               should be specified.  For example, "odd:" is
+                               interpreted as the file named "odd".
+
+       main                    Selects all functions named "main".  Notice
+                               that there may be multiple instances of the
+                               same function name because some of the
+                               definitions may be local (i.e., static).
+                               Unless a function name is unique in a program,
+                               you must use the colon notation explained
+                               below to specify a function from a specific
+                               source file.  Sometimes, functionnames contain
+                               dots.  In such cases, it is necessar to
+                               add a leading colon to the name.  For example,
+                               ":.mul" selects function ".mul".
+                               
+       main.c:main             Selects function "main" in file "main.c".
+
+       main.c:134              Selects line 134 in file "main.c".
+
+IMPLEMENTATION NOTE: The source code uses the type sym_id for symspecs.
+At some point, this probably ought to be changed to "sym_spec" to make
+reading the code easier.
+
+*** Long options
+
+GNU gprof now supports long options.  The following is a list of all
+supported options.  Options that are listed without description
+operate in the same manner as the corresponding option in older
+versions of gprof.
+
+Short Form:    Long Form:
+-----------    ----------
+-l             --line
+                       Request profiling at the line-level rather
+                       than just at the function level.  Source
+                       lines are identified by symbols of the form:
+
+                               func (file:line)
+
+                       where "func" is the function name, "file" is the
+                       file name and "line" is the line-number that
+                       corresponds to the line.
+
+                       To work properly, the binary must contain symbolic
+                       debugging information.  This means that the source
+                       have to be translated with option "-g" specified.
+                       Functions for which there is no symbolic debugging
+                       information available are treated as if "--line"
+                       had not been specified.  However, the line number
+                       printed with such symbols is usually incorrect
+                       and should be ignored.
+
+-a             --no-static
+-A[symspec]    --annotated-source[=symspec]
+                       Request output in the form of annotated source
+                       files.  If "symspec" is specified, print output only
+                       for symbols selected by "symspec".  If the option
+                       is specified multiple times, annotated output is
+                       generated for the union of all symspecs.
+
+                       Examples:
+
+                         -A            Prints annotated source for all
+                                       source files.
+                         -Agprof.c     Prints annotated source for file
+                                       gprof.c.
+                         -Afoobar      Prints annotated source for files
+                                       containing a function named "foobar".
+                                       The entire file will be printed, but
+                                       only the function itself will be
+                                       annotated with profile data.
+
+-J[symspec]    --no-annotated-source[=symspec]
+                       Suppress annotated source output.  If specified
+                       without argument, annotated output is suppressed
+                       completely.  With an argument, annotated output
+                       is suppressed only for the symbols selected by
+                       "symspec".  If the option is specified multiple
+                       times, annotated output is suppressed for the
+                       union of all symspecs.  This option has lower
+                       precedence than --annotated-source
+
+-p[symspec]    --flat-profile[=symspec]
+                       Request output in the form of a flat profile
+                       (unless any other output-style option is specified,
+                        this option is turned on by default).  If
+                       "symspec" is specified, include only symbols
+                       selected by "symspec" in flat profile.  If the
+                       option is specified multiple times, the flat
+                       profile includes symbols selected by the union
+                       of all symspecs.
+                       
+-P[symspec]    --no-flat-profile[=symspec]
+                       Suppress output in the flat profile.  If given
+                       without an argument, the flat profile is suppressed
+                       completely.  If "symspec" is specified, suppress
+                       the selected symbols in the flat profile.  If the
+                       option is specified multiple times, the union of
+                       the selected symbols is suppressed.  This option
+                       has lower precedence than --flat-profile.
+
+-q[symspec]    --graph[=symspec]
+                       Request output in the form of a call-graph
+                       (unless any other output-style option is specified,
+                        this option is turned on by default).  If "symspec"
+                       is specified, include only symbols selected by
+                       "symspec" in the call-graph.  If the option is
+                       specified multiple times, the call-graph includes
+                       symbols selected by the union of all symspecs.
+
+-Q[symspec]    --no-graph[=symspec]
+                       Suppress output in the call-graph.  If given without
+                       an argument, the call-graph is suppressed completely.
+                       With a "symspec", suppress the selected symbols
+                       from the call-graph.  If the option is specified
+                       multiple times, the union of the selected symbols
+                       is suppressed.  This option has lower precedence
+                       than --graph.
+
+-C[symspec]    --exec-counts[=symspec]
+                       Request output in the form of execution counts.
+                       If "symspec" is present, include only symbols
+                       selected by "symspec" in the execution count
+                       listing.  If the option is specified multiple
+                       times, the execution count listing includes
+                       symbols selected by the union of all symspecs.
+
+-Z[symspec]    --no-exec-counts[=symspec]
+                       Suppress output in the execution count listing.
+                       If given without an argument, the listing is
+                       suppressed completely.  With a "symspec", suppress
+                       the selected symbols from the call-graph.  If the
+                       option is specified multiple times, the union of
+                       the selected symbols is suppressed.  This option
+                       has lower precedence than --exec-counts.
+
+-i             --file-info
+                       Print information about the profile files that
+                       are read.  The information consists of the
+                       number and types of records present in the
+                       profile file.  Currently, a profile file can
+                       contain any number and any combination of histogram,
+                       call-graph, or basic-block count records.
+
+-s             --sum
+
+-x             --all-lines
+                       This option affects annotated source output only.
+                       By default, only the lines at the beginning of
+                       a basic-block are annotated.  If this option is
+                       specified, every line in a basic-block is annotated
+                       by repeating the annotation for the first line.
+                       This option is identical to tcov's "-a".
+
+-I dirs                --directory-path=dirs
+                       This option affects annotated source output only.
+                       Specifies the list of directories to be searched
+                       for source files.  The argument "dirs" is a colon
+                       separated list of directories.  By default, gprof
+                       searches for source files relative to the current
+                       working directory only.
+
+-z             --display-unused-functions
+
+-m num         --min-count=num
+                       This option affects annotated source and execution
+                       count output only.  Symbols that are executed
+                       less than "num" times are suppressed.  For annotated
+                       source output, suppressed symbols are marked
+                       by five hash-marks (#####).  In an execution count
+                       output, suppressed symbols do not appear at all.
+
+-L             --print-path
+                       Normally, source filenames are printed with the path
+                       component suppressed.  With this option, gprof
+                       can be forced to print the full pathname of
+                       source filenames.  The full pathname is determined
+                       from symbolic debugging information in the image file
+                       and is relative to the directory in which the compiler
+                       was invoked.
+
+-y             --separate-files
+                       This option affects annotated source output only.
+                       Normally, gprof prints annotated source files
+                       to standard-output.  If this option is specified,
+                       annotated source for a file named "path/filename"
+                       is generated in the file "filename-ann".  That is,
+                       annotated output is {\em always\/} generated in
+                       gprof's current working directory.  Care has to
+                       be taken if a program consists of files that have
+                       identical filenames, but distinct paths.
+
+-c             --static-call-graph
+
+-t num         --table-length=num
+                       This option affects annotated source output only.
+                       After annotating a source file, gprof generates
+                       an execution count summary consisting of a table
+                       of lines with the top execution counts.  By
+                       default, this table is ten entries long.
+                       This option can be used to change the table length
+                       or, by specifying an argument value of 0, it can be
+                       suppressed completely.
+
+-n symspec     --time=symspec
+                       Only symbols selected by "symspec" are considered
+                       in total and percentage time computations.
+                       However, this option does not affect percentage time
+                       computation for the flat profile.
+                       If the option is specified multiple times, the union
+                       of all selected symbols is used in time computations.
+
+-N             --no-time=symspec
+                       Exclude the symbols selected by "symspec" from
+                       total and percentage time computations.
+                       However, this option does not affect percentage time
+                       computation for the flat profile.
+                       This option is ignored if any --time options are
+                       specified.
+
+-w num         --width=num
+                       Sets the output line width.  Currently, this option
+                       affects the printing of the call-graph function index
+                       only.
+
+-e             <no long form---for backwards compatibility only>
+-E             <no long form---for backwards compatibility only>
+-f             <no long form---for backwards compatibility only>
+-F             <no long form---for backwards compatibility only>
+-k             <no long form---for backwards compatibility only>
+-b             --brief
+-dnum          --debug[=num]
+
+-h             --help
+                       Prints a usage message.
+
+-O name                --file-format=name
+                       Selects the format of the profile data files.
+                       Recognized formats are "auto", "bsd", "magic",
+                       and "prof".  The last one is not yet supported.
+                       Format "auto" attempts to detect the file format
+                       automatically (this is the default behavior).
+                       It attempts to read the profile data files as
+                       "magic" files and if this fails, falls back to
+                       the "bsd" format.  "bsd" forces gprof to read
+                       the data files in the BSD format.  "magic" forces
+                       gprof to read the data files in the "magic" format.
+
+-T             --traditional
+-v             --version
+
+** File Format Changes
+
+The old BSD-derived format used for profile data does not contain a
+magic cookie that allows to check whether a data file really is a
+gprof file.  Furthermore, it does not provide a version number, thus
+rendering changes to the file format almost impossible.  GNU gprof
+uses a new file format that provides these features.  For backward
+compatibility, GNU gprof continues to support the old BSD-derived
+format, but not all features are supported with it.  For example,
+basic-block execution counts cannot be accommodated by the old file
+format.
+
+The new file format is defined in header file \file{gmon_out.h}.  It
+consists of a header containing the magic cookie and a version number,
+as well as some spare bytes available for future extensions.  All data
+in a profile data file is in the native format of the host on which
+the profile was collected.  GNU gprof adapts automatically to the
+byte-order in use.
+
+In the new file format, the header is followed by a sequence of
+records.  Currently, there are three different record types: histogram
+records, call-graph arc records, and basic-block execution count
+records.  Each file can contain any number of each record type.  When
+reading a file, GNU gprof will ensure records of the same type are
+compatible with each other and compute the union of all records.  For
+example, for basic-block execution counts, the union is simply the sum
+of all execution counts for each basic-block.
+
+*** Histogram Records
+
+Histogram records consist of a header that is followed by an array of
+bins.  The header contains the text-segment range that the histogram
+spans, the size of the histogram in bytes (unlike in the old BSD
+format, this does not include the size of the header), the rate of the
+profiling clock, and the physical dimension that the bin counts
+represent after being scaled by the profiling clock rate.  The
+physical dimension is specified in two parts: a long name of up to 15
+characters and a single character abbreviation.  For example, a
+histogram representing real-time would specify the long name as
+"seconds" and the abbreviation as "s".  This feature is useful for
+architectures that support performance monitor hardware (which,
+fortunately, is becoming increasingly common).  For example, under DEC
+OSF/1, the "uprofile" command can be used to produce a histogram of,
+say, instruction cache misses.  In this case, the dimension in the
+histogram header could be set to "i-cache misses" and the abbreviation
+could be set to "1" (because it is simply a count, not a physical
+dimension).  Also, the profiling rate would have to be set to 1 in
+this case.
+
+Histogram bins are 16-bit numbers and each bin represent an equal
+amount of text-space.  For example, if the text-segment is one
+thousand bytes long and if there are ten bins in the histogram, each
+bin represents one hundred bytes.
+
+
+*** Call-Graph Records
+
+Call-graph records have a format that is identical to the one used in
+the BSD-derived file format.  It consists of an arc in the call graph
+and a count indicating the number of times the arc was traversed
+during program execution.  Arcs are specified by a pair of addresses:
+the first must be within caller's function and the second must be
+within the callee's function.  When performing profiling at the
+function level, these addresses can point anywhere within the
+respective function.  However, when profiling at the line-level, it is
+better if the addresses are as close to the call-site/entry-point as
+possible.  This will ensure that the line-level call-graph is able to
+identify exactly which line of source code performed calls to a
+function.
+
+*** Basic-Block Execution Count Records
+
+Basic-block execution count records consist of a header followed by a
+sequence of address/count pairs.  The header simply specifies the
+length of the sequence.  In an address/count pair, the address
+identifies a basic-block and the count specifies the number of times
+that basic-block was executed.  Any address within the basic-address can
+be used.
+
+IMPLEMENTATION NOTE: gcc -a can be used to instrument a program to
+record basic-block execution counts.  However, the __bb_exit_func()
+that is currently present in libgcc2.c does not generate a gmon.out
+file in a suiteable format.  This should be fixed for future releases
+of gcc.  In the meantime, contact davidm@cs.arizona.edu for a version
+of __bb_exit_func() to is appropriate.
diff --git a/gprof/TEST b/gprof/TEST
new file mode 100644 (file)
index 0000000..78a9030
--- /dev/null
@@ -0,0 +1,7 @@
+- check whether old file format is properly read when input comes from
+  stdin
+
+- check whether underscores are properly dealt with (both, on systems
+  that prepend them to each C name and on systems that don't)
+
+- ensure gprof fails gracefully when no debugging info available
diff --git a/gprof/TODO b/gprof/TODO
new file mode 100644 (file)
index 0000000..20111c6
--- /dev/null
@@ -0,0 +1,72 @@
+
+- gmon_io.c cannot deal with target architecture that have a pointer size
+  that is different from the host architectures pointer size---fix this
+  (gmon_out.h, and gmon_io.c)
+- add support for prof file format so that prof files can be displayed
+  at the line-level (this is useful for the uprofile tool under DEC's
+  OSF/1)
+- take a hard look at --file-ordering (broken) and --function-ordering
+
++ documentation
++ optimize bfd_find_nearest_line_num() (or replace by different interface)
++ cleanup _bfd_ecoff_find_nearest_line_num() fixes & description
++ ensure "cc -pg" produces good files under OSF/1 v3.0
++ make sure gprof works together with OSF/1 v3.0's profiling libraries
++ implement symtab_parse(); modify sym_lookup() to consider addr_high
++ change gprof.c to collect lists, then invoke symtab_parse() for
+  each list
++ Questions:
+       o is -c (--static-call-graph) useful at all?  i can't see
+         how; if it were deleted, gprof would be completely machine
+         independent => yup, it is
+       o are (long) option names appropriate?
+       o -k (--exclude-arc) cannot be implemented with getopt();
+         is new syntax (-k from/to) acceptable?  If not, how to
+         fix it?
+       o in the FSF output, the call-graph index now prints
+         the filename of static functions in parentheses; e.g.,
+         static function foo() that is defined in file bar.c
+         would be printed as:
+
+                       [4] foo (bar.c)
+
+         is this acceptable?  should it be done only optionally?
+       o symbols with addresses that map back to a different
+         name are suppressed (happens with labels, for example);
+         is this acceptable?  should it be done only optionally?
++ generalize to allow arbitrary histograms (not just time histograms)
++ basic-block information currently replaces all symbols created from
+  the core because of an ugly ordering conflict---for now, the current
+  solution works, but something cleaner is desirable ==> cleaned up,
+  but it's slower now
++ convert to very new file format (back to trivial format, that is :)
++ replace "dummy.h" for Alpha (if there is any use to it)
++ add support for execution time profiling at a basic-block level
++ fix filename-off-by-one bug for Alpha (see ~/tmp/d.[ch])---no longer
+  relevant
++ "-pg -a" doesn't work as expected because mcleanup() will overwrite
+  the file generated by __bb_exit_func() (or vice versa)
++ first basic-block of fac() seems to get credited to last basic-block
+  of previous function => bug in basic_blocks.c
++ flat profile should provide automatic scaling for per-call times because
+  otherwise they'll always be zero on a fast machine with tons of small
+  functions
++ make "-a" imply to retain line number info (without actually generating
+  the debugging information (unless -g is specified)---no, this is a
+  bad idea, because it is not clear what level of debugging info should
+  be requested (e.g., -g vs. -g3); leaving it up to the user seems best
++ add long options support (or at least use getopt instead of ad-hoc
+  implementation)
++ split into files according to abstract objects that are manipulated
++ replace sccsid by rcsid & add "end of ..." to every .c file
++ use DBG() everywhere
++ fix spacing (" ," -> "," etc.)
++ use DEFUNs everywhere
++ make compile cleanly with -Wall
++ "gcc -pg -O2" doesn't work on tecc.c unless -fno-omit-frame-pointer is
+  specified; find out why
++ make things portable (prototypes, const, etc.)
++ if NEW_GMON_OUT is not defined, have a flag that will allow to
+  read new gmon.out style files.  The idea being that everyone
+  will use the new format for basic-block style profiling but
+  the old format for regular gpprofiling
diff --git a/gprof/aclocal.m4 b/gprof/aclocal.m4
new file mode 100644 (file)
index 0000000..ad20122
--- /dev/null
@@ -0,0 +1,1109 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Do all the work for Automake.  This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "[$]*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "[$]*" != "X $srcdir/configure conftestfile" \
+      && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "[$]2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+   $1=$2
+   AC_MSG_RESULT(found)
+else
+   $1="$3/missing $2"
+   AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+
+# serial 35 AC_PROG_LIBTOOL
+AC_DEFUN(AC_PROG_LIBTOOL,
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+# Save cache, so that ltconfig can load it
+AC_CACHE_SAVE
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+DLLTOOL="$DLLTOOL" AS="$AS" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| AC_MSG_ERROR([libtool configure failed])
+
+# Reload cache, that may have been modified by ltconfig
+AC_CACHE_LOAD
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+])
+
+AC_DEFUN(AC_LIBTOOL_SETUP,
+[AC_PREREQ(2.13)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_RANLIB])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_SYS_NM_PARSE])dnl
+AC_REQUIRE([AC_SYS_SYMBOL_UNDERSCORE])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+dnl
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags="--cache-file=$cache_file"
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$lt_dlopen" = yes && libtool_flags="$libtool_flags --enable-dlopen"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$host" in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+*-*-cygwin*)
+  AC_SYS_LIBTOOL_CYGWIN
+  ;;
+
+esac
+
+# enable the --disable-libtool-lock switch
+
+AC_ARG_ENABLE(libtool-lock,
+[  --disable-libtool-lock  force libtool not to do file locking],
+need_locks=$enableval,
+need_locks=yes)
+
+if test x"$need_locks" = xno; then
+  libtool_flags="$libtool_flags --disable-lock"
+fi
+])
+
+# AC_LIBTOOL_DLOPEN - check for dlopen support
+AC_DEFUN(AC_LIBTOOL_DLOPEN, [lt_dlopen=yes])
+
+# AC_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_SHARED,
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<<  --enable-shared[=PKGS]  build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN(AC_DISABLE_SHARED,
+[AC_ENABLE_SHARED(no)])
+
+# AC_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_STATIC,
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<<  --enable-static[=PKGS]  build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+])
+
+# AC_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN(AC_DISABLE_STATIC,
+[AC_ENABLE_STATIC(no)])
+
+
+# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_FAST_INSTALL,
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(fast-install,
+changequote(<<, >>)dnl
+<<  --enable-fast-install[=PKGS]  optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+])
+
+# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install
+AC_DEFUN(AC_DISABLE_FAST_INSTALL,
+[AC_ENABLE_FAST_INSTALL(no)])
+
+
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN(AC_PROG_LD,
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  ac_prog=`($CC -print-prog-name=ld) 2>&5`
+  case "$ac_prog" in
+    # Accept absolute paths.
+changequote(,)dnl
+    /* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+changequote([,])dnl
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog"; then
+      ac_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_SUBST(LD)
+AC_PROG_LD_GNU
+])
+
+AC_DEFUN(AC_PROG_LD_GNU,
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  ac_cv_prog_gnu_ld=yes
+else
+  ac_cv_prog_gnu_ld=no
+fi])
+])
+
+# AC_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN(AC_PROG_NM,
+[AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(ac_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  ac_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/nm; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -B"
+       break
+      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -p"
+       break
+      else
+       ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi])
+NM="$ac_cv_path_NM"
+AC_MSG_RESULT([$NM])
+AC_SUBST(NM)
+])
+
+# AC_SYS_NM_PARSE - Check for command to grab the raw symbol name followed
+# by C symbol name from nm.
+AC_DEFUN(AC_SYS_NM_PARSE,
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output])
+AC_CACHE_VAL(ac_cv_sys_global_symbol_pipe,
+[# These are sane defaults that work on at least a few old systems.
+# {They come from Ultrix.  What could be older than Ultrix?!! ;)}
+
+changequote(,)dnl
+# Character class describing NM global symbol codes.
+ac_symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+ac_symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+  ac_symcode='[BCDT]'
+  ;;
+cygwin* | mingw*)
+  ac_symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+  ;;
+irix*)
+  ac_symcode='[BCDEGRST]'
+  ;;
+solaris*)
+  ac_symcode='[BDT]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  ac_symcode='[ABCDGISTW]'
+fi
+changequote([,])dnl
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[      ]\($ac_symcode\)[       ][      ]*\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  ac_pipe_works=no
+  rm -f conftest.$ac_ext
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func;return 0;}
+EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+  
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
+
+      # Try sorting and uniquifying the output.
+      if sort "$ac_nlist" | uniq > "$ac_nlist"T; then
+       mv -f "$ac_nlist"T "$ac_nlist"
+      else
+       rm -f "$ac_nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then
+       if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then
+         cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c'
+
+         cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+changequote(,)dnl
+lt_preloaded_symbols[] =
+changequote([,])dnl
+{
+EOF
+       sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c
+       cat <<\EOF >> conftest.c
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftestm.$ac_objext
+         ac_save_LIBS="$LIBS"
+         ac_save_CFLAGS="$CFLAGS"
+         LIBS="conftestm.$ac_objext"
+         CFLAGS="$CFLAGS$no_builtin_flag"
+         if AC_TRY_EVAL(ac_link) && test -s conftest; then
+           ac_pipe_works=yes
+         else
+           echo "configure: failed program was:" >&AC_FD_CC
+           cat conftest.c >&AC_FD_CC
+         fi
+         LIBS="$ac_save_LIBS"
+         CFLAGS="$ac_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $ac_nlist" >&AC_FD_CC
+       fi
+      else
+       echo "cannot find nm_test_var in $ac_nlist" >&AC_FD_CC
+      fi
+    else
+      echo "cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC
+    fi
+  else
+    echo "$progname: failed program was:" >&AC_FD_CC
+    cat conftest.c >&AC_FD_CC
+  fi
+  rm -rf conftest*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$ac_pipe_works" = yes; then
+    if test x"$ac_symprfx" = x"_"; then
+      ac_cv_sys_symbol_underscore=yes
+    else
+      ac_cv_sys_symbol_underscore=no
+    fi
+    break
+  else
+    ac_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+
+ac_result=yes
+if test -z "$ac_cv_sys_global_symbol_pipe"; then
+   ac_result=no
+fi
+AC_MSG_RESULT($ac_result)
+])
+
+# AC_SYS_LIBTOOL_CYGWIN - find tools needed on cygwin
+AC_DEFUN(AC_SYS_LIBTOOL_CYGWIN,
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+AC_CHECK_TOOL(AS, as, false)
+])
+
+# AC_SYS_SYMBOL_UNDERSCORE - does the compiler prefix global symbols
+#                            with an underscore?
+AC_DEFUN(AC_SYS_SYMBOL_UNDERSCORE,
+[AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_SYS_NM_PARSE])dnl
+AC_MSG_CHECKING([for _ prefix in compiled symbols])
+AC_CACHE_VAL(ac_cv_sys_symbol_underscore,
+[ac_cv_sys_symbol_underscore=no
+cat > conftest.$ac_ext <<EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+EOF
+if AC_TRY_EVAL(ac_compile); then
+  # Now try to grab the symbols.
+  ac_nlist=conftest.nm
+  if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
+    # See whether the symbols have a leading underscore.
+    if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+      ac_cv_sys_symbol_underscore=yes
+    else
+      if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+       :
+      else
+       echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC
+      fi
+    fi
+  else
+    echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC
+  fi
+else
+  echo "configure: failed program was:" >&AC_FD_CC
+  cat conftest.c >&AC_FD_CC
+fi
+rm -rf conftest*
+])
+AC_MSG_RESULT($ac_cv_sys_symbol_underscore)
+USE_SYMBOL_UNDERSCORE=${ac_cv_sys_symbol_underscore=no}
+AC_SUBST(USE_SYMBOL_UNDERSCORE)dnl
+])
+
+# AC_CHECK_LIBM - check for math library
+AC_DEFUN(AC_CHECK_LIBM, [
+AC_CHECK_LIB(mw, _mwvalidcheckl)
+AC_CHECK_LIB(m, cos)
+])
+
+# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl convenience library, adds --enable-ltdl-convenience to
+# the configure arguments.  Note that LIBLTDL is not AC_SUBSTed, nor
+# is AC_CONFIG_SUBDIRS called.  If DIR is not provided, it is assumed
+# to be `${top_builddir}/libltdl'.  Make sure you start DIR with
+# '${top_builddir}/' (note the single quotes!) if your package is not
+# flat, and, if you're not using automake, define top_builddir as
+# appropriate in the Makefiles.
+AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [
+  case "$enable_ltdl_convenience" in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
+])
+
+# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl installable library, and adds --enable-ltdl-install to
+# the configure arguments.  Note that LIBLTDL is not AC_SUBSTed, nor
+# is AC_CONFIG_SUBDIRS called.  If DIR is not provided, it is assumed
+# to be `${top_builddir}/libltdl'.  Make sure you start DIR with
+# '${top_builddir}/' (note the single quotes!) if your package is not
+# flat, and, if you're not using automake, define top_builddir as
+# appropriate in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [
+  AC_CHECK_LIB(ltdl, main, LIBLTDL="-lltdl", [
+    case "$enable_ltdl_install" in
+    no) AC_MSG_WARN([libltdl not installed, but installation disabled]) ;;
+    "") enable_ltdl_install=yes
+        ac_configure_args="$ac_configure_args --enable-ltdl-install" ;;
+    esac
+  ])
+  if test x"$enable_ltdl_install" != x"no"; then
+    LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
+  fi
+])
+
+dnl old names
+AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl
+AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl
+AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl
+AC_DEFUN(AM_SYS_NM_PARSE, [indir([AC_SYS_NM_PARSE])])dnl
+AC_DEFUN(AM_SYS_SYMBOL_UNDERSCORE, [indir([AC_SYS_SYMBOL_UNDERSCORE])])dnl
+AC_DEFUN(AM_SYS_LIBTOOL_CYGWIN, [indir([AC_SYS_LIBTOOL_CYGWIN])])dnl
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated.  We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+  case " <<$>>CONFIG_HEADERS " in
+  *" <<$>>am_file "*<<)>>
+    echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+    ;;
+  esac
+  am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+# This file is derived from `gettext.m4'.  The difference is that the
+# included macros assume Cygnus-style source and build trees.
+
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 3
+
+AC_DEFUN(CY_WITH_NLS,
+  [AC_MSG_CHECKING([whether NLS is requested])
+    dnl Default is enabled NLS
+    AC_ARG_ENABLE(nls,
+      [  --disable-nls           do not use Native Language Support],
+      USE_NLS=$enableval, USE_NLS=yes)
+    AC_MSG_RESULT($USE_NLS)
+    AC_SUBST(USE_NLS)
+
+    USE_INCLUDED_LIBINTL=no
+
+    dnl If we use NLS figure out what method
+    if test "$USE_NLS" = "yes"; then
+      AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if NLS is requested])
+      AC_MSG_CHECKING([whether included gettext is requested])
+      AC_ARG_WITH(included-gettext,
+        [  --with-included-gettext use the GNU gettext library included here],
+        nls_cv_force_use_gnu_gettext=$withval,
+        nls_cv_force_use_gnu_gettext=no)
+      AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+      nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+      if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+        dnl User does not insist on using GNU NLS library.  Figure out what
+        dnl to use.  If gettext or catgets are available (in this order) we
+        dnl use this.  Else we have to fall back to GNU NLS library.
+       dnl catgets is only used if permitted by option --with-catgets.
+       nls_cv_header_intl=
+       nls_cv_header_libgt=
+       CATOBJEXT=NONE
+
+       AC_CHECK_HEADER(libintl.h,
+         [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
+           [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
+              gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
+
+          if test "$gt_cv_func_gettext_libc" != "yes"; then
+            AC_CHECK_LIB(intl, bindtextdomain,
+              [AC_CACHE_CHECK([for gettext in libintl],
+                gt_cv_func_gettext_libintl,
+                [AC_TRY_LINK([], [return (int) gettext ("")],
+                gt_cv_func_gettext_libintl=yes,
+                gt_cv_func_gettext_libintl=no)])])
+          fi
+
+          if test "$gt_cv_func_gettext_libc" = "yes" \
+             || test "$gt_cv_func_gettext_libintl" = "yes"; then
+             AC_DEFINE(HAVE_GETTEXT, 1,
+                       [Define as 1 if you have gettext and don't want to use GNU gettext.])
+             AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+               [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+             if test "$MSGFMT" != "no"; then
+               AC_CHECK_FUNCS(dcgettext)
+               AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+               AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+                 [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+               AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+                              return _nl_msg_cat_cntr],
+                 [CATOBJEXT=.gmo
+                  DATADIRNAME=share],
+                 [CATOBJEXT=.mo
+                  DATADIRNAME=lib])
+               INSTOBJEXT=.mo
+             fi
+           fi
+       ])
+
+       dnl In the standard gettext, we would now check for catgets.
+        dnl However, we never want to use catgets for our releases.
+
+        if test "$CATOBJEXT" = "NONE"; then
+         dnl Neither gettext nor catgets in included in the C library.
+         dnl Fall back on GNU gettext library.
+         nls_cv_use_gnu_gettext=yes
+        fi
+      fi
+
+      if test "$nls_cv_use_gnu_gettext" = "yes"; then
+        dnl Mark actions used to generate GNU NLS library.
+        INTLOBJS="\$(GETTOBJS)"
+        AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+         [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
+        AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+        AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+         [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+        AC_SUBST(MSGFMT)
+       USE_INCLUDED_LIBINTL=yes
+        CATOBJEXT=.gmo
+        INSTOBJEXT=.mo
+        DATADIRNAME=share
+       INTLDEPS='$(top_builddir)/../intl/libintl.a'
+       INTLLIBS=$INTLDEPS
+       LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+        nls_cv_header_intl=libintl.h
+        nls_cv_header_libgt=libgettext.h
+      fi
+
+      dnl Test whether we really found GNU xgettext.
+      if test "$XGETTEXT" != ":"; then
+       dnl If it is no GNU xgettext we define it as : so that the
+       dnl Makefiles still can work.
+       if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+         : ;
+       else
+         AC_MSG_RESULT(
+           [found xgettext programs is not GNU xgettext; ignore it])
+         XGETTEXT=":"
+       fi
+      fi
+
+      # We need to process the po/ directory.
+      POSUB=po
+    else
+      DATADIRNAME=share
+      nls_cv_header_intl=libintl.h
+      nls_cv_header_libgt=libgettext.h
+    fi
+
+    # If this is used in GNU gettext we have to set USE_NLS to `yes'
+    # because some of the sources are only built for this goal.
+    if test "$PACKAGE" = gettext; then
+      USE_NLS=yes
+      USE_INCLUDED_LIBINTL=yes
+    fi
+
+    dnl These rules are solely for the distribution goal.  While doing this
+    dnl we only have to keep exactly one list of the available catalogs
+    dnl in configure.in.
+    for lang in $ALL_LINGUAS; do
+      GMOFILES="$GMOFILES $lang.gmo"
+      POFILES="$POFILES $lang.po"
+    done
+
+    dnl Make all variables we use known to autoconf.
+    AC_SUBST(USE_INCLUDED_LIBINTL)
+    AC_SUBST(CATALOGS)
+    AC_SUBST(CATOBJEXT)
+    AC_SUBST(DATADIRNAME)
+    AC_SUBST(GMOFILES)
+    AC_SUBST(INSTOBJEXT)
+    AC_SUBST(INTLDEPS)
+    AC_SUBST(INTLLIBS)
+    AC_SUBST(INTLOBJS)
+    AC_SUBST(POFILES)
+    AC_SUBST(POSUB)
+  ])
+
+AC_DEFUN(CY_GNU_GETTEXT,
+  [AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+   AC_REQUIRE([AC_PROG_CC])dnl
+   AC_REQUIRE([AC_PROG_RANLIB])dnl
+   AC_REQUIRE([AC_ISC_POSIX])dnl
+   AC_REQUIRE([AC_HEADER_STDC])dnl
+   AC_REQUIRE([AC_C_CONST])dnl
+   AC_REQUIRE([AC_C_INLINE])dnl
+   AC_REQUIRE([AC_TYPE_OFF_T])dnl
+   AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+   AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+   AC_REQUIRE([AC_FUNC_MMAP])dnl
+
+   AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h])
+   AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next])
+
+   if test "${ac_cv_func_stpcpy+set}" != "set"; then
+     AC_CHECK_FUNCS(stpcpy)
+   fi
+   if test "${ac_cv_func_stpcpy}" = "yes"; then
+     AC_DEFINE(HAVE_STPCPY, 1, [Define if you have the stpcpy function])
+   fi
+
+   AM_LC_MESSAGES
+   CY_WITH_NLS
+
+   if test "x$CATOBJEXT" != "x"; then
+     if test "x$ALL_LINGUAS" = "x"; then
+       LINGUAS=
+     else
+       AC_MSG_CHECKING(for catalogs to be installed)
+       NEW_LINGUAS=
+       for lang in ${LINGUAS=$ALL_LINGUAS}; do
+         case "$ALL_LINGUAS" in
+          *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+         esac
+       done
+       LINGUAS=$NEW_LINGUAS
+       AC_MSG_RESULT($LINGUAS)
+     fi
+
+     dnl Construct list of names of catalog files to be constructed.
+     if test -n "$LINGUAS"; then
+       for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+     fi
+   fi
+
+   dnl The reference to <locale.h> in the installed <libintl.h> file
+   dnl must be resolved because we cannot expect the users of this
+   dnl to define HAVE_LOCALE_H.
+   if test $ac_cv_header_locale_h = yes; then
+     INCLUDE_LOCALE_H="#include <locale.h>"
+   else
+     INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>.  Take care yourself.  */"
+   fi
+   AC_SUBST(INCLUDE_LOCALE_H)
+
+   dnl Determine which catalog format we have (if any is needed)
+   dnl For now we know about two different formats:
+   dnl   Linux libc-5 and the normal X/Open format
+   if test -f $srcdir/po2tbl.sed.in; then
+      if test "$CATOBJEXT" = ".cat"; then
+        AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
+
+        dnl Transform the SED scripts while copying because some dumb SEDs
+         dnl cannot handle comments.
+        sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed
+      fi
+      dnl po2tbl.sed is always needed.
+      sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+        $srcdir/po2tbl.sed.in > po2tbl.sed
+   fi
+
+   dnl In the intl/Makefile.in we have a special dependency which makes
+   dnl only sense for gettext.  We comment this out for non-gettext
+   dnl packages.
+   if test "$PACKAGE" = "gettext"; then
+     GT_NO="#NO#"
+     GT_YES=
+   else
+     GT_NO=
+     GT_YES="#YES#"
+   fi
+   AC_SUBST(GT_NO)
+   AC_SUBST(GT_YES)
+
+   MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs"
+   AC_SUBST(MKINSTALLDIRS)
+
+   dnl *** For now the libtool support in intl/Makefile is not for real.
+   l=
+   AC_SUBST(l)
+
+   dnl Generate list of files to be processed by xgettext which will
+   dnl be included in po/Makefile.  But only do this if the po directory
+   dnl exists in srcdir.
+   if test -d $srcdir/po; then
+      test -d po || mkdir po
+      if test "x$srcdir" != "x."; then
+        if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+           posrcprefix="$srcdir/"
+        else
+           posrcprefix="../$srcdir/"
+        fi
+      else
+        posrcprefix="../"
+      fi
+      rm -f po/POTFILES
+      sed -e "/^#/d" -e "/^\$/d" -e "s,.*,     $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+        < $srcdir/po/POTFILES.in > po/POTFILES
+   fi
+  ])
+
+# Search path for a program which passes the given test.
+# Ulrich Drepper <drepper@cygnus.com>, 1996.
+#
+# This file file be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl   TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN(AM_PATH_PROG_WITH_TEST,
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+  /*)
+  ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in ifelse([$5], , $PATH, [$5]); do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if [$3]; then
+       ac_cv_path_$1="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [  test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+  ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test -n "[$]$1"; then
+  AC_MSG_RESULT([$]$1)
+else
+  AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+AC_DEFUN(AM_LC_MESSAGES,
+  [if test $ac_cv_header_locale_h = yes; then
+    AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+      [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+       am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+    if test $am_cv_val_LC_MESSAGES = yes; then
+      AC_DEFINE(HAVE_LC_MESSAGES, 1,
+               [Define if your locale.h file contains LC_MESSAGES.])
+    fi
+  fi])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# serial 1
+
+AC_DEFUN(AM_MAINTAINER_MODE,
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode is disabled by default
+  AC_ARG_ENABLE(maintainer-mode,
+[  --enable-maintainer-mode enable make rules and dependencies not useful
+                          (and sometimes confusing) to the casual installer],
+      USE_MAINTAINER_MODE=$enableval,
+      USE_MAINTAINER_MODE=no)
+  AC_MSG_RESULT($USE_MAINTAINER_MODE)
+  AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes)
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST(MAINT)dnl
+]
+)
+
+# Define a conditional.
+
+AC_DEFUN(AM_CONDITIONAL,
+[AC_SUBST($1_TRUE)
+AC_SUBST($1_FALSE)
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi])
+
diff --git a/gprof/alpha.c b/gprof/alpha.c
new file mode 100644 (file)
index 0000000..ad4f22e
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1983, 1998 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "gprof.h"
+#include "cg_arcs.h"
+#include "corefile.h"
+#include "hist.h"
+#include "symtab.h"
+
+/*
+ * Opcodes of the call instructions:
+ */
+#define OP_Jxx 0x1a
+#define        OP_BSR  0x34
+
+#define Jxx_FUNC_JMP           0
+#define Jxx_FUNC_JSR           1
+#define Jxx_FUNC_RET           2
+#define Jxx_FUNC_JSR_COROUTINE 3
+
+typedef union
+  {
+    struct
+      {
+       unsigned other:26;
+       unsigned op_code:6;
+      }
+    a;                         /* any format */
+    struct
+      {
+       int disp:21;
+       unsigned ra:5;
+       unsigned op_code:6;
+      }
+    b;                         /* branch format */
+    struct
+      {
+       int hint:14;
+       unsigned func:2;
+       unsigned rb:5;
+       unsigned ra:5;
+       unsigned op_code:6;
+      }
+    j;                         /* jump format */
+  }
+alpha_Instruction;
+
+static Sym indirect_child;
+
+
+/*
+ * On the Alpha we can only detect PC relative calls, which are
+ * usually generated for calls to functions within the same
+ * object file only.  This is still better than nothing, however.
+ * (In particular it should be possible to find functions that
+ *  potentially call integer division routines, for example.)
+ */
+void
+alpha_find_call (parent, p_lowpc, p_highpc)
+     Sym *parent;
+     bfd_vma p_lowpc;
+     bfd_vma p_highpc;
+{
+  static bfd_vma delta = 0;
+  bfd_vma dest_pc;
+  alpha_Instruction *pc;
+  Sym *child;
+
+  if (!delta)
+    {
+      delta = (bfd_vma) core_text_space - core_text_sect->vma;
+
+      sym_init (&indirect_child);
+      indirect_child.name = _("<indirect child>");
+      indirect_child.cg.prop.fract = 1.0;
+      indirect_child.cg.cyc.head = &indirect_child;
+    }
+
+  if (!core_text_space)
+    {
+      return;
+    }
+  if (p_lowpc < s_lowpc)
+    {
+      p_lowpc = s_lowpc;
+    }
+  if (p_highpc > s_highpc)
+    {
+      p_highpc = s_highpc;
+    }
+  DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
+                         parent->name, p_lowpc, p_highpc));
+  for (pc = (alpha_Instruction *) (p_lowpc + delta);
+       pc < (alpha_Instruction *) (p_highpc + delta);
+       ++pc)
+    {
+      switch (pc->a.op_code)
+       {
+       case OP_Jxx:
+         /*
+          * There is no simple and reliable way to determine the
+          * target of a jsr (the hint bits help, but there aren't
+          * enough bits to get a satisfactory hit rate).  Instead,
+          * for any indirect jump we simply add an arc from PARENT
+          * to INDIRECT_CHILD---that way the user it at least able
+          * to see that there are other calls as well.
+          */
+         if (pc->j.func == Jxx_FUNC_JSR
+             || pc->j.func == Jxx_FUNC_JSR_COROUTINE)
+           {
+             DBG (CALLDEBUG,
+                  printf (_("[find_call] 0x%lx: jsr%s <indirect_child>\n"),
+                          (bfd_vma) pc - delta,
+                          pc->j.func == Jxx_FUNC_JSR ? "" : "_coroutine"));
+             arc_add (parent, &indirect_child, (unsigned long) 0);
+           }
+         break;
+
+       case OP_BSR:
+         DBG (CALLDEBUG,
+              printf (_("[find_call] 0x%lx: bsr"), (bfd_vma) pc - delta));
+         /*
+          * Regular PC relative addressing.  Check that this is the
+          * address of a function.  The linker sometimes redirects
+          * the entry point by 8 bytes to skip loading the global
+          * pointer, so we all for either address:
+          */
+         dest_pc = ((bfd_vma) (pc + 1 + pc->b.disp)) - delta;
+         if (dest_pc >= s_lowpc && dest_pc <= s_highpc)
+           {
+             child = sym_lookup (&symtab, dest_pc);
+             DBG (CALLDEBUG,
+                  printf (" 0x%lx\t; name=%s, addr=0x%lx",
+                          dest_pc, child->name, child->addr));
+             if (child->addr == dest_pc || child->addr == dest_pc - 8)
+               {
+                 DBG (CALLDEBUG, printf ("\n"));
+                 /* a hit:  */
+                 arc_add (parent, child, (unsigned long) 0);
+                 continue;
+               }
+           }
+         /*
+          * Something funny going on.
+          */
+         DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
+         break;
+
+       default:
+         break;
+       }
+    }
+}
diff --git a/gprof/basic_blocks.c b/gprof/basic_blocks.c
new file mode 100644 (file)
index 0000000..07b6f8d
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ * Basic-block level related code: reading/writing of basic-block info
+ * to/from gmon.out; computing and formatting of basic-block related
+ * statistics.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include "basic_blocks.h"
+#include "corefile.h"
+#include "gmon_io.h"
+#include "gmon_out.h"
+#include "gprof.h"
+#include "libiberty.h"
+#include "source.h"
+#include "sym_ids.h"
+
+
+/*
+ * Default option values:
+ */
+bool bb_annotate_all_lines = FALSE;
+unsigned long bb_min_calls = 1;
+int bb_table_length = 10;
+
+/*
+ * Variables used to compute annotated source listing stats:
+ */
+static long num_executable_lines;
+static long num_lines_executed;
+
+
+/*
+ * Helper for sorting.  Compares two symbols and returns result
+ * such that sorting will be increasing according to filename, line
+ * number, and address (in that order).
+ */
+
+static int
+DEFUN (cmp_bb, (lp, rp), const void *lp AND const void *rp)
+{
+  int r;
+  const Sym *left = *(const Sym **) lp;
+  const Sym *right = *(const Sym **) rp;
+
+  if (left->file && right->file)
+    {
+      r = strcmp (left->file->name, right->file->name);
+      if (r)
+       {
+         return r;
+       }
+
+      if (left->line_num != right->line_num)
+       {
+         return left->line_num - right->line_num;
+       }
+    }
+
+  if (left->addr < right->addr)
+    {
+      return -1;
+    }
+  else if (left->addr > right->addr)
+    {
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+
+/*
+ * Helper for sorting.  Order basic blocks in decreasing number of
+ * calls, ties are broken in increasing order of line numbers.
+ */
+static int
+DEFUN (cmp_ncalls, (lp, rp), const void *lp AND const void *rp)
+{
+  const Sym *left = *(const Sym **) lp;
+  const Sym *right = *(const Sym **) rp;
+
+  if (!left)
+    {
+      return 1;
+    }
+  else if (!right)
+    {
+      return -1;
+    }
+
+  if (left->ncalls < right->ncalls)
+    return 1;
+  else if (left->ncalls > right->ncalls)
+    return -1;
+
+  return left->line_num - right->line_num;
+}
+
+
+/*
+ * Skip over variable length string.
+ */
+static void
+DEFUN (fskip_string, (fp), FILE * fp)
+{
+  int ch;
+
+  while ((ch = fgetc (fp)) != EOF)
+    {
+      if (ch == '\0')
+       {
+         break;
+       }
+    }
+}
+
+
+/*
+ * Read a basic-block record from file IFP.  FILENAME is the name
+ * of file IFP and is provided for formatting error-messages only.
+ */
+void
+DEFUN (bb_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
+{
+  int nblocks, b;
+  bfd_vma addr;
+  unsigned long ncalls;
+  Sym *sym;
+
+  if (fread (&nblocks, sizeof (nblocks), 1, ifp) != 1)
+    {
+      fprintf (stderr, _("%s: %s: unexpected end of file\n"), whoami, filename);
+      done (1);
+    }
+
+  nblocks = bfd_get_32 (core_bfd, (bfd_byte *) & nblocks);
+  if (gmon_file_version == 0)
+    {
+      fskip_string (ifp);
+    }
+
+  for (b = 0; b < nblocks; ++b)
+    {
+      if (gmon_file_version == 0)
+       {
+         int line_num;
+         /*
+          * Version 0 had lots of extra stuff that we don't
+          * care about anymore.
+          */
+         if ((fread (&ncalls, sizeof (ncalls), 1, ifp) != 1)
+             || (fread (&addr, sizeof (addr), 1, ifp) != 1)
+             || (fskip_string (ifp), FALSE)
+             || (fskip_string (ifp), FALSE)
+             || (fread (&line_num, sizeof (line_num), 1, ifp) != 1))
+           {
+             perror (filename);
+             done (1);
+           }
+       }
+      else
+       {
+         if (fread (&addr, sizeof (addr), 1, ifp) != 1
+             || fread (&ncalls, sizeof (ncalls), 1, ifp) != 1)
+           {
+             perror (filename);
+             done (1);
+           }
+       }
+
+      /*
+       * Basic-block execution counts are meaningful only if we're
+       * profiling at the line-by-line level:
+       */
+      if (line_granularity)
+       {
+
+         /* convert from target to host endianness: */
+
+         addr = get_vma (core_bfd, (bfd_byte *) & addr);
+         ncalls = bfd_get_32 (core_bfd, (bfd_byte *) &ncalls);
+
+         sym = sym_lookup (&symtab, addr);
+
+         if (sym)
+           {
+             int i;
+
+             DBG (BBDEBUG,
+                  printf ("[bb_read_rec] 0x%lx->0x%lx (%s:%d) cnt=%lu\n",
+                          addr, sym->addr, sym->name, sym->line_num, ncalls));
+
+             for (i = 0; i < NBBS; i++)
+               {
+                 if (! sym->bb_addr[i] || sym->bb_addr[i] == addr)
+                   {
+                     sym->bb_addr[i] = addr;
+                     sym->bb_calls[i] += ncalls;
+                     break;
+                   }
+               }
+           }
+       }
+      else
+       {
+         static bool user_warned = FALSE;
+
+         if (!user_warned)
+           {
+             user_warned = TRUE;
+             fprintf (stderr,
+                      _("%s: warning: ignoring basic-block exec counts (use -l or --line)\n"),
+                      whoami);
+           }
+       }
+    }
+  return;
+}
+
+
+/*
+ * Write all basic-blocks with non-zero counts to file OFP.  FILENAME
+ * is the name of OFP and is provided for producing error-messages
+ * only.
+ */
+void
+DEFUN (bb_write_blocks, (ofp, filename), FILE * ofp AND const char *filename)
+{
+  const unsigned char tag = GMON_TAG_BB_COUNT;
+  int nblocks = 0;
+  bfd_vma addr;
+  unsigned long ncalls;
+  Sym *sym;
+  int i;
+
+  /* count how many non-zero blocks with have: */
+
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      for (i = 0; i < NBBS && sym->bb_addr[i]; i++)
+       ;
+      nblocks += i;
+    }
+
+  /* write header: */
+  bfd_put_32 (core_bfd, nblocks, (bfd_byte *) & nblocks);
+  if (fwrite (&tag, sizeof (tag), 1, ofp) != 1
+      || fwrite (&nblocks, sizeof (nblocks), 1, ofp) != 1)
+    {
+      perror (filename);
+      done (1);
+    }
+
+  /* write counts: */
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      for (i = 0; i < NBBS && sym->bb_addr[i]; i++)
+       {
+         put_vma (core_bfd, sym->bb_addr[i], (bfd_byte *) & addr);
+         bfd_put_32 (core_bfd, sym->bb_calls[i], (bfd_byte *) & ncalls);
+
+         if (fwrite (&addr, sizeof (addr), 1, ofp) != 1
+             || fwrite (&ncalls, sizeof (ncalls), 1, ofp) != 1)
+           {
+             perror (filename);
+             done (1);
+           }
+       }
+    }
+}
+
+
+/*
+ * Output basic-block statistics in a format that is easily parseable.
+ * Current the format is:
+ *
+ *      <filename>:<line-number>: (<function-name>:<bb-addr): <ncalls>
+ */
+void
+DEFUN_VOID (print_exec_counts)
+{
+  Sym **sorted_bbs, *sym;
+  int i, j, len;
+
+  if (first_output)
+    {
+      first_output = FALSE;
+    }
+  else
+    {
+      printf ("\f\n");
+    }
+
+  /* sort basic-blocks according to function name and line number: */
+
+  sorted_bbs = (Sym **) xmalloc (symtab.len * sizeof (sorted_bbs[0]));
+  len = 0;
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      /*
+       * Accept symbol if it's in the INCL_EXEC table
+       * or there is no INCL_EXEC table
+       *    and it does not appear in the EXCL_EXEC table.
+       */
+      if (sym_lookup (&syms[INCL_EXEC], sym->addr)
+         || (syms[INCL_EXEC].len == 0
+             && !sym_lookup (&syms[EXCL_EXEC], sym->addr)))
+       {
+         sorted_bbs[len++] = sym;
+       }
+    }
+  qsort (sorted_bbs, len, sizeof (sorted_bbs[0]), cmp_bb);
+
+  /* output basic-blocks: */
+
+  for (i = 0; i < len; ++i)
+    {
+      if (sym->ncalls > 0 || ! ignore_zeros)
+       {
+         printf (_("%s:%d: (%s:0x%lx) %lu executions\n"),
+                 sym->file ? sym->file->name : _("<unknown>"), sym->line_num,
+                 sym->name, sym->addr, sym->ncalls);
+       }
+      for (j = 0; j < NBBS && sym->bb_addr[j]; j ++)
+       {
+         if (sym->bb_calls[j] > 0 || ! ignore_zeros)
+           {
+             printf (_("%s:%d: (%s:0x%lx) %lu executions\n"),
+                     sym->file ? sym->file->name : _("<unknown>"), sym->line_num,
+                     sym->name, sym->bb_addr[j], sym->bb_calls[j]);
+           }
+       }
+    }
+  free (sorted_bbs);
+}
+
+/*
+ * Helper for bb_annotated_source: format annotation containing
+ * number of line executions.  Depends on being called on each
+ * line of a file in sequential order.
+ *
+ * Global variable bb_annotate_all_lines enables execution count
+ * compression (counts are supressed if identical to the last one)
+ * and prints counts on all executed lines.  Otherwise, print
+ * all basic-block execution counts exactly once on the line
+ * that starts the basic-block.
+ */
+
+static void
+DEFUN (annotate_with_count, (buf, width, line_num, arg),
+       char *buf AND int width AND int line_num AND void *arg)
+{
+  Source_File *sf = arg;
+  Sym *b;
+  int i;
+  static unsigned long last_count;
+  unsigned long last_print = (unsigned long) -1;
+
+  b = NULL;
+  if (line_num <= sf->num_lines)
+    {
+      b = sf->line[line_num - 1];
+    }
+  if (!b)
+    {
+      for (i = 0; i < width; i++)
+       buf[i] = ' ';
+      buf[width] = '\0';
+    }
+  else
+    {
+      char tmpbuf[NBBS * 30];
+      char *p;
+      unsigned long ncalls;
+      int ncalls_set;
+      int len;
+
+      ++num_executable_lines;
+
+      p = tmpbuf;
+      *p = '\0';
+
+      ncalls = 0;
+      ncalls_set = 0;
+
+      /* If this is a function entry point, label the line no matter what.
+       * Otherwise, we're in the middle of a function, so check to see
+       * if the first basic-block address is larger than the starting
+       * address of the line.  If so, then this line begins with a
+       * a portion of the previous basic-block, so print that prior
+       * execution count (if bb_annotate_all_lines is set).
+       */
+
+      if (b->is_func)
+       {
+         sprintf (p, "%lu", b->ncalls);
+         p += strlen (p);
+         last_count = b->ncalls;
+         last_print = last_count;
+         ncalls = b->ncalls;
+         ncalls_set = 1;
+       }
+      else if (bb_annotate_all_lines
+              && b->bb_addr[0] && b->bb_addr[0] > b->addr)
+       {
+         sprintf (p, "%lu", last_count);
+         p += strlen (p);
+         last_print = last_count;
+         ncalls = last_count;
+         ncalls_set = 1;
+       }
+
+      /* Loop through all of this line's basic-blocks.  For each one,
+       * update last_count, then compress sequential identical counts
+       * (if bb_annotate_all_lines) and print the execution count.
+       */
+
+      for (i = 0; i < NBBS && b->bb_addr[i]; i++)
+       {
+         last_count = b->bb_calls[i];
+         if (! ncalls_set)
+           {
+             ncalls = 0;
+             ncalls_set = 1;
+           }
+         ncalls += last_count;
+
+         if (bb_annotate_all_lines && last_count == last_print)
+           {
+             continue;
+           }
+
+         if (p > tmpbuf)
+           *p++ = ',';
+         sprintf (p, "%lu", last_count);
+         p += strlen (p);
+
+         last_print = last_count;
+       }
+
+      /* We're done.  If nothing has been printed on this line,
+       * print the last execution count (bb_annotate_all_lines),
+       * which could be from either a previous line (if there were
+       * no BBs on this line), or from this line (if all our BB
+       * counts were compressed out because they were identical).
+       */
+
+      if (bb_annotate_all_lines && p == tmpbuf)
+       {
+         sprintf (p, "%lu", last_count);
+         p += strlen (p);
+         ncalls = last_count;
+         ncalls_set = 1;
+       }
+
+      if (! ncalls_set)
+       {
+         int c;
+
+         for (c = 0; c < width; c++)
+           buf[c] = ' ';
+         buf[width] = '\0';
+         return;
+       }
+
+      ++num_lines_executed;
+
+      if (ncalls < bb_min_calls)
+       {
+         strcpy (tmpbuf, "#####");
+         p = tmpbuf + 5;
+       }
+
+      strcpy (p, " -> ");
+      p += 4;
+
+      len = p - tmpbuf;
+      if (len >= width)
+       {
+         strncpy (buf, tmpbuf, width);
+         buf[width] = '\0';
+       }
+      else
+       {
+         int c;
+
+         strcpy (buf + width - len, tmpbuf);
+         for (c = 0; c < width - len; ++c)
+           buf[c] = ' ';
+       }
+    }
+}
+
+/*
+ * Annotate the files named in SOURCE_FILES with basic-block statistics
+ * (execution counts).  After each source files, a few statistics
+ * regarding that source file are printed.
+ */
+void
+DEFUN_VOID (print_annotated_source)
+{
+  Sym *sym, *line_stats, *new_line;
+  Source_File *sf;
+  int i, table_len;
+  FILE *ofp;
+
+  /*
+   * Find maximum line number for each source file that user is
+   * interested in:
+   */
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      /*
+       * Accept symbol if it's file is known, its line number is
+       * bigger than anything we have seen for that file so far and
+       * if it's in the INCL_ANNO table or there is no INCL_ANNO
+       * table and it does not appear in the EXCL_ANNO table.
+       */
+      if (sym->file && sym->line_num > sym->file->num_lines
+         && (sym_lookup (&syms[INCL_ANNO], sym->addr)
+             || (syms[INCL_ANNO].len == 0
+                 && !sym_lookup (&syms[EXCL_ANNO], sym->addr))))
+       {
+         sym->file->num_lines = sym->line_num;
+       }
+    }
+
+  /* allocate line descriptors: */
+
+  for (sf = first_src_file; sf; sf = sf->next)
+    {
+      if (sf->num_lines > 0)
+       {
+         sf->line = (void *) xmalloc (sf->num_lines * sizeof (sf->line[0]));
+         memset (sf->line, 0, sf->num_lines * sizeof (sf->line[0]));
+       }
+    }
+
+  /* count executions per line: */
+
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      if (sym->file && sym->file->num_lines
+         && (sym_lookup (&syms[INCL_ANNO], sym->addr)
+             || (syms[INCL_ANNO].len == 0
+                 && !sym_lookup (&syms[EXCL_ANNO], sym->addr))))
+       {
+         sym->file->ncalls += sym->ncalls;
+         line_stats = sym->file->line[sym->line_num - 1];
+         if (!line_stats)
+           {
+             /* common case has at most one basic-block per source line: */
+             sym->file->line[sym->line_num - 1] = sym;
+           }
+         else if (!line_stats->addr)
+           {
+             /* sym is the 3rd .. nth basic block for this line: */
+             line_stats->ncalls += sym->ncalls;
+           }
+         else
+           {
+             /* sym is the second basic block for this line */
+             new_line = (Sym *) xmalloc (sizeof (*new_line));
+             *new_line = *line_stats;
+             new_line->addr = 0;
+             new_line->ncalls += sym->ncalls;
+             sym->file->line[sym->line_num - 1] = new_line;
+           }
+       }
+    }
+
+  /* plod over source files, annotating them: */
+
+  for (sf = first_src_file; sf; sf = sf->next)
+    {
+      if (!sf->num_lines || (ignore_zeros && sf->ncalls == 0))
+       {
+         continue;
+       }
+
+      num_executable_lines = num_lines_executed = 0;
+      ofp = annotate_source (sf, 16, annotate_with_count, sf);
+      if (!ofp)
+       {
+         continue;
+       }
+
+      if (bb_table_length > 0)
+       {
+         fprintf (ofp, _("\n\nTop %d Lines:\n\n     Line      Count\n\n"),
+                  bb_table_length);
+
+         /* abuse line arrays---it's not needed anymore: */
+         qsort (sf->line, sf->num_lines, sizeof (sf->line[0]), cmp_ncalls);
+         table_len = bb_table_length;
+         if (table_len > sf->num_lines)
+           {
+             table_len = sf->num_lines;
+           }
+         for (i = 0; i < table_len; ++i)
+           {
+             sym = sf->line[i];
+             if (!sym || sym->ncalls == 0)
+               {
+                 break;
+               }
+             fprintf (ofp, "%9d %10lu\n", sym->line_num, sym->ncalls);
+           }
+       }
+
+      free (sf->line);
+      sf->line = 0;
+
+      fprintf (ofp, _("\nExecution Summary:\n\n"));
+      fprintf (ofp, _("%9ld   Executable lines in this file\n"),
+              num_executable_lines);
+      fprintf (ofp, _("%9ld   Lines executed\n"), num_lines_executed);
+      fprintf (ofp, _("%9.2f   Percent of the file executed\n"),
+              num_executable_lines
+              ? 100.0 * num_lines_executed / (double) num_executable_lines
+              : 100.0);
+      fprintf (ofp, _("\n%9lu   Total number of line executions\n"),
+              sf->ncalls);
+      fprintf (ofp, _("%9.2f   Average executions per line\n"),
+              num_executable_lines
+              ? (double) sf->ncalls / (double) num_executable_lines
+              : 0.0);
+      if (ofp != stdout)
+       {
+         fclose (ofp);
+       }
+    }
+}
diff --git a/gprof/basic_blocks.h b/gprof/basic_blocks.h
new file mode 100644 (file)
index 0000000..923eca1
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef basic_blocks_h
+#define basic_blocks_h
+
+#include <stdio.h>
+#include "gprof.h"
+#include "source.h"
+#include "symtab.h"
+
+/*
+ * Options:
+ */
+extern bool bb_annotate_all_lines;     /* force annotation of all lines? */
+extern int bb_table_length;            /* length of most-used bb table */
+extern unsigned long bb_min_calls;     /* minimum execution count */
+
+extern void bb_read_rec PARAMS ((FILE * ifp, const char *filename));
+extern void bb_write_blocks PARAMS ((FILE * ofp, const char *filename));
+extern void bb_create_syms PARAMS ((void));
+
+extern void print_annotated_source PARAMS ((void));
+extern void print_exec_counts PARAMS ((void));
+
+#endif /* basic_blocks_h */
diff --git a/gprof/bb_exit_func.c b/gprof/bb_exit_func.c
new file mode 100644 (file)
index 0000000..8133215
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1994 David Mosberger-Tang.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * __bb_exit_func() dumps all the basic-block statistics linked into
+ * the bb_head chain to .d files.
+ */
+#include <stdio.h>
+#include <strings.h>
+#include "bfd.h"
+#include "gmon_out.h"
+
+/* structure emitted by -a */
+struct bb {
+    long               zero_word;
+    const char         *filename;
+    long               *counts;
+    long               ncounts;
+    struct bb          *next;
+    const unsigned long        *addresses;
+};
+
+struct bb *__bb_head = (struct bb *)0;
+
+
+void
+__bb_exit_func (void)
+{
+    const int version = GMON_VERSION;
+    struct gmon_hdr ghdr;
+    struct bb *ptr;
+    FILE *fp;
+    /*
+     * GEN_GMON_CNT_FILE should be defined on systems with mcleanup()
+     * functions that do not write basic-block to gmon.out.  In such
+     * cases profiling with "-pg -a" would result in a gmon.out file
+     * without basic-block info (because the file written here would
+     * be overwritten.  Thus, a separate file is generated instead.
+     * The two files can easily be combined by specifying them
+     * on gprof's command line (and possibly generating a gmon.sum
+     * file with "gprof -s").
+     */
+#ifndef GEN_GMON_CNT_FILE
+#   define OUT_NAME    "gmon.out"
+#else
+#   define OUT_NAME    "gmon.cnt"
+#endif
+    fp = fopen(OUT_NAME, "wb");
+    if (!fp) {
+       perror(OUT_NAME);
+       return;
+    } /* if */
+    memcpy(&ghdr.cookie[0], GMON_MAGIC, 4);
+    memcpy(&ghdr.version, &version, sizeof(version));
+    fwrite(&ghdr, sizeof(ghdr), 1, fp);
+
+    for (ptr = __bb_head; ptr != 0; ptr = ptr->next) {
+       u_int ncounts = ptr->ncounts;
+       u_char tag;
+       u_int i;
+
+       tag = GMON_TAG_BB_COUNT;
+       fwrite(&tag, sizeof(tag), 1, fp);
+       fwrite(&ncounts, sizeof(ncounts), 1, fp);
+
+       for (i = 0; i < ncounts; ++i) {
+           fwrite(&ptr->addresses[i], sizeof(ptr->addresses[0]), 1, fp);
+           fwrite(&ptr->counts[i], sizeof(ptr->counts[0]), 1, fp);
+       } /* for */
+    } /* for */
+    fclose (fp);
+} /* __bb_exit_func */
+
+                       /*** end of __bb_exit_func.c ***/
diff --git a/gprof/bbconv.pl b/gprof/bbconv.pl
new file mode 100755 (executable)
index 0000000..7312f51
--- /dev/null
@@ -0,0 +1,36 @@
+#! /usr/bin/perl
+
+# This script converts a "bb.out" file into a format
+# suitable for processing by gprof
+
+# Write a new-style gmon header
+
+print pack("A4Ix12", "gmon", 1);
+
+
+# The input file format contains header lines and data lines.
+# Header lines contain a count of how many data lines follow before
+# the next header line.  $blockcount is set to the count that
+# appears in each header line, then decremented at each data line.
+# $blockcount should always be zero at the start of a header line,
+# and should never be zero at the start of a data line.
+
+$blockcount=0;
+
+while (<>) {
+    if (/^File .*, ([0-9]+) basic blocks/) {
+       print STDERR "Miscount: line $.\n" if ($blockcount != 0);
+       $blockcount = $1;
+
+       print pack("cI", 2, $blockcount);
+    }
+    if (/Block.*executed([ 0-9]+) time.* address= 0x([0-9a-fA-F]*)/) {
+       print STDERR "Miscount: line $.\n" if ($blockcount == 0);
+       $blockcount-- if ($blockcount > 0);
+
+       $count = $1;
+       $addr = hex $2;
+
+       print pack("II",$addr,$count);
+    }
+}
diff --git a/gprof/bsd_callg_bl.m b/gprof/bsd_callg_bl.m
new file mode 100644 (file)
index 0000000..533c96c
--- /dev/null
@@ -0,0 +1,108 @@
+
+
+
+call graph profile:
+          The sum of self and descendents is the major sort
+          for this listing.
+
+          function entries:
+
+index     the index of the function in the call graph
+          listing, as an aid to locating it (see below).
+
+%time     the percentage of the total time of the program
+          accounted for by this function and its
+          descendents.
+
+self      the number of seconds spent in this function
+          itself.
+
+descendents
+          the number of seconds spent in the descendents of
+          this function on behalf of this function.
+
+called    the number of times this function is called (other
+          than recursive calls).
+
+self      the number of times this function calls itself
+          recursively.
+
+name      the name of the function, with an indication of
+          its membership in a cycle, if any.
+
+index     the index of the function in the call graph
+          listing, as an aid to locating it.
+
+
+
+          parent listings:
+
+self*     the number of seconds of this function's self time
+          which is due to calls from this parent.
+
+descendents*
+          the number of seconds of this function's
+          descendent time which is due to calls from this
+          parent.
+
+called**  the number of times this function is called by
+          this parent.  This is the numerator of the
+          fraction which divides up the function's time to
+          its parents.
+
+total*    the number of times this function was called by
+          all of its parents.  This is the denominator of
+          the propagation fraction.
+
+parents   the name of this parent, with an indication of the
+          parent's membership in a cycle, if any.
+
+index     the index of this parent in the call graph
+          listing, as an aid in locating it.
+
+
+
+          children listings:
+
+self*     the number of seconds of this child's self time
+          which is due to being called by this function.
+
+descendent*
+          the number of seconds of this child's descendent's
+          time which is due to being called by this
+          function.
+
+called**  the number of times this child is called by this
+          function.  This is the numerator of the
+          propagation fraction for this child.
+
+total*    the number of times this child is called by all
+          functions.  This is the denominator of the
+          propagation fraction.
+
+children  the name of this child, and an indication of its
+          membership in a cycle, if any.
+
+index     the index of this child in the call graph listing,
+          as an aid to locating it.
+
+
+
+          * these fields are omitted for parents (or
+          children) in the same cycle as the function.  If
+          the function (or child) is a member of a cycle,
+          the propagated times and propagation denominator
+          represent the self time and descendent time of the
+          cycle as a whole.
+
+          ** static-only parents and children are indicated
+          by a call count of 0.
+
+
+
+          cycle listings:
+          the cycle as a whole is listed with the same
+          fields as a function entry.  Below it are listed
+          the members of the cycle, and their contributions
+          to the time and call counts of the cycle.
+\f
diff --git a/gprof/call_graph.c b/gprof/call_graph.c
new file mode 100644 (file)
index 0000000..8f12cbd
--- /dev/null
@@ -0,0 +1,116 @@
+#include "cg_arcs.h"
+#include "call_graph.h"
+#include "corefile.h"
+#include "gmon_io.h"
+#include "gmon_out.h"
+#include "symtab.h"
+#include "sym_ids.h"
+
+extern void
+DEFUN (cg_tally, (from_pc, self_pc, count),
+       bfd_vma from_pc AND bfd_vma self_pc AND unsigned long count)
+{
+  Sym *parent;
+  Sym *child;
+
+  parent = sym_lookup (&symtab, from_pc);
+  child = sym_lookup (&symtab, self_pc);
+
+  if (child == NULL || parent == NULL)
+    return;
+
+  /* If we're doing line-by-line profiling, both the parent and the
+     child will probably point to line symbols instead of function
+     symbols.  For the parent this is fine, since this identifies the
+     line number in the calling routing, but the child should always
+     point to a function entry point, so we back up in the symbol
+     table until we find it.
+   
+     For normal profiling, is_func will be set on all symbols, so this
+     code will do nothing.  */
+
+  while (child >= symtab.base && ! child->is_func)
+    --child;
+
+  if (child < symtab.base)
+    return;
+
+  /*
+   * Keep arc if it is on INCL_ARCS table or if the INCL_ARCS table
+   * is empty and it is not in the EXCL_ARCS table.
+   */
+  if (sym_id_arc_is_present (&syms[INCL_ARCS], parent, child)
+      || (syms[INCL_ARCS].len == 0
+         && !sym_id_arc_is_present (&syms[EXCL_ARCS], parent, child)))
+    {
+      child->ncalls += count;
+      DBG (TALLYDEBUG,
+          printf (_("[cg_tally] arc from %s to %s traversed %lu times\n"),
+                  parent->name, child->name, count));
+      arc_add (parent, child, count);
+    }
+}
+
+
+/*
+ * Read a record from file IFP describing an arc in the function
+ * call-graph and the count of how many times the arc has been
+ * traversed.  FILENAME is the name of file IFP and is provided
+ * for formatting error-messages only.
+ */
+void
+DEFUN (cg_read_rec, (ifp, filename), FILE * ifp AND CONST char *filename)
+{
+  bfd_vma from_pc, self_pc;
+  struct gmon_cg_arc_record arc;
+  unsigned long count;
+
+  if (fread (&arc, sizeof (arc), 1, ifp) != 1)
+    {
+      fprintf (stderr, _("%s: %s: unexpected end of file\n"),
+              whoami, filename);
+      done (1);
+    }
+  from_pc = get_vma (core_bfd, (bfd_byte *) arc.from_pc);
+  self_pc = get_vma (core_bfd, (bfd_byte *) arc.self_pc);
+  count = bfd_get_32 (core_bfd, (bfd_byte *) arc.count);
+  DBG (SAMPLEDEBUG,
+       printf ("[cg_read_rec] frompc 0x%lx selfpc 0x%lx count %lu\n",
+              from_pc, self_pc, count));
+  /* add this arc: */
+  cg_tally (from_pc, self_pc, count);
+}
+
+
+/*
+ * Write all the arcs in the call-graph to file OFP.  FILENAME is
+ * the name of OFP and is provided for formatting error-messages
+ * only.
+ */
+void
+DEFUN (cg_write_arcs, (ofp, filename), FILE * ofp AND const char *filename)
+{
+  const unsigned char tag = GMON_TAG_CG_ARC;
+  struct gmon_cg_arc_record raw_arc;
+  Arc *arc;
+  Sym *sym;
+
+  for (sym = symtab.base; sym < symtab.limit; sym++)
+    {
+      for (arc = sym->cg.children; arc; arc = arc->next_child)
+       {
+         put_vma (core_bfd, arc->parent->addr, (bfd_byte *) raw_arc.from_pc);
+         put_vma (core_bfd, arc->child->addr, (bfd_byte *) raw_arc.self_pc);
+         bfd_put_32 (core_bfd, arc->count, (bfd_byte *) raw_arc.count);
+         if (fwrite (&tag, sizeof (tag), 1, ofp) != 1
+             || fwrite (&raw_arc, sizeof (raw_arc), 1, ofp) != 1)
+           {
+             perror (filename);
+             done (1);
+           }
+         DBG (SAMPLEDEBUG,
+            printf ("[cg_write_arcs] frompc 0x%lx selfpc 0x%lx count %lu\n",
+                    arc->parent->addr, arc->child->addr, arc->count));
+       }
+    }
+}
diff --git a/gprof/call_graph.h b/gprof/call_graph.h
new file mode 100644 (file)
index 0000000..be5139b
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef call_graph_h
+#define call_graph_h
+
+#include <stdio.h>
+#include "gprof.h"
+#include "symtab.h"
+
+extern void cg_tally PARAMS ((bfd_vma from_pc, bfd_vma self_pc,
+                             unsigned long count));
+extern void cg_read_rec PARAMS ((FILE * ifp, const char *filename));
+extern void cg_write_arcs PARAMS ((FILE * ofp, const char *filename));
+
+#endif /* call_graph_h */
diff --git a/gprof/cg_arcs.c b/gprof/cg_arcs.c
new file mode 100644 (file)
index 0000000..0702317
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "libiberty.h"
+#include "gprof.h"
+#include "call_graph.h"
+#include "cg_arcs.h"
+#include "cg_dfn.h"
+#include "cg_print.h"
+#include "utils.h"
+#include "sym_ids.h"
+
+Sym *cycle_header;
+unsigned int num_cycles;
+Arc **arcs;
+unsigned int numarcs;
+
+/*
+ * Return TRUE iff PARENT has an arc to covers the address
+ * range covered by CHILD.
+ */
+Arc *
+DEFUN (arc_lookup, (parent, child), Sym * parent AND Sym * child)
+{
+  Arc *arc;
+
+  if (!parent || !child)
+    {
+      printf ("[arc_lookup] parent == 0 || child == 0\n");
+      return 0;
+    }
+  DBG (LOOKUPDEBUG, printf ("[arc_lookup] parent %s child %s\n",
+                           parent->name, child->name));
+  for (arc = parent->cg.children; arc; arc = arc->next_child)
+    {
+      DBG (LOOKUPDEBUG, printf ("[arc_lookup]\t parent %s child %s\n",
+                               arc->parent->name, arc->child->name));
+      if (child->addr >= arc->child->addr
+         && child->end_addr <= arc->child->end_addr)
+       {
+         return arc;
+       }
+    }
+  return 0;
+}
+
+
+/*
+ * Add (or just increment) an arc:
+ */
+void
+DEFUN (arc_add, (parent, child, count),
+       Sym * parent AND Sym * child AND unsigned long count)
+{
+  static unsigned int maxarcs = 0;
+  Arc *arc, **newarcs;
+
+  DBG (TALLYDEBUG, printf ("[arc_add] %lu arcs from %s to %s\n",
+                          count, parent->name, child->name));
+  arc = arc_lookup (parent, child);
+  if (arc)
+    {
+      /*
+       * A hit: just increment the count.
+       */
+      DBG (TALLYDEBUG, printf ("[tally] hit %lu += %lu\n",
+                              arc->count, count));
+      arc->count += count;
+      return;
+    }
+  arc = (Arc *) xmalloc (sizeof (*arc));
+  memset (arc, 0, sizeof (*arc));
+  arc->parent = parent;
+  arc->child = child;
+  arc->count = count;
+
+  /* If this isn't an arc for a recursive call to parent, then add it
+     to the array of arcs.  */
+  if (parent != child)
+    {
+      /* If we've exhausted space in our current array, get a new one
+        and copy the contents.   We might want to throttle the doubling
+        factor one day.  */
+      if (numarcs == maxarcs)
+       {
+         /* Determine how much space we want to allocate.  */
+         if (maxarcs == 0)
+           maxarcs = 1;
+         maxarcs *= 2;
+       
+         /* Allocate the new array.  */
+         newarcs = (Arc **)xmalloc(sizeof (Arc *) * maxarcs);
+
+         /* Copy the old array's contents into the new array.  */
+         memcpy (newarcs, arcs, numarcs * sizeof (Arc *));
+
+         /* Free up the old array.  */
+         free (arcs);
+
+         /* And make the new array be the current array.  */
+         arcs = newarcs;
+       }
+
+      /* Place this arc in the arc array.  */
+      arcs[numarcs++] = arc;
+    }
+
+  /* prepend this child to the children of this parent: */
+  arc->next_child = parent->cg.children;
+  parent->cg.children = arc;
+
+  /* prepend this parent to the parents of this child: */
+  arc->next_parent = child->cg.parents;
+  child->cg.parents = arc;
+}
+
+
+static int
+DEFUN (cmp_topo, (lp, rp), const PTR lp AND const PTR rp)
+{
+  const Sym *left = *(const Sym **) lp;
+  const Sym *right = *(const Sym **) rp;
+
+  return left->cg.top_order - right->cg.top_order;
+}
+
+
+static void
+DEFUN (propagate_time, (parent), Sym * parent)
+{
+  Arc *arc;
+  Sym *child;
+  double share, prop_share;
+
+  if (parent->cg.prop.fract == 0.0)
+    {
+      return;
+    }
+
+  /* gather time from children of this parent: */
+
+  for (arc = parent->cg.children; arc; arc = arc->next_child)
+    {
+      child = arc->child;
+      if (arc->count == 0 || child == parent || child->cg.prop.fract == 0)
+       {
+         continue;
+       }
+      if (child->cg.cyc.head != child)
+       {
+         if (parent->cg.cyc.num == child->cg.cyc.num)
+           {
+             continue;
+           }
+         if (parent->cg.top_order <= child->cg.top_order)
+           {
+             fprintf (stderr, "[propagate] toporder botches\n");
+           }
+         child = child->cg.cyc.head;
+       }
+      else
+       {
+         if (parent->cg.top_order <= child->cg.top_order)
+           {
+             fprintf (stderr, "[propagate] toporder botches\n");
+             continue;
+           }
+       }
+      if (child->ncalls == 0)
+       {
+         continue;
+       }
+
+      /* distribute time for this arc: */
+      arc->time = child->hist.time * (((double) arc->count)
+                                     / ((double) child->ncalls));
+      arc->child_time = child->cg.child_time
+       * (((double) arc->count) / ((double) child->ncalls));
+      share = arc->time + arc->child_time;
+      parent->cg.child_time += share;
+
+      /* (1 - cg.prop.fract) gets lost along the way: */
+      prop_share = parent->cg.prop.fract * share;
+
+      /* fix things for printing: */
+      parent->cg.prop.child += prop_share;
+      arc->time *= parent->cg.prop.fract;
+      arc->child_time *= parent->cg.prop.fract;
+
+      /* add this share to the parent's cycle header, if any: */
+      if (parent->cg.cyc.head != parent)
+       {
+         parent->cg.cyc.head->cg.child_time += share;
+         parent->cg.cyc.head->cg.prop.child += prop_share;
+       }
+      DBG (PROPDEBUG,
+          printf ("[prop_time] child \t");
+          print_name (child);
+          printf (" with %f %f %lu/%lu\n", child->hist.time,
+                  child->cg.child_time, arc->count, child->ncalls);
+          printf ("[prop_time] parent\t");
+          print_name (parent);
+          printf ("\n[prop_time] share %f\n", share));
+    }
+}
+
+
+/*
+ * Compute the time of a cycle as the sum of the times of all
+ * its members.
+ */
+static void
+DEFUN_VOID (cycle_time)
+{
+  Sym *member, *cyc;
+
+  for (cyc = &cycle_header[1]; cyc <= &cycle_header[num_cycles]; ++cyc)
+    {
+      for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
+       {
+         if (member->cg.prop.fract == 0.0)
+           {
+             /*
+              * All members have the same propfraction except those
+              * that were excluded with -E.
+              */
+             continue;
+           }
+         cyc->hist.time += member->hist.time;
+       }
+      cyc->cg.prop.self = cyc->cg.prop.fract * cyc->hist.time;
+    }
+}
+
+
+static void
+DEFUN_VOID (cycle_link)
+{
+  Sym *sym, *cyc, *member;
+  Arc *arc;
+  int num;
+
+  /* count the number of cycles, and initialize the cycle lists: */
+
+  num_cycles = 0;
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      /* this is how you find unattached cycles: */
+      if (sym->cg.cyc.head == sym && sym->cg.cyc.next)
+       {
+         ++num_cycles;
+       }
+    }
+
+  /*
+   * cycle_header is indexed by cycle number: i.e. it is origin 1,
+   * not origin 0.
+   */
+  cycle_header = (Sym *) xmalloc ((num_cycles + 1) * sizeof (Sym));
+
+  /*
+   * Now link cycles to true cycle-heads, number them, accumulate
+   * the data for the cycle.
+   */
+  num = 0;
+  cyc = cycle_header;
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      if (!(sym->cg.cyc.head == sym && sym->cg.cyc.next != 0))
+       {
+         continue;
+       }
+      ++num;
+      ++cyc;
+      sym_init (cyc);
+      cyc->cg.print_flag = TRUE;       /* should this be printed? */
+      cyc->cg.top_order = DFN_NAN;     /* graph call chain top-sort order */
+      cyc->cg.cyc.num = num;   /* internal number of cycle on */
+      cyc->cg.cyc.head = cyc;  /* pointer to head of cycle */
+      cyc->cg.cyc.next = sym;  /* pointer to next member of cycle */
+      DBG (CYCLEDEBUG, printf ("[cycle_link] ");
+          print_name (sym);
+          printf (" is the head of cycle %d\n", num));
+
+      /* link members to cycle header: */
+      for (member = sym; member; member = member->cg.cyc.next)
+       {
+         member->cg.cyc.num = num;
+         member->cg.cyc.head = cyc;
+       }
+
+      /*
+       * Count calls from outside the cycle and those among cycle
+       * members:
+       */
+      for (member = sym; member; member = member->cg.cyc.next)
+       {
+         for (arc = member->cg.parents; arc; arc = arc->next_parent)
+           {
+             if (arc->parent == member)
+               {
+                 continue;
+               }
+             if (arc->parent->cg.cyc.num == num)
+               {
+                 cyc->cg.self_calls += arc->count;
+               }
+             else
+               {
+                 cyc->ncalls += arc->count;
+               }
+           }
+       }
+    }
+}
+
+
+/*
+ * Check if any parent of this child (or outside parents of this
+ * cycle) have their print flags on and set the print flag of the
+ * child (cycle) appropriately.  Similarly, deal with propagation
+ * fractions from parents.
+ */
+static void
+DEFUN (inherit_flags, (child), Sym * child)
+{
+  Sym *head, *parent, *member;
+  Arc *arc;
+
+  head = child->cg.cyc.head;
+  if (child == head)
+    {
+      /* just a regular child, check its parents: */
+      child->cg.print_flag = FALSE;
+      child->cg.prop.fract = 0.0;
+      for (arc = child->cg.parents; arc; arc = arc->next_parent)
+       {
+         parent = arc->parent;
+         if (child == parent)
+           {
+             continue;
+           }
+         child->cg.print_flag |= parent->cg.print_flag;
+         /*
+          * If the child was never actually called (e.g., this arc
+          * is static (and all others are, too)) no time propagates
+          * along this arc.
+          */
+         if (child->ncalls != 0)
+           {
+             child->cg.prop.fract += parent->cg.prop.fract
+               * (((double) arc->count) / ((double) child->ncalls));
+           }
+       }
+    }
+  else
+    {
+      /*
+       * Its a member of a cycle, look at all parents from outside
+       * the cycle.
+       */
+      head->cg.print_flag = FALSE;
+      head->cg.prop.fract = 0.0;
+      for (member = head->cg.cyc.next; member; member = member->cg.cyc.next)
+       {
+         for (arc = member->cg.parents; arc; arc = arc->next_parent)
+           {
+             if (arc->parent->cg.cyc.head == head)
+               {
+                 continue;
+               }
+             parent = arc->parent;
+             head->cg.print_flag |= parent->cg.print_flag;
+             /*
+              * If the cycle was never actually called (e.g. this
+              * arc is static (and all others are, too)) no time
+              * propagates along this arc.
+              */
+             if (head->ncalls != 0)
+               {
+                 head->cg.prop.fract += parent->cg.prop.fract
+                   * (((double) arc->count) / ((double) head->ncalls));
+               }
+           }
+       }
+      for (member = head; member; member = member->cg.cyc.next)
+       {
+         member->cg.print_flag = head->cg.print_flag;
+         member->cg.prop.fract = head->cg.prop.fract;
+       }
+    }
+}
+
+
+/*
+ * In one top-to-bottom pass over the topologically sorted symbols
+ * propagate:
+ *      cg.print_flag as the union of parents' print_flags
+ *      propfraction as the sum of fractional parents' propfractions
+ * and while we're here, sum time for functions.
+ */
+static void
+DEFUN (propagate_flags, (symbols), Sym ** symbols)
+{
+  int index;
+  Sym *old_head, *child;
+
+  old_head = 0;
+  for (index = symtab.len - 1; index >= 0; --index)
+    {
+      child = symbols[index];
+      /*
+       * If we haven't done this function or cycle, inherit things
+       * from parent.  This way, we are linear in the number of arcs
+       * since we do all members of a cycle (and the cycle itself)
+       * as we hit the first member of the cycle.
+       */
+      if (child->cg.cyc.head != old_head)
+       {
+         old_head = child->cg.cyc.head;
+         inherit_flags (child);
+       }
+      DBG (PROPDEBUG,
+          printf ("[prop_flags] ");
+          print_name (child);
+          printf ("inherits print-flag %d and prop-fract %f\n",
+                  child->cg.print_flag, child->cg.prop.fract));
+      if (!child->cg.print_flag)
+       {
+         /*
+          * Printflag is off. It gets turned on by being in the
+          * INCL_GRAPH table, or there being an empty INCL_GRAPH
+          * table and not being in the EXCL_GRAPH table.
+          */
+         if (sym_lookup (&syms[INCL_GRAPH], child->addr)
+             || (syms[INCL_GRAPH].len == 0
+                 && !sym_lookup (&syms[EXCL_GRAPH], child->addr)))
+           {
+             child->cg.print_flag = TRUE;
+           }
+       }
+      else
+       {
+         /*
+          * This function has printing parents: maybe someone wants
+          * to shut it up by putting it in the EXCL_GRAPH table.
+          * (But favor INCL_GRAPH over EXCL_GRAPH.)
+          */
+         if (!sym_lookup (&syms[INCL_GRAPH], child->addr)
+             && sym_lookup (&syms[EXCL_GRAPH], child->addr))
+           {
+             child->cg.print_flag = FALSE;
+           }
+       }
+      if (child->cg.prop.fract == 0.0)
+       {
+         /*
+          * No parents to pass time to.  Collect time from children
+          * if its in the INCL_TIME table, or there is an empty
+          * INCL_TIME table and its not in the EXCL_TIME table.
+          */
+         if (sym_lookup (&syms[INCL_TIME], child->addr)
+             || (syms[INCL_TIME].len == 0
+                 && !sym_lookup (&syms[EXCL_TIME], child->addr)))
+           {
+             child->cg.prop.fract = 1.0;
+           }
+       }
+      else
+       {
+         /*
+          * It has parents to pass time to, but maybe someone wants
+          * to shut it up by puttting it in the EXCL_TIME table.
+          * (But favor being in INCL_TIME tabe over being in
+          * EXCL_TIME table.)
+          */
+         if (!sym_lookup (&syms[INCL_TIME], child->addr)
+             && sym_lookup (&syms[EXCL_TIME], child->addr))
+           {
+             child->cg.prop.fract = 0.0;
+           }
+       }
+      child->cg.prop.self = child->hist.time * child->cg.prop.fract;
+      print_time += child->cg.prop.self;
+      DBG (PROPDEBUG,
+          printf ("[prop_flags] ");
+          print_name (child);
+          printf (" ends up with printflag %d and prop-fract %f\n",
+                  child->cg.print_flag, child->cg.prop.fract);
+          printf ("[prop_flags] time %f propself %f print_time %f\n",
+                  child->hist.time, child->cg.prop.self, print_time));
+    }
+}
+
+
+/*
+ * Compare by decreasing propagated time.  If times are equal, but one
+ * is a cycle header, say that's first (e.g. less, i.e. -1).  If one's
+ * name doesn't have an underscore and the other does, say that one is
+ * first.  All else being equal, compare by names.
+ */
+static int
+DEFUN (cmp_total, (lp, rp), const PTR lp AND const PTR rp)
+{
+  const Sym *left = *(const Sym **) lp;
+  const Sym *right = *(const Sym **) rp;
+  double diff;
+
+  diff = (left->cg.prop.self + left->cg.prop.child)
+    - (right->cg.prop.self + right->cg.prop.child);
+  if (diff < 0.0)
+    {
+      return 1;
+    }
+  if (diff > 0.0)
+    {
+      return -1;
+    }
+  if (!left->name && left->cg.cyc.num != 0)
+    {
+      return -1;
+    }
+  if (!right->name && right->cg.cyc.num != 0)
+    {
+      return 1;
+    }
+  if (!left->name)
+    {
+      return -1;
+    }
+  if (!right->name)
+    {
+      return 1;
+    }
+  if (left->name[0] != '_' && right->name[0] == '_')
+    {
+      return -1;
+    }
+  if (left->name[0] == '_' && right->name[0] != '_')
+    {
+      return 1;
+    }
+  if (left->ncalls > right->ncalls)
+    {
+      return -1;
+    }
+  if (left->ncalls < right->ncalls)
+    {
+      return 1;
+    }
+  return strcmp (left->name, right->name);
+}
+
+
+/*
+ * Topologically sort the graph (collapsing cycles), and propagates
+ * time bottom up and flags top down.
+ */
+Sym **
+DEFUN_VOID (cg_assemble)
+{
+  Sym *parent, **time_sorted_syms, **top_sorted_syms;
+  unsigned int index;
+  Arc *arc;
+
+  /*
+   * initialize various things:
+   *      zero out child times.
+   *      count self-recursive calls.
+   *      indicate that nothing is on cycles.
+   */
+  for (parent = symtab.base; parent < symtab.limit; parent++)
+    {
+      parent->cg.child_time = 0.0;
+      arc = arc_lookup (parent, parent);
+      if (arc && parent == arc->child)
+       {
+         parent->ncalls -= arc->count;
+         parent->cg.self_calls = arc->count;
+       }
+      else
+       {
+         parent->cg.self_calls = 0;
+       }
+      parent->cg.prop.fract = 0.0;
+      parent->cg.prop.self = 0.0;
+      parent->cg.prop.child = 0.0;
+      parent->cg.print_flag = FALSE;
+      parent->cg.top_order = DFN_NAN;
+      parent->cg.cyc.num = 0;
+      parent->cg.cyc.head = parent;
+      parent->cg.cyc.next = 0;
+      if (ignore_direct_calls)
+       {
+         find_call (parent, parent->addr, (parent + 1)->addr);
+       }
+    }
+  /*
+   * Topologically order things.  If any node is unnumbered, number
+   * it and any of its descendents.
+   */
+  for (parent = symtab.base; parent < symtab.limit; parent++)
+    {
+      if (parent->cg.top_order == DFN_NAN)
+       {
+         cg_dfn (parent);
+       }
+    }
+
+  /* link together nodes on the same cycle: */
+  cycle_link ();
+
+  /* sort the symbol table in reverse topological order: */
+  top_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+  for (index = 0; index < symtab.len; ++index)
+    {
+      top_sorted_syms[index] = &symtab.base[index];
+    }
+  qsort (top_sorted_syms, symtab.len, sizeof (Sym *), cmp_topo);
+  DBG (DFNDEBUG,
+       printf ("[cg_assemble] topological sort listing\n");
+       for (index = 0; index < symtab.len; ++index)
+       {
+       printf ("[cg_assemble] ");
+       printf ("%d:", top_sorted_syms[index]->cg.top_order);
+       print_name (top_sorted_syms[index]);
+       printf ("\n");
+       }
+  );
+  /*
+   * Starting from the topological top, propagate print flags to
+   * children.  also, calculate propagation fractions.  this happens
+   * before time propagation since time propagation uses the
+   * fractions.
+   */
+  propagate_flags (top_sorted_syms);
+
+  /*
+   * Starting from the topological bottom, propogate children times
+   * up to parents.
+   */
+  cycle_time ();
+  for (index = 0; index < symtab.len; ++index)
+    {
+      propagate_time (top_sorted_syms[index]);
+    }
+
+  free (top_sorted_syms);
+
+  /*
+   * Now, sort by CG.PROP.SELF + CG.PROP.CHILD.  Sorting both the regular
+   * function names and cycle headers.
+   */
+  time_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
+  for (index = 0; index < symtab.len; index++)
+    {
+      time_sorted_syms[index] = &symtab.base[index];
+    }
+  for (index = 1; index <= num_cycles; index++)
+    {
+      time_sorted_syms[symtab.len + index - 1] = &cycle_header[index];
+    }
+  qsort (time_sorted_syms, symtab.len + num_cycles, sizeof (Sym *),
+        cmp_total);
+  for (index = 0; index < symtab.len + num_cycles; index++)
+    {
+      time_sorted_syms[index]->cg.index = index + 1;
+    }
+  return time_sorted_syms;
+}
diff --git a/gprof/cg_arcs.h b/gprof/cg_arcs.h
new file mode 100644 (file)
index 0000000..caa0197
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef cg_arcs_h
+#define cg_arcs_h
+
+#include "gprof.h"
+#include "symtab.h"
+
+/*
+ * Arc structure for call-graph.
+ *
+ * With pointers to the symbols of the parent and the child, a count
+ * of how many times this arc was traversed, and pointers to the next
+ * parent of this child and the next child of this parent.
+ */
+typedef struct arc
+  {
+    Sym *parent;               /* source vertice of arc */
+    Sym *child;                        /* dest vertice of arc */
+    unsigned long count;       /* # of calls from parent to child */
+    double time;               /* time inherited along arc */
+    double child_time;         /* child-time inherited along arc */
+    struct arc *next_parent;   /* next parent of CHILD */
+    struct arc *next_child;    /* next child of PARENT */
+    int has_been_placed;       /* have this arc's functions been placed? */
+  }
+Arc;
+
+extern unsigned int num_cycles;        /* number of cycles discovered */
+extern Sym *cycle_header;      /* cycle headers */
+
+extern void arc_add PARAMS ((Sym * parent, Sym * child, unsigned long count));
+extern Arc *arc_lookup PARAMS ((Sym * parent, Sym * child));
+extern Sym **cg_assemble PARAMS ((void));
+extern Arc **arcs;
+extern unsigned int numarcs;
+
+#endif /* cg_arcs_h */
diff --git a/gprof/cg_dfn.c b/gprof/cg_dfn.c
new file mode 100644 (file)
index 0000000..c9e37ab
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include <stdio.h>
+#include "gprof.h"
+#include "cg_arcs.h"
+#include "cg_dfn.h"
+#include "symtab.h"
+#include "utils.h"
+
+#define        DFN_DEPTH       100
+
+typedef struct
+  {
+    Sym *sym;
+    int cycle_top;
+  }
+DFN_Stack;
+
+DFN_Stack dfn_stack[DFN_DEPTH];
+int dfn_depth = 0;
+int dfn_counter = DFN_NAN;
+
+
+/*
+ * Is CHILD already numbered?
+ */
+static bool
+DEFUN (is_numbered, (child), Sym * child)
+{
+  return child->cg.top_order != DFN_NAN && child->cg.top_order != DFN_BUSY;
+}
+
+
+/*
+ * Is CHILD already busy?
+ */
+static bool
+DEFUN (is_busy, (child), Sym * child)
+{
+  if (child->cg.top_order == DFN_NAN)
+    {
+      return FALSE;
+    }
+  return TRUE;
+}
+
+
+/*
+ * CHILD is part of a cycle.  Find the top caller into this cycle
+ * that is not part of the cycle and make all functions in cycle
+ * members of that cycle (top caller == caller with smallest
+ * depth-first number).
+ */
+static void
+DEFUN (find_cycle, (child), Sym * child)
+{
+  Sym *head = 0;
+  Sym *tail;
+  int cycle_top;
+  int index;
+
+  for (cycle_top = dfn_depth; cycle_top > 0; --cycle_top)
+    {
+      head = dfn_stack[cycle_top].sym;
+      if (child == head)
+       {
+         break;
+       }
+      if (child->cg.cyc.head != child && child->cg.cyc.head == head)
+       {
+         break;
+       }
+    }
+  if (cycle_top <= 0)
+    {
+      fprintf (stderr, "[find_cycle] couldn't find head of cycle\n");
+      done (1);
+    }
+#ifdef DEBUG
+  if (debug_level & DFNDEBUG)
+    {
+      printf ("[find_cycle] dfn_depth %d cycle_top %d ",
+             dfn_depth, cycle_top);
+      if (head)
+       {
+         print_name (head);
+       }
+      else
+       {
+         printf ("<unknown>");
+       }
+      printf ("\n");
+    }
+#endif
+  if (cycle_top == dfn_depth)
+    {
+      /*
+       * This is previous function, e.g. this calls itself.  Sort of
+       * boring.
+       *
+       * Since we are taking out self-cycles elsewhere no need for
+       * the special case, here.
+       */
+      DBG (DFNDEBUG,
+          printf ("[find_cycle] ");
+          print_name (child);
+          printf ("\n"));
+    }
+  else
+    {
+      /*
+       * Glom intervening functions that aren't already glommed into
+       * this cycle.  Things have been glommed when their cyclehead
+       * field points to the head of the cycle they are glommed
+       * into.
+       */
+      for (tail = head; tail->cg.cyc.next; tail = tail->cg.cyc.next)
+       {
+         /* void: chase down to tail of things already glommed */
+         DBG (DFNDEBUG,
+              printf ("[find_cycle] tail ");
+              print_name (tail);
+              printf ("\n"));
+       }
+      /*
+       * If what we think is the top of the cycle has a cyclehead
+       * field, then it's not really the head of the cycle, which is
+       * really what we want.
+       */
+      if (head->cg.cyc.head != head)
+       {
+         head = head->cg.cyc.head;
+         DBG (DFNDEBUG, printf ("[find_cycle] new cyclehead ");
+              print_name (head);
+              printf ("\n"));
+       }
+      for (index = cycle_top + 1; index <= dfn_depth; ++index)
+       {
+         child = dfn_stack[index].sym;
+         if (child->cg.cyc.head == child)
+           {
+             /*
+              * Not yet glommed anywhere, glom it and fix any
+              * children it has glommed.
+              */
+             tail->cg.cyc.next = child;
+             child->cg.cyc.head = head;
+             DBG (DFNDEBUG, printf ("[find_cycle] glomming ");
+                  print_name (child);
+                  printf (" onto ");
+                  print_name (head);
+                  printf ("\n"));
+             for (tail = child; tail->cg.cyc.next; tail = tail->cg.cyc.next)
+               {
+                 tail->cg.cyc.next->cg.cyc.head = head;
+                 DBG (DFNDEBUG, printf ("[find_cycle] and its tail ");
+                      print_name (tail->cg.cyc.next);
+                      printf (" onto ");
+                      print_name (head);
+                      printf ("\n"));
+               }
+           }
+         else if (child->cg.cyc.head != head /* firewall */ )
+           {
+             fprintf (stderr, "[find_cycle] glommed, but not to head\n");
+             done (1);
+           }
+       }
+    }
+}
+
+
+/*
+ * Prepare for visiting the children of PARENT.  Push a parent onto
+ * the stack and mark it busy.
+ */
+static void
+DEFUN (pre_visit, (parent), Sym * parent)
+{
+  ++dfn_depth;
+  if (dfn_depth >= DFN_DEPTH)
+    {
+      fprintf (stderr, "[pre_visit] dfn_stack overflow\n");
+      done (1);
+    }
+  dfn_stack[dfn_depth].sym = parent;
+  dfn_stack[dfn_depth].cycle_top = dfn_depth;
+  parent->cg.top_order = DFN_BUSY;
+  DBG (DFNDEBUG, printf ("[pre_visit]\t\t%d:", dfn_depth);
+       print_name (parent);
+       printf ("\n"));
+}
+
+
+/*
+ * Done with visiting node PARENT.  Pop PARENT off dfn_stack
+ * and number functions if PARENT is head of a cycle.
+ */
+static void
+DEFUN (post_visit, (parent), Sym * parent)
+{
+  Sym *member;
+
+  DBG (DFNDEBUG, printf ("[post_visit]\t%d: ", dfn_depth);
+       print_name (parent);
+       printf ("\n"));
+  /*
+   * Number functions and things in their cycles unless the function
+   * is itself part of a cycle:
+   */
+  if (parent->cg.cyc.head == parent)
+    {
+      ++dfn_counter;
+      for (member = parent; member; member = member->cg.cyc.next)
+       {
+         member->cg.top_order = dfn_counter;
+         DBG (DFNDEBUG, printf ("[post_visit]\t\tmember ");
+              print_name (member);
+              printf ("-> cg.top_order = %d\n", dfn_counter));
+       }
+    }
+  else
+    {
+      DBG (DFNDEBUG, printf ("[post_visit]\t\tis part of a cycle\n"));
+    }
+  --dfn_depth;
+}
+
+
+/*
+ * Given this PARENT, depth first number its children.
+ */
+void
+DEFUN (cg_dfn, (parent), Sym * parent)
+{
+  Arc *arc;
+
+  DBG (DFNDEBUG, printf ("[dfn] dfn( ");
+       print_name (parent);
+       printf (")\n"));
+  /*
+   * If we're already numbered, no need to look any further:
+   */
+  if (is_numbered (parent))
+    {
+      return;
+    }
+  /*
+   * If we're already busy, must be a cycle:
+   */
+  if (is_busy (parent))
+    {
+      find_cycle (parent);
+      return;
+    }
+  pre_visit (parent);
+  /*
+   * Recursively visit children:
+   */
+  for (arc = parent->cg.children; arc; arc = arc->next_child)
+    {
+      cg_dfn (arc->child);
+    }
+  post_visit (parent);
+}
diff --git a/gprof/cg_dfn.h b/gprof/cg_dfn.h
new file mode 100644 (file)
index 0000000..4bd3030
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef cg_dfn_h
+#define cg_dfn_h
+
+/*
+ * Flags which mark a symbol as topologically ``busy'' or as
+ * topologically ``not_numbered'':
+ */
+#define        DFN_BUSY        -1
+#define        DFN_NAN         0
+
+/*
+ * Depth-first numbering of a call-graph.
+ */
+
+extern void cg_dfn PARAMS ((Sym * root));
+
+#endif /* cg_dfn_h */
diff --git a/gprof/cg_print.c b/gprof/cg_print.c
new file mode 100644 (file)
index 0000000..e645bc7
--- /dev/null
@@ -0,0 +1,1276 @@
+#include "libiberty.h"
+#include "cg_arcs.h"
+#include "cg_print.h"
+#include "hist.h"
+#include "utils.h"
+
+/*
+ * Return value of comparison functions used to sort tables:
+ */
+#define        LESSTHAN        -1
+#define        EQUALTO         0
+#define        GREATERTHAN     1
+
+static void order_and_dump_functions_by_arcs PARAMS ((Arc **, unsigned long,
+                                                     int, Arc **,
+                                                     unsigned long *));
+/* declarations of automatically generated functions to output blurbs: */
+extern void bsd_callg_blurb PARAMS ((FILE * fp));
+extern void fsf_callg_blurb PARAMS ((FILE * fp));
+
+double print_time = 0.0;
+
+
+static void
+DEFUN_VOID (print_header)
+{
+  if (first_output)
+    {
+      first_output = FALSE;
+    }
+  else
+    {
+      printf ("\f\n");
+    }
+  if (!bsd_style_output)
+    {
+      if (print_descriptions)
+       {
+         printf (_("\t\t     Call graph (explanation follows)\n\n"));
+       }
+      else
+       {
+         printf (_("\t\t\tCall graph\n\n"));
+       }
+    }
+  printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
+         (long) hist_scale * sizeof (UNIT));
+  if (print_time > 0.0)
+    {
+      printf (_(" for %.2f%% of %.2f seconds\n\n"),
+             100.0 / print_time, print_time / hz);
+    }
+  else
+    {
+      printf (_(" no time propagated\n\n"));
+      /*
+       * This doesn't hurt, since all the numerators will be 0.0:
+       */
+      print_time = 1.0;
+    }
+  if (bsd_style_output)
+    {
+      printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n",
+             "", "", "", "", _("called"), _("total"), _("parents"));
+      printf ("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
+             _("index"), _("%time"), _("self"), _("descendents"),
+             _("called"), _("self"), _("name"), _("index"));
+      printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n",
+             "", "", "", "", _("called"), _("total"), _("children"));
+      printf ("\n");
+    }
+  else
+    {
+      printf (_("index %% time    self  children    called     name\n"));
+    }
+}
+
+
+/*
+ * Print a cycle header.
+ */
+static void
+DEFUN (print_cycle, (cyc), Sym * cyc)
+{
+  char buf[BUFSIZ];
+
+  sprintf (buf, "[%d]", cyc->cg.index);
+  printf (bsd_style_output
+         ? "%-6.6s %5.1f %7.2f %11.2f %7lu"
+         : "%-6.6s %5.1f %7.2f %7.2f %7lu", buf,
+         100 * (cyc->cg.prop.self + cyc->cg.prop.child) / print_time,
+         cyc->cg.prop.self / hz, cyc->cg.prop.child / hz, cyc->ncalls);
+  if (cyc->cg.self_calls != 0)
+    {
+      printf ("+%-7lu", cyc->cg.self_calls);
+    }
+  else
+    {
+      printf (" %7.7s", "");
+    }
+  printf (_(" <cycle %d as a whole> [%d]\n"), cyc->cg.cyc.num, cyc->cg.index);
+}
+
+
+/*
+ * Compare LEFT and RIGHT membmer.  Major comparison key is
+ * CG.PROP.SELF+CG.PROP.CHILD, secondary key is NCALLS+CG.SELF_CALLS.
+ */
+static int
+DEFUN (cmp_member, (left, right), Sym * left AND Sym * right)
+{
+  double left_time = left->cg.prop.self + left->cg.prop.child;
+  double right_time = right->cg.prop.self + right->cg.prop.child;
+  unsigned long left_calls = left->ncalls + left->cg.self_calls;
+  unsigned long right_calls = right->ncalls + right->cg.self_calls;
+
+  if (left_time > right_time)
+    {
+      return GREATERTHAN;
+    }
+  if (left_time < right_time)
+    {
+      return LESSTHAN;
+    }
+
+  if (left_calls > right_calls)
+    {
+      return GREATERTHAN;
+    }
+  if (left_calls < right_calls)
+    {
+      return LESSTHAN;
+    }
+  return EQUALTO;
+}
+
+
+/*
+ * Sort members of a cycle.
+ */
+static void
+DEFUN (sort_members, (cyc), Sym * cyc)
+{
+  Sym *todo, *doing, *prev;
+  /*
+   * Detach cycle members from cyclehead, and insertion sort them
+   * back on.
+   */
+  todo = cyc->cg.cyc.next;
+  cyc->cg.cyc.next = 0;
+  for (doing = todo; doing && doing->cg.cyc.next; doing = todo)
+    {
+      todo = doing->cg.cyc.next;
+      for (prev = cyc; prev->cg.cyc.next; prev = prev->cg.cyc.next)
+       {
+         if (cmp_member (doing, prev->cg.cyc.next) == GREATERTHAN)
+           {
+             break;
+           }
+       }
+      doing->cg.cyc.next = prev->cg.cyc.next;
+      prev->cg.cyc.next = doing;
+    }
+}
+
+
+/*
+ * Print the members of a cycle.
+ */
+static void
+DEFUN (print_members, (cyc), Sym * cyc)
+{
+  Sym *member;
+
+  sort_members (cyc);
+  for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
+    {
+      printf (bsd_style_output
+             ? "%6.6s %5.5s %7.2f %11.2f %7lu"
+             : "%6.6s %5.5s %7.2f %7.2f %7lu",
+             "", "", member->cg.prop.self / hz, member->cg.prop.child / hz,
+             member->ncalls);
+      if (member->cg.self_calls != 0)
+       {
+         printf ("+%-7lu", member->cg.self_calls);
+       }
+      else
+       {
+         printf (" %7.7s", "");
+       }
+      printf ("     ");
+      print_name (member);
+      printf ("\n");
+    }
+}
+
+
+/*
+ * Compare two arcs to/from the same child/parent.
+ *      - if one arc is a self arc, it's least.
+ *      - if one arc is within a cycle, it's less than.
+ *      - if both arcs are within a cycle, compare arc counts.
+ *      - if neither arc is within a cycle, compare with
+ *              time + child_time as major key
+ *              arc count as minor key
+ */
+static int
+DEFUN (cmp_arc, (left, right), Arc * left AND Arc * right)
+{
+  Sym *left_parent = left->parent;
+  Sym *left_child = left->child;
+  Sym *right_parent = right->parent;
+  Sym *right_child = right->child;
+  double left_time, right_time;
+
+  DBG (TIMEDEBUG,
+       printf ("[cmp_arc] ");
+       print_name (left_parent);
+       printf (" calls ");
+       print_name (left_child);
+       printf (" %f + %f %lu/%lu\n", left->time, left->child_time,
+              left->count, left_child->ncalls);
+       printf ("[cmp_arc] ");
+       print_name (right_parent);
+       printf (" calls ");
+       print_name (right_child);
+       printf (" %f + %f %lu/%lu\n", right->time, right->child_time,
+              right->count, right_child->ncalls);
+       printf ("\n");
+    );
+  if (left_parent == left_child)
+    {
+      return LESSTHAN;         /* left is a self call */
+    }
+  if (right_parent == right_child)
+    {
+      return GREATERTHAN;      /* right is a self call */
+    }
+
+  if (left_parent->cg.cyc.num != 0 && left_child->cg.cyc.num != 0
+      && left_parent->cg.cyc.num == left_child->cg.cyc.num)
+    {
+      /* left is a call within a cycle */
+      if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
+         && right_parent->cg.cyc.num == right_child->cg.cyc.num)
+       {
+         /* right is a call within the cycle, too */
+         if (left->count < right->count)
+           {
+             return LESSTHAN;
+           }
+         if (left->count > right->count)
+           {
+             return GREATERTHAN;
+           }
+         return EQUALTO;
+       }
+      else
+       {
+         /* right isn't a call within the cycle */
+         return LESSTHAN;
+       }
+    }
+  else
+    {
+      /* left isn't a call within a cycle */
+      if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
+         && right_parent->cg.cyc.num == right_child->cg.cyc.num)
+       {
+         /* right is a call within a cycle */
+         return GREATERTHAN;
+       }
+      else
+       {
+         /* neither is a call within a cycle */
+         left_time = left->time + left->child_time;
+         right_time = right->time + right->child_time;
+         if (left_time < right_time)
+           {
+             return LESSTHAN;
+           }
+         if (left_time > right_time)
+           {
+             return GREATERTHAN;
+           }
+         if (left->count < right->count)
+           {
+             return LESSTHAN;
+           }
+         if (left->count > right->count)
+           {
+             return GREATERTHAN;
+           }
+         return EQUALTO;
+       }
+    }
+}
+
+
+static void
+DEFUN (sort_parents, (child), Sym * child)
+{
+  Arc *arc, *detached, sorted, *prev;
+
+  /*
+   * Unlink parents from child, then insertion sort back on to
+   * sorted's parents.
+   *      *arc        the arc you have detached and are inserting.
+   *      *detached   the rest of the arcs to be sorted.
+   *      sorted      arc list onto which you insertion sort.
+   *      *prev       arc before the arc you are comparing.
+   */
+  sorted.next_parent = 0;
+  for (arc = child->cg.parents; arc; arc = detached)
+    {
+      detached = arc->next_parent;
+
+      /* consider *arc as disconnected; insert it into sorted: */
+      for (prev = &sorted; prev->next_parent; prev = prev->next_parent)
+       {
+         if (cmp_arc (arc, prev->next_parent) != GREATERTHAN)
+           {
+             break;
+           }
+       }
+      arc->next_parent = prev->next_parent;
+      prev->next_parent = arc;
+    }
+
+  /* reattach sorted arcs to child: */
+  child->cg.parents = sorted.next_parent;
+}
+
+
+static void
+DEFUN (print_parents, (child), Sym * child)
+{
+  Sym *parent;
+  Arc *arc;
+  Sym *cycle_head;
+
+  if (child->cg.cyc.head != 0)
+    {
+      cycle_head = child->cg.cyc.head;
+    }
+  else
+    {
+      cycle_head = child;
+    }
+  if (!child->cg.parents)
+    {
+      printf (bsd_style_output
+             ? _("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n")
+             : _("%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s     <spontaneous>\n"),
+             "", "", "", "", "", "");
+      return;
+    }
+  sort_parents (child);
+  for (arc = child->cg.parents; arc; arc = arc->next_parent)
+    {
+      parent = arc->parent;
+      if (child == parent || (child->cg.cyc.num != 0
+                             && parent->cg.cyc.num == child->cg.cyc.num))
+       {
+         /* selfcall or call among siblings: */
+         printf (bsd_style_output
+                 ? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s     "
+                 : "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s     ",
+                 "", "", "", "",
+                 arc->count, "");
+         print_name (parent);
+         printf ("\n");
+       }
+      else
+       {
+         /* regular parent of child: */
+         printf (bsd_style_output
+                 ? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu     "
+                 : "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu     ",
+                 "", "",
+                 arc->time / hz, arc->child_time / hz,
+                 arc->count, cycle_head->ncalls);
+         print_name (parent);
+         printf ("\n");
+       }
+    }
+}
+
+
+static void
+DEFUN (sort_children, (parent), Sym * parent)
+{
+  Arc *arc, *detached, sorted, *prev;
+  /*
+   * Unlink children from parent, then insertion sort back on to
+   * sorted's children.
+   *      *arc        the arc you have detached and are inserting.
+   *      *detached   the rest of the arcs to be sorted.
+   *      sorted      arc list onto which you insertion sort.
+   *      *prev       arc before the arc you are comparing.
+   */
+  sorted.next_child = 0;
+  for (arc = parent->cg.children; arc; arc = detached)
+    {
+      detached = arc->next_child;
+
+      /* consider *arc as disconnected; insert it into sorted: */
+      for (prev = &sorted; prev->next_child; prev = prev->next_child)
+       {
+         if (cmp_arc (arc, prev->next_child) != LESSTHAN)
+           {
+             break;
+           }
+       }
+      arc->next_child = prev->next_child;
+      prev->next_child = arc;
+    }
+
+  /* reattach sorted children to parent: */
+  parent->cg.children = sorted.next_child;
+}
+
+
+static void
+DEFUN (print_children, (parent), Sym * parent)
+{
+  Sym *child;
+  Arc *arc;
+
+  sort_children (parent);
+  arc = parent->cg.children;
+  for (arc = parent->cg.children; arc; arc = arc->next_child)
+    {
+      child = arc->child;
+      if (child == parent || (child->cg.cyc.num != 0
+                             && child->cg.cyc.num == parent->cg.cyc.num))
+       {
+         /* self call or call to sibling: */
+         printf (bsd_style_output
+                 ? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s     "
+                 : "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s     ",
+                 "", "", "", "", arc->count, "");
+         print_name (child);
+         printf ("\n");
+       }
+      else
+       {
+         /* regular child of parent: */
+         printf (bsd_style_output
+                 ? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu     "
+                 : "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu     ",
+                 "", "",
+                 arc->time / hz, arc->child_time / hz,
+                 arc->count, child->cg.cyc.head->ncalls);
+         print_name (child);
+         printf ("\n");
+       }
+    }
+}
+
+
+static void
+DEFUN (print_line, (np), Sym * np)
+{
+  char buf[BUFSIZ];
+
+  sprintf (buf, "[%d]", np->cg.index);
+  printf (bsd_style_output
+         ? "%-6.6s %5.1f %7.2f %11.2f"
+         : "%-6.6s %5.1f %7.2f %7.2f", buf,
+         100 * (np->cg.prop.self + np->cg.prop.child) / print_time,
+         np->cg.prop.self / hz, np->cg.prop.child / hz);
+  if ((np->ncalls + np->cg.self_calls) != 0)
+    {
+      printf (" %7lu", np->ncalls);
+      if (np->cg.self_calls != 0)
+       {
+         printf ("+%-7lu ", np->cg.self_calls);
+       }
+      else
+       {
+         printf (" %7.7s ", "");
+       }
+    }
+  else
+    {
+      printf (" %7.7s %7.7s ", "", "");
+    }
+  print_name (np);
+  printf ("\n");
+}
+
+
+/*
+ * Print dynamic call graph.
+ */
+void
+DEFUN (cg_print, (timesortsym), Sym ** timesortsym)
+{
+  unsigned int index;
+  Sym *parent;
+
+  if (print_descriptions && bsd_style_output)
+    {
+      bsd_callg_blurb (stdout);
+    }
+
+  print_header ();
+
+  for (index = 0; index < symtab.len + num_cycles; ++index)
+    {
+      parent = timesortsym[index];
+      if ((ignore_zeros && parent->ncalls == 0
+          && parent->cg.self_calls == 0 && parent->cg.prop.self == 0
+          && parent->cg.prop.child == 0)
+         || !parent->cg.print_flag
+         || (line_granularity && ! parent->is_func))
+       {
+         continue;
+       }
+      if (!parent->name && parent->cg.cyc.num != 0)
+       {
+         /* cycle header: */
+         print_cycle (parent);
+         print_members (parent);
+       }
+      else
+       {
+         print_parents (parent);
+         print_line (parent);
+         print_children (parent);
+       }
+      if (bsd_style_output)
+       printf ("\n");
+      printf ("-----------------------------------------------\n");
+      if (bsd_style_output)
+       printf ("\n");
+    }
+  free (timesortsym);
+  if (print_descriptions && !bsd_style_output)
+    {
+      fsf_callg_blurb (stdout);
+    }
+}
+
+
+static int
+DEFUN (cmp_name, (left, right), const PTR left AND const PTR right)
+{
+  const Sym **npp1 = (const Sym **) left;
+  const Sym **npp2 = (const Sym **) right;
+
+  return strcmp ((*npp1)->name, (*npp2)->name);
+}
+
+
+void
+DEFUN_VOID (cg_print_index)
+{
+  unsigned int index;
+  unsigned int nnames, todo, i, j;
+  int col, starting_col;
+  Sym **name_sorted_syms, *sym;
+  const char *filename;
+  char buf[20];
+  int column_width = (output_width - 1) / 3;   /* don't write in last col! */
+  /*
+   * Now, sort regular function name alphabetically to create an
+   * index:
+   */
+  name_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
+  for (index = 0, nnames = 0; index < symtab.len; index++)
+    {
+      if (ignore_zeros && symtab.base[index].ncalls == 0
+         && symtab.base[index].hist.time == 0)
+       {
+         continue;
+       }
+      name_sorted_syms[nnames++] = &symtab.base[index];
+    }
+  qsort (name_sorted_syms, nnames, sizeof (Sym *), cmp_name);
+  for (index = 1, todo = nnames; index <= num_cycles; index++)
+    {
+      name_sorted_syms[todo++] = &cycle_header[index];
+    }
+  printf ("\f\n");
+  printf (_("Index by function name\n\n"));
+  index = (todo + 2) / 3;
+  for (i = 0; i < index; i++)
+    {
+      col = 0;
+      starting_col = 0;
+      for (j = i; j < todo; j += index)
+       {
+         sym = name_sorted_syms[j];
+         if (sym->cg.print_flag)
+           {
+             sprintf (buf, "[%d]", sym->cg.index);
+           }
+         else
+           {
+             sprintf (buf, "(%d)", sym->cg.index);
+           }
+         if (j < nnames)
+           {
+             if (bsd_style_output)
+               {
+                 printf ("%6.6s %-19.19s", buf, sym->name);
+               }
+             else
+               {
+                 col += strlen (buf);
+                 for (; col < starting_col + 5; ++col)
+                   {
+                     putchar (' ');
+                   }
+                 printf (" %s ", buf);
+                 col += print_name_only (sym);
+                 if (!line_granularity && sym->is_static && sym->file)
+                   {
+                     filename = sym->file->name;
+                     if (!print_path)
+                       {
+                         filename = strrchr (filename, '/');
+                         if (filename)
+                           {
+                             ++filename;
+                           }
+                         else
+                           {
+                             filename = sym->file->name;
+                           }
+                       }
+                     printf (" (%s)", filename);
+                     col += strlen (filename) + 3;
+                   }
+               }
+           }
+         else
+           {
+             if (bsd_style_output)
+               {
+                 printf ("%6.6s ", buf);
+                 sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
+                 printf ("%-19.19s", buf);
+               }
+             else
+               {
+                 col += strlen (buf);
+                 for (; col < starting_col + 5; ++col)
+                   putchar (' ');
+                 printf (" %s ", buf);
+                 sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
+                 printf ("%s", buf);
+                 col += strlen (buf);
+               }
+           }
+         starting_col += column_width;
+       }
+      printf ("\n");
+    }
+  free (name_sorted_syms);
+}
+
+/* Compare two arcs based on their usage counts.  We want to sort
+   in descending order.  */
+static int
+DEFUN (cmp_arc_count, (left, right), const PTR left AND const PTR right)
+{
+  const Arc **npp1 = (const Arc **) left;
+  const Arc **npp2 = (const Arc **) right;
+
+  if ((*npp1)->count > (*npp2)->count)
+    return -1;
+  else if ((*npp1)->count < (*npp2)->count)
+    return 1;
+  else
+    return 0;
+}
+
+/* Compare two funtions based on their usage counts.  We want to sort
+   in descending order.  */
+static int
+DEFUN (cmp_fun_nuses, (left, right), const PTR left AND const PTR right)
+{
+  const Sym **npp1 = (const Sym **) left;
+  const Sym **npp2 = (const Sym **) right;
+
+  if ((*npp1)->nuses > (*npp2)->nuses)
+    return -1;
+  else if ((*npp1)->nuses < (*npp2)->nuses)
+    return 1;
+  else
+    return 0;
+}
+
+/* Print a suggested function ordering based on the profiling data.
+
+   We perform 4 major steps when ordering functions:
+
+       * Group unused functions together and place them at the
+       end of the function order.
+
+       * Search the highest use arcs (those which account for 90% of
+       the total arc count) for functions which have several parents.
+
+       Group those with the most call sites together (currently the
+       top 1.25% which have at least five different call sites).
+
+       These are emitted at the start of the function order.
+
+       * Use a greedy placement algorithm to place functions which
+       occur in the top 99% of the arcs in the profile.  Some provisions
+       are made to handle high usage arcs where the parent and/or
+       child has already been placed.
+
+       * Run the same greedy placement algorithm on the remaining
+       arcs to place the leftover functions.
+
+
+   The various "magic numbers" should (one day) be tuneable by command
+   line options.  They were arrived at by benchmarking a few applications
+   with various values to see which values produced better overall function
+   orderings.
+
+   Of course, profiling errors, machine limitations (PA long calls), and
+   poor cutoff values for the placement algorithm may limit the usefullness
+   of the resulting function order.  Improvements would be greatly appreciated.
+   
+   Suggestions:
+
+       * Place the functions with many callers near the middle of the
+       list to reduce long calls.
+
+       * Propagate arc usage changes as functions are placed.  Ie if
+       func1 and func2 are placed together, arcs to/from those arcs
+       to the same parent/child should be combined, then resort the
+       arcs to choose the next one.
+
+       * Implement some global positioning algorithm to place the
+       chains made by the greedy local positioning algorithm.  Probably
+       by examining arcs which haven't been placed yet to tie two
+       chains together.
+
+       * Take a function's size and time into account in the algorithm;
+       size in particular is important on the PA (long calls).  Placing
+       many small functions onto their own page may be wise.
+
+       * Use better profiling information; many published algorithms
+       are based on call sequences through time, rather than just
+       arc counts.
+
+       * Prodecure cloning could improve performance when a small number
+       of arcs account for most of the calls to a particular function.
+
+       * Use relocation information to avoid moving unused functions
+       completely out of the code stream; this would avoid severe lossage
+       when the profile data bears little resemblance to actual runs.
+
+       * Propagation of arc usages should also improve .o link line
+       ordering which shares the same arc placement algorithm with
+       the function ordering code (in fact it is a degenerate case
+       of function ordering).  */
+       
+void
+DEFUN_VOID (cg_print_function_ordering)
+{
+  unsigned long index, used, unused, scratch_index;
+  unsigned long  unplaced_arc_count, high_arc_count, scratch_arc_count;
+#ifdef __GNUC__
+  unsigned long long total_arcs, tmp_arcs_count;
+#else
+  unsigned long total_arcs, tmp_arcs_count;
+#endif
+  Sym **unused_syms, **used_syms, **scratch_syms;
+  Arc **unplaced_arcs, **high_arcs, **scratch_arcs;
+
+  index = 0;
+  used = 0;
+  unused = 0;
+  scratch_index = 0;
+  unplaced_arc_count = 0;
+  high_arc_count = 0;
+  scratch_arc_count = 0;
+
+  /* First group all the unused functions together.  */
+  unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+  used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+  scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+  high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
+  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
+  unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
+
+  /* Walk through all the functions; mark those which are never
+     called as placed (we'll emit them as a group later).  */
+  for (index = 0, used = 0, unused = 0; index < symtab.len; index++)
+    {
+      if (symtab.base[index].ncalls == 0)
+       {
+         /* Filter out gprof generated names.  */
+         if (strcmp (symtab.base[index].name, "<locore>")
+             && strcmp (symtab.base[index].name, "<hicore>"))
+           {
+             unused_syms[unused++] = &symtab.base[index];
+             symtab.base[index].has_been_placed = 1;
+           }
+       }
+      else
+       {
+         used_syms[used++] = &symtab.base[index];
+         symtab.base[index].has_been_placed = 0;
+         symtab.base[index].next = 0;
+         symtab.base[index].prev = 0;
+         symtab.base[index].nuses = 0;
+       }
+    }
+
+  /* Sort the arcs from most used to least used.  */
+  qsort (arcs, numarcs, sizeof (Arc *), cmp_arc_count);
+
+  /* Compute the total arc count.  Also mark arcs as unplaced.
+
+     Note we don't compensate for overflow if that happens!
+     Overflow is much less likely when this file is compiled
+     with GCC as it can double-wide integers via long long.  */
+  total_arcs = 0;
+  for (index = 0; index < numarcs; index++)
+    {
+      total_arcs += arcs[index]->count;
+      arcs[index]->has_been_placed = 0;
+    }
+
+  /* We want to pull out those functions which are referenced
+     by many highly used arcs and emit them as a group.  This
+     could probably use some tuning.  */
+  tmp_arcs_count = 0;
+  for (index = 0; index < numarcs; index++)
+    {
+      tmp_arcs_count += arcs[index]->count;
+
+      /* Count how many times each parent and child are used up
+        to our threshhold of arcs (90%).  */
+      if ((double)tmp_arcs_count / (double)total_arcs > 0.90)
+       break;
+
+      arcs[index]->child->nuses++;
+    }
+
+  /* Now sort a temporary symbol table based on the number of
+     times each function was used in the highest used arcs.  */
+  memcpy (scratch_syms, used_syms, used * sizeof (Sym *));
+  qsort (scratch_syms, used, sizeof (Sym *), cmp_fun_nuses);
+
+  /* Now pick out those symbols we're going to emit as
+     a group.  We take up to 1.25% of the used symbols.  */
+  for (index = 0; index < used / 80; index++)
+    {
+      Sym *sym = scratch_syms[index];
+      Arc *arc;
+
+      /* If we hit symbols that aren't used from many call sites,
+        then we can quit.  We choose five as the low limit for
+        no particular reason.  */
+      if (sym->nuses == 5)
+       break;
+
+      /* We're going to need the arcs between these functions.
+        Unfortunately, we don't know all these functions
+        until we're done.  So we keep track of all the arcs
+        to the functions we care about, then prune out those
+        which are uninteresting. 
+
+        An interesting variation would be to quit when we found
+        multi-call site functions which account for some percentage
+        of the arcs.  */
+
+      arc = sym->cg.children;
+      while (arc)
+       {
+         if (arc->parent != arc->child)
+           scratch_arcs[scratch_arc_count++] = arc;
+         arc->has_been_placed = 1;
+         arc = arc->next_child;
+       }
+
+      arc = sym->cg.parents;
+      while (arc)
+       {
+         if (arc->parent != arc->child)
+           scratch_arcs[scratch_arc_count++] = arc;
+         arc->has_been_placed = 1;
+         arc = arc->next_parent;
+       }
+
+      /* Keep track of how many symbols we're going to place.  */
+      scratch_index = index;
+
+      /* A lie, but it makes identifying these functions easier
+        later.  */
+      sym->has_been_placed = 1;
+    }
+
+  /* Now walk through the temporary arcs and copy those we care about
+     into the high arcs array.  */
+  for (index = 0; index < scratch_arc_count; index++)
+    {
+      Arc *arc = scratch_arcs[index];
+
+      /* If this arc refers to highly used functions, then
+        then we want to keep it.  */
+      if (arc->child->has_been_placed
+         && arc->parent->has_been_placed)
+       {
+         high_arcs[high_arc_count++] = scratch_arcs[index];
+
+         /* We need to turn of has_been_placed since we're going to
+            use the main arc placement algorithm on these arcs.  */
+         arc->child->has_been_placed = 0;
+         arc->parent->has_been_placed = 0;
+       }
+    }
+
+  /* Dump the multi-site high usage functions which are not going
+     to be ordered by the main ordering algorithm.  */
+  for (index = 0; index < scratch_index; index++)
+    {
+      if (scratch_syms[index]->has_been_placed)
+       printf ("%s\n", scratch_syms[index]->name);
+    }
+
+  /* Now we can order the multi-site high use functions based on the
+     arcs between them.  */
+  qsort (high_arcs, high_arc_count, sizeof (Arc *), cmp_arc_count);
+  order_and_dump_functions_by_arcs (high_arcs, high_arc_count, 1,
+                                   unplaced_arcs, &unplaced_arc_count);
+
+  /* Order and dump the high use functions left, these typically
+     have only a few call sites.  */
+  order_and_dump_functions_by_arcs (arcs, numarcs, 0,
+                                   unplaced_arcs, &unplaced_arc_count);
+
+  /* Now place the rarely used functions.  */
+  order_and_dump_functions_by_arcs (unplaced_arcs, unplaced_arc_count, 1,
+                                   scratch_arcs, &scratch_arc_count);
+
+  /* Output any functions not emitted by the order_and_dump calls.  */
+  for (index = 0; index < used; index++)
+    if (used_syms[index]->has_been_placed == 0)
+      printf("%s\n", used_syms[index]->name);
+
+  /* Output the unused functions.  */
+  for (index = 0; index < unused; index++)
+    printf("%s\n", unused_syms[index]->name);
+
+  unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+  used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+  scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+  high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
+  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
+  unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
+
+  free (unused_syms);
+  free (used_syms);
+  free (scratch_syms);
+  free (high_arcs);
+  free (scratch_arcs);
+  free (unplaced_arcs);
+}
+
+/* Place functions based on the arcs in ARCS with NUMARCS entries;
+   place unused arcs into UNPLACED_ARCS/UNPLACED_ARC_COUNT.
+
+   If ALL is nonzero, then place all functions referenced by ARCS,
+   else only place those referenced in the top 99% of the arcs in ARCS.  */
+
+#define MOST 0.99
+static void
+order_and_dump_functions_by_arcs (arcs, numarcs, all,
+                                 unplaced_arcs, unplaced_arc_count)
+     Arc **arcs;
+     unsigned long numarcs;
+     int all;
+     Arc **unplaced_arcs;
+     unsigned long *unplaced_arc_count;
+{
+#ifdef __GNUC__
+  unsigned long long tmp_arcs, total_arcs;
+#else
+  unsigned long tmp_arcs, total_arcs;
+#endif
+  unsigned int index;
+
+  /* If needed, compute the total arc count.
+
+     Note we don't compensate for overflow if that happens!  */
+  if (! all)
+    {
+      total_arcs = 0;
+      for (index = 0; index < numarcs; index++)
+       total_arcs += arcs[index]->count;
+    }
+  else
+    total_arcs = 0;
+
+  tmp_arcs = 0;
+  for (index = 0; index < numarcs; index++)
+    {
+      Sym *sym1, *sym2;
+      Sym *child, *parent;
+
+      tmp_arcs += arcs[index]->count;
+
+      /* Ignore this arc if it's already been placed.  */
+      if (arcs[index]->has_been_placed)
+       continue;
+
+      child = arcs[index]->child;
+      parent = arcs[index]->parent;
+
+      /* If we're not using all arcs, and this is a rarely used
+        arc, then put it on the unplaced_arc list.  Similarly
+        if both the parent and child of this arc have been placed.  */
+      if ((! all && (double)tmp_arcs / (double)total_arcs > MOST)
+         || child->has_been_placed || parent->has_been_placed)
+       {
+         unplaced_arcs[(*unplaced_arc_count)++] = arcs[index];
+         continue;
+       }
+
+      /* If all slots in the parent and child are full, then there isn't
+        anything we can do right now.  We'll place this arc on the
+        unplaced arc list in the hope that a global positioning
+        algorithm can use it to place function chains.  */
+      if (parent->next && parent->prev && child->next && child->prev)
+       {
+         unplaced_arcs[(*unplaced_arc_count)++] = arcs[index];
+         continue;
+       }
+
+      /* If the parent is unattached, then find the closest
+        place to attach it onto child's chain.   Similarly
+        for the opposite case.  */
+      if (!parent->next && !parent->prev)
+       {
+         int next_count = 0;
+         int prev_count = 0;
+         Sym *prev = child;
+         Sym *next = child;
+
+         /* Walk to the beginning and end of the child's chain.  */
+         while (next->next)
+           {
+             next = next->next;
+             next_count++;
+           }
+
+         while (prev->prev)
+           {
+             prev = prev->prev;
+             prev_count++;
+           }
+         
+         /* Choose the closest.  */
+         child = next_count < prev_count ? next : prev;
+      }
+      else if (! child->next && !child->prev)
+       {
+         int next_count = 0;
+         int prev_count = 0;
+         Sym *prev = parent;
+         Sym *next = parent;
+
+         while (next->next)
+           {
+             next = next->next;
+             next_count++;
+           }
+
+         while (prev->prev)
+           {
+             prev = prev->prev;
+             prev_count++;
+           }
+
+         parent = prev_count < next_count ? prev : next;
+       }
+      else
+       {
+         /* Couldn't find anywhere to attach the functions,
+            put the arc on the unplaced arc list.  */
+         unplaced_arcs[(*unplaced_arc_count)++] = arcs[index];
+         continue;
+       }
+
+      /* Make sure we don't tie two ends together.  */
+      sym1 = parent;
+      if (sym1->next)
+       while (sym1->next)
+         sym1 = sym1->next;
+      else
+       while (sym1->prev)
+         sym1 = sym1->prev;
+
+      sym2 = child;
+      if (sym2->next)
+       while (sym2->next)
+         sym2 = sym2->next;
+      else
+       while (sym2->prev)
+         sym2 = sym2->prev;
+
+      if (sym1 == child
+         && sym2 == parent)
+       {
+         /* This would tie two ends together.  */
+         unplaced_arcs[(*unplaced_arc_count)++] = arcs[index];
+         continue;
+       }
+
+      if (parent->next)
+       {
+         /* Must attach to the parent's prev field.  */
+         if (! child->next)
+           {
+             /* parent-prev and child-next */
+             parent->prev = child;
+             child->next = parent;
+             arcs[index]->has_been_placed = 1;
+           }
+       }
+      else if (parent->prev)
+       {
+         /* Must attach to the parent's next field.  */
+         if (! child->prev)
+           {
+             /* parent-next and child-prev */
+             parent->next = child;
+             child->prev = parent;
+             arcs[index]->has_been_placed = 1;
+           }
+       }
+      else
+       {
+         /* Can attach to either field in the parent, depends
+            on where we've got space in the child.  */
+         if (child->prev)
+           {
+             /* parent-prev and child-next */
+             parent->prev = child;
+             child->next = parent;
+             arcs[index]->has_been_placed = 1;
+           }
+         else
+           {
+             /* parent-next and child-prev */
+             parent->next = child;
+             child->prev = parent;
+             arcs[index]->has_been_placed = 1;
+           }
+       }
+    }
+
+  /* Dump the chains of functions we've made.  */
+  for (index = 0; index < numarcs; index++)
+    {
+      Sym *sym;
+      if (arcs[index]->parent->has_been_placed
+         || arcs[index]->child->has_been_placed)
+       continue;
+
+      sym = arcs[index]->parent;
+
+      /* If this symbol isn't attached to any other
+        symbols, then we've got a rarely used arc.
+
+        Skip it for now, we'll deal with them later.  */
+      if (sym->next == NULL
+         && sym->prev == NULL)
+       continue;
+
+      /* Get to the start of this chain.  */
+      while (sym->prev)
+       sym = sym->prev;
+
+      while (sym)
+       {
+         /* Mark it as placed.  */
+         sym->has_been_placed = 1;
+         printf ("%s\n", sym->name);
+         sym = sym->next;
+       }
+    }
+
+  /* If we want to place all the arcs, then output those which weren't
+     placed by the main algorithm.  */
+  if (all)
+    for (index = 0; index < numarcs; index++)
+      {
+       Sym *sym;
+       if (arcs[index]->parent->has_been_placed
+           || arcs[index]->child->has_been_placed)
+         continue;
+
+       sym = arcs[index]->parent;
+
+       sym->has_been_placed = 1;
+       printf ("%s\n", sym->name);
+      }
+}
+
+/* Print a suggested .o ordering for files on a link line based
+   on profiling information.  This uses the function placement
+   code for the bulk of its work.  */
+
+struct function_map {
+  char *function_name;
+  char *file_name;
+};
+
+void
+DEFUN_VOID (cg_print_file_ordering)
+{
+  unsigned long scratch_arc_count, index;
+  Arc **scratch_arcs;
+  extern struct function_map *symbol_map;
+  extern unsigned int symbol_map_count;
+  char *last;
+
+  scratch_arc_count = 0;
+
+  scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
+  for (index = 0; index < numarcs; index++)
+    {
+      if (! arcs[index]->parent->mapped
+         || ! arcs[index]->child->mapped)
+       arcs[index]->has_been_placed = 1;
+    }
+
+  order_and_dump_functions_by_arcs (arcs, numarcs, 0,
+                                   scratch_arcs, &scratch_arc_count);
+
+  /* Output .o's not handled by the main placement algorithm.  */
+  for (index = 0; index < symtab.len; index++)
+    {
+      if (symtab.base[index].mapped
+         && ! symtab.base[index].has_been_placed)
+       printf ("%s\n", symtab.base[index].name);
+    }
+
+  /* Now output any .o's that didn't have any text symbols.  */
+  last = NULL;
+  for (index = 0; index < symbol_map_count; index++)
+    {
+      unsigned int index2;
+
+      /* Don't bother searching if this symbol is the
+        same as the previous one.  */
+      if (last && !strcmp (last, symbol_map[index].file_name))
+       continue;
+
+      for (index2 = 0; index2 < symtab.len; index2++)
+       {
+         if (! symtab.base[index2].mapped)
+           continue;
+
+         if (!strcmp (symtab.base[index2].name, symbol_map[index].file_name))
+           break;
+       }
+
+      /* If we didn't find it in the symbol table, then it must be a .o
+        with no text symbols.  Output it last.  */
+      if (index2 == symtab.len)
+       printf ("%s\n", symbol_map[index].file_name);
+      last = symbol_map[index].file_name;
+    } 
+}
diff --git a/gprof/cg_print.h b/gprof/cg_print.h
new file mode 100644 (file)
index 0000000..782c4aa
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef cg_print_h
+#define cg_print_h
+
+#include "gprof.h"
+#include "symtab.h"
+
+extern double print_time;      /* total of time being printed */
+
+extern void cg_print PARAMS ((Sym ** cg));
+extern void cg_print_index PARAMS ((void));
+extern void cg_print_file_ordering PARAMS ((void));
+extern void cg_print_function_ordering PARAMS ((void));
+
+#endif /* cg_print_h */
diff --git a/gprof/configure b/gprof/configure
new file mode 100755 (executable)
index 0000000..5ff5137
--- /dev/null
@@ -0,0 +1,4403 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+  --enable-shared[=PKGS]  build shared libraries [default=yes]"
+ac_help="$ac_help
+  --enable-static[=PKGS]  build static libraries [default=yes]"
+ac_help="$ac_help
+  --enable-fast-install[=PKGS]  optimize for fast installation [default=yes]"
+ac_help="$ac_help
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]"
+ac_help="$ac_help
+  --disable-libtool-lock  force libtool not to do file locking"
+ac_help="$ac_help
+  --disable-nls           do not use Native Language Support"
+ac_help="$ac_help
+  --with-included-gettext use the GNU gettext library included here"
+ac_help="$ac_help
+  --enable-maintainer-mode enable make rules and dependencies not useful
+                          (and sometimes confusing) to the casual installer"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=gprof.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+#    configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+#    same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+#    as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:590: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+  case $nonopt in
+  NONE)
+    if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+    fi ;;
+  *) host_alias=$nonopt ;;
+  esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:611: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+  case $nonopt in
+  NONE) target_alias=$host_alias ;;
+  *) target_alias=$nonopt ;;
+  esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:629: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+  case $nonopt in
+  NONE) build_alias=$host_alias ;;
+  *) build_alias=$nonopt ;;
+  esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:664: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:717: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "$*" != "X $srcdir/configure conftestfile" \
+      && test "$*" != "X conftestfile $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { echo "configure: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+   fi
+
+   test "$2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+  program_transform_name=
+else
+  # Double any \ or $.  echo might interpret backslashes.
+  cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+  program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+  rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:774: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+       @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+PACKAGE=gprof
+
+VERSION=2.9.4
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:820: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+   ACLOCAL=aclocal
+   echo "$ac_t""found" 1>&6
+else
+   ACLOCAL="$missing_dir/missing aclocal"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:833: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+   AUTOCONF=autoconf
+   echo "$ac_t""found" 1>&6
+else
+   AUTOCONF="$missing_dir/missing autoconf"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:846: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+   AUTOMAKE=automake
+   echo "$ac_t""found" 1>&6
+else
+   AUTOMAKE="$missing_dir/missing automake"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:859: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+   AUTOHEADER=autoheader
+   echo "$ac_t""found" 1>&6
+else
+   AUTOHEADER="$missing_dir/missing autoheader"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:872: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+   MAKEINFO=makeinfo
+   echo "$ac_t""found" 1>&6
+else
+   MAKEINFO="$missing_dir/missing makeinfo"
+   echo "$ac_t""missing" 1>&6
+fi
+
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval="$enable_shared"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_shared=yes
+fi
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval="$enable_static"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_static=yes
+fi
+
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval="$enable_fast_install"
+  p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_fast_install=yes
+fi
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:958: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_RANLIB="ranlib"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+  echo "$ac_t""$RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:988: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1018: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1069: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1101: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1112 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1143: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1148: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1157: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1176: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+echo "configure:1219: checking for ld used by GCC" >&5
+  ac_prog=`($CC -print-prog-name=ld) 2>&5`
+  case "$ac_prog" in
+    # Accept absolute paths.
+    /* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+echo "configure:1243: checking for GNU ld" >&5
+else
+  echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+echo "configure:1246: checking for non-GNU ld" >&5
+fi
+if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog"; then
+      ac_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+  echo "$ac_t""$LD" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+
+echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+echo "configure:1282: checking if the linker ($LD) is GNU ld" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  ac_cv_prog_gnu_ld=yes
+else
+  ac_cv_prog_gnu_ld=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6
+
+
+echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+echo "configure:1298: checking for BSD-compatible nm" >&5
+if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  ac_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/nm; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -B"
+       break
+      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       ac_cv_path_NM="$ac_dir/nm -p"
+       break
+      else
+       ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi
+fi
+
+NM="$ac_cv_path_NM"
+echo "$ac_t""$NM" 1>&6
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6
+echo "configure:1336: checking command to parse $NM output" >&5
+if eval "test \"`echo '$''{'ac_cv_sys_global_symbol_pipe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # These are sane defaults that work on at least a few old systems.
+# {They come from Ultrix.  What could be older than Ultrix?!! ;)}
+
+# Character class describing NM global symbol codes.
+ac_symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+ac_symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+  ac_symcode='[BCDT]'
+  ;;
+cygwin* | mingw*)
+  ac_symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+  ;;
+irix*)
+  ac_symcode='[BCDEGRST]'
+  ;;
+solaris*)
+  ac_symcode='[BDT]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+  ac_symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.*       \($ac_symcode\)                 *\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  ac_pipe_works=no
+  rm -f conftest.$ac_ext
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func;return 0;}
+EOF
+
+  if { (eval echo configure:1399: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+  
+    if { (eval echo configure:1403: \"$NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5; } && test -s "$ac_nlist"; then
+
+      # Try sorting and uniquifying the output.
+      if sort "$ac_nlist" | uniq > "$ac_nlist"T; then
+       mv -f "$ac_nlist"T "$ac_nlist"
+      else
+       rm -f "$ac_nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then
+       if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then
+         cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c'
+
+         cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+       sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c
+       cat <<\EOF >> conftest.c
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftestm.$ac_objext
+         ac_save_LIBS="$LIBS"
+         ac_save_CFLAGS="$CFLAGS"
+         LIBS="conftestm.$ac_objext"
+         CFLAGS="$CFLAGS$no_builtin_flag"
+         if { (eval echo configure:1455: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+           ac_pipe_works=yes
+         else
+           echo "configure: failed program was:" >&5
+           cat conftest.c >&5
+         fi
+         LIBS="$ac_save_LIBS"
+         CFLAGS="$ac_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $ac_nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $ac_nlist" >&5
+      fi
+    else
+      echo "cannot run $ac_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.c >&5
+  fi
+  rm -rf conftest*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$ac_pipe_works" = yes; then
+    if test x"$ac_symprfx" = x"_"; then
+      ac_cv_sys_symbol_underscore=yes
+    else
+      ac_cv_sys_symbol_underscore=no
+    fi
+    break
+  else
+    ac_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+
+ac_result=yes
+if test -z "$ac_cv_sys_global_symbol_pipe"; then
+   ac_result=no
+fi
+echo "$ac_t""$ac_result" 1>&6
+
+echo $ac_n "checking for _ prefix in compiled symbols""... $ac_c" 1>&6
+echo "configure:1501: checking for _ prefix in compiled symbols" >&5
+if eval "test \"`echo '$''{'ac_cv_sys_symbol_underscore'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_sys_symbol_underscore=no
+cat > conftest.$ac_ext <<EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+EOF
+if { (eval echo configure:1510: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  # Now try to grab the symbols.
+  ac_nlist=conftest.nm
+  if { (eval echo configure:1513: \"$NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5; } && test -s "$ac_nlist"; then
+    # See whether the symbols have a leading underscore.
+    if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+      ac_cv_sys_symbol_underscore=yes
+    else
+      if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+       :
+      else
+       echo "configure: cannot find nm_test_func in $ac_nlist" >&5
+      fi
+    fi
+  else
+    echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&5
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.c >&5
+fi
+rm -rf conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_sys_symbol_underscore" 1>&6
+USE_SYMBOL_UNDERSCORE=${ac_cv_sys_symbol_underscore=no}
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1539: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+  rm -f conftestdata
+  ac_cv_prog_LN_S="ln -s"
+else
+  ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+  echo "$ac_t""yes" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test $host != $build; then
+  ac_tool_prefix=${host_alias}-
+else
+  ac_tool_prefix=
+fi
+
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags="--cache-file=$cache_file"
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$lt_dlopen" = yes && libtool_flags="$libtool_flags --enable-dlopen"
+test "$silent" = yes && libtool_flags="$libtool_flags --silent"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$host" in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 1581 "configure"' > conftest.$ac_ext
+  if { (eval echo configure:1582: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
+echo "configure:1603: checking whether the C compiler needs -belf" >&5
+if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1608 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1615: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  lt_cv_cc_needs_belf=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  lt_cv_cc_needs_belf=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+*-*-cygwin*)
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1638: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+DLLTOOL="$ac_cv_prog_DLLTOOL"
+if test -n "$DLLTOOL"; then
+  echo "$ac_t""$DLLTOOL" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_DLLTOOL"; then
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1670: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_DLLTOOL="dlltool"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_DLLTOOL" && ac_cv_prog_DLLTOOL="false"
+fi
+fi
+DLLTOOL="$ac_cv_prog_DLLTOOL"
+if test -n "$DLLTOOL"; then
+  echo "$ac_t""$DLLTOOL" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  DLLTOOL="false"
+fi
+fi
+
+# Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1705: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$AS"; then
+  ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_AS="${ac_tool_prefix}as"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+AS="$ac_cv_prog_AS"
+if test -n "$AS"; then
+  echo "$ac_t""$AS" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_AS"; then
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1737: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$AS"; then
+  ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_AS="as"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_AS" && ac_cv_prog_AS="false"
+fi
+fi
+AS="$ac_cv_prog_AS"
+if test -n "$AS"; then
+  echo "$ac_t""$AS" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  AS="false"
+fi
+fi
+
+
+  ;;
+
+esac
+
+# enable the --disable-libtool-lock switch
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval="$enable_libtool_lock"
+  need_locks=$enableval
+else
+  need_locks=yes
+fi
+
+
+if test x"$need_locks" = xno; then
+  libtool_flags="$libtool_flags --disable-lock"
+fi
+
+
+# Save cache, so that ltconfig can load it
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \
+DLLTOOL="$DLLTOOL" AS="$AS" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; }
+
+# Reload cache, that may have been modified by ltconfig
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+
+
+
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1875: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1905: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1956: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1988: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1999 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:2004: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:2030: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:2035: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2044: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:2063: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:2106: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+echo "configure:2160: checking for POSIXized ISC" >&5
+if test -d /etc/conf/kconfig.d &&
+  grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+  echo "$ac_t""yes" 1>&6
+  ISC=yes # If later tests want to check for ISC.
+  cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+  if test "$GCC" = yes; then
+    CC="$CC -posix"
+  else
+    CC="$CC -Xp"
+  fi
+else
+  echo "$ac_t""no" 1>&6
+  ISC=
+fi
+
+
+ALL_LINGUAS=
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:2183: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 2198 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2204: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 2215 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2221: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 2232 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2238: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2263: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2268 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2276: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2293 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2311 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+  :
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2332 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:2343: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2367: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2372 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this.  */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this.  */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this.  */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+   It does not let you subtract one const X* pointer from another in an arm
+   of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this.  */
+  char *t;
+  char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+  *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+  int x[] = {25, 17};
+  const int *foo = &x[0];
+  ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+  typedef const int *iptr;
+  iptr p = 0;
+  ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+     "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+  struct s { int j; const int *ap[3]; };
+  struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+  const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:2421: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_const=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+  cat >> confdefs.h <<\EOF
+#define const 
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:2442: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat > conftest.$ac_ext <<EOF
+#line 2449 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:2456: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_inline=$ac_kw; break
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+  inline | yes) ;;
+  no) cat >> confdefs.h <<\EOF
+#define inline 
+EOF
+ ;;
+  *)  cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:2482: checking for off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2487 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_off_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+  cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:2515: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2520 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_size_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+  cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:2550: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2555 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:2562: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_header_alloca_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:2583: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2588 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:2616: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_func_alloca_works=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+  # that cause trouble.  Some versions do not even contain alloca or
+  # contain a buggy version.  If you still want to use their alloca,
+  # use ar to extract alloca.o from them instead of compiling alloca.c.
+  ALLOCA=alloca.${ac_objext}
+  cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:2648: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2653 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "webecray" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_os_cray=yes
+else
+  rm -rf conftest*
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+  echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2678: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2683 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2706: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+  break
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:2733: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2741 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+  exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:2760: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_c_stack_direction=1
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2785: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2790 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2795: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2824: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2829 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2852: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:2877: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_mmap_fixed_mapped=no
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2885 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+   Here is a matrix of mmap possibilities:
+       mmap private not fixed
+       mmap private fixed at somewhere currently unmapped
+       mmap private fixed at somewhere already mapped
+       mmap shared not fixed
+       mmap shared fixed at somewhere currently unmapped
+       mmap shared fixed at somewhere already mapped
+   For private mappings, we should verify that changes cannot be read()
+   back from the file, nor mmap's back from the file at a different
+   address.  (There have been systems where private was not correctly
+   implemented like the infamous i386 svr4.0, and systems where the
+   VM page cache was not coherent with the filesystem buffer cache
+   like early versions of FreeBSD and possibly contemporary NetBSD.)
+   For shared mappings, we should conversely verify that changes get
+   propogated back to all the places they're supposed to be.
+
+   Grep wants private fixed already mapped.
+   The main things grep needs to know about mmap are:
+   * does it exist and is it safe to write into the mmap'd area
+   * how to use it (BSD variants)  */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h.  */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h.  */
+# ifndef HAVE_SYS_PARAM_H
+#  define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+#  define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+#  ifdef HAVE_SYS_PARAM_H
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else /* no EXEC_PAGESIZE */
+#    ifdef NBPG
+#     define getpagesize() NBPG * CLSIZE
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif /* no CLSIZE */
+#    else /* no NBPG */
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     else /* no NBPC */
+#      ifdef PAGESIZE
+#       define getpagesize() PAGESIZE
+#      endif /* PAGESIZE */
+#     endif /* no NBPC */
+#    endif /* no NBPG */
+#   endif /* no EXEC_PAGESIZE */
+#  else /* no HAVE_SYS_PARAM_H */
+#   define getpagesize() 8192  /* punt totally */
+#  endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+       char *data, *data2, *data3;
+       int i, pagesize;
+       int fd;
+
+       pagesize = getpagesize();
+
+       /*
+        * First, make a file with some known garbage in it.
+        */
+       data = malloc(pagesize);
+       if (!data)
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               *(data + i) = rand();
+       umask(0);
+       fd = creat("conftestmmap", 0600);
+       if (fd < 0)
+               exit(1);
+       if (write(fd, data, pagesize) != pagesize)
+               exit(1);
+       close(fd);
+
+       /*
+        * Next, try to mmap the file at a fixed address which
+        * already has something else allocated at it.  If we can,
+        * also make sure that we see the same garbage.
+        */
+       fd = open("conftestmmap", O_RDWR);
+       if (fd < 0)
+               exit(1);
+       data2 = malloc(2 * pagesize);
+       if (!data2)
+               exit(1);
+       data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+       if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+           MAP_PRIVATE | MAP_FIXED, fd, 0L))
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               if (*(data + i) != *(data2 + i))
+                       exit(1);
+
+       /*
+        * Finally, make sure that changes to the mapped area
+        * do not percolate back to the file as seen by read().
+        * (This is a bug on some variants of i386 svr4.0.)
+        */
+       for (i = 0; i < pagesize; ++i)
+               *(data2 + i) = *(data2 + i) + 1;
+       data3 = malloc(pagesize);
+       if (!data3)
+               exit(1);
+       if (read(fd, data3, pagesize) != pagesize)
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               if (*(data + i) != *(data3 + i))
+                       exit(1);
+       close(fd);
+       unlink("conftestmmap");
+       exit(0);
+}
+
+EOF
+if { (eval echo configure:3025: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_func_mmap_fixed_mapped=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+                              
+   for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:3053: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3058 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3063: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+   for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3093: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3098 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+   if test "${ac_cv_func_stpcpy+set}" != "set"; then
+     for ac_func in stpcpy
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3150: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3155 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+   fi
+   if test "${ac_cv_func_stpcpy}" = "yes"; then
+     cat >> confdefs.h <<\EOF
+#define HAVE_STPCPY 1
+EOF
+
+   fi
+
+   if test $ac_cv_header_locale_h = yes; then
+    echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
+echo "configure:3212: checking for LC_MESSAGES" >&5
+if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3217 "configure"
+#include "confdefs.h"
+#include <locale.h>
+int main() {
+return LC_MESSAGES
+; return 0; }
+EOF
+if { (eval echo configure:3224: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  am_cv_val_LC_MESSAGES=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  am_cv_val_LC_MESSAGES=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6
+    if test $am_cv_val_LC_MESSAGES = yes; then
+      cat >> confdefs.h <<\EOF
+#define HAVE_LC_MESSAGES 1
+EOF
+
+    fi
+  fi
+   echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
+echo "configure:3245: checking whether NLS is requested" >&5
+        # Check whether --enable-nls or --disable-nls was given.
+if test "${enable_nls+set}" = set; then
+  enableval="$enable_nls"
+  USE_NLS=$enableval
+else
+  USE_NLS=yes
+fi
+
+    echo "$ac_t""$USE_NLS" 1>&6
+    
+
+    USE_INCLUDED_LIBINTL=no
+
+        if test "$USE_NLS" = "yes"; then
+      cat >> confdefs.h <<\EOF
+#define ENABLE_NLS 1
+EOF
+
+      echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
+echo "configure:3265: checking whether included gettext is requested" >&5
+      # Check whether --with-included-gettext or --without-included-gettext was given.
+if test "${with_included_gettext+set}" = set; then
+  withval="$with_included_gettext"
+  nls_cv_force_use_gnu_gettext=$withval
+else
+  nls_cv_force_use_gnu_gettext=no
+fi
+
+      echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6
+
+      nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+      if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+                                       nls_cv_header_intl=
+       nls_cv_header_libgt=
+       CATOBJEXT=NONE
+
+       ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
+echo "configure:3284: checking for libintl.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3289 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3294: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6
+echo "configure:3311: checking for gettext in libc" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3316 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:3323: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  gt_cv_func_gettext_libc=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  gt_cv_func_gettext_libc=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6
+
+          if test "$gt_cv_func_gettext_libc" != "yes"; then
+            echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6
+echo "configure:3339: checking for bindtextdomain in -lintl" >&5
+ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lintl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3347 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char bindtextdomain();
+
+int main() {
+bindtextdomain()
+; return 0; }
+EOF
+if { (eval echo configure:3358: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6
+echo "configure:3374: checking for gettext in libintl" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3379 "configure"
+#include "confdefs.h"
+
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:3386: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  gt_cv_func_gettext_libintl=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  gt_cv_func_gettext_libintl=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+          fi
+
+          if test "$gt_cv_func_gettext_libc" = "yes" \
+             || test "$gt_cv_func_gettext_libintl" = "yes"; then
+             cat >> confdefs.h <<\EOF
+#define HAVE_GETTEXT 1
+EOF
+
+             # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3414: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$MSGFMT" in
+  /*)
+  ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+       ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no"
+  ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+  echo "$ac_t""$MSGFMT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+             if test "$MSGFMT" != "no"; then
+               for ac_func in dcgettext
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3448: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3453 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3476: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+               # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3503: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$GMSGFMT" in
+  /*)
+  ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+  ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+  echo "$ac_t""$GMSGFMT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+               # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3539: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$XGETTEXT" in
+  /*)
+  ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+       ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+  ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+  echo "$ac_t""$XGETTEXT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+               cat > conftest.$ac_ext <<EOF
+#line 3571 "configure"
+#include "confdefs.h"
+
+int main() {
+extern int _nl_msg_cat_cntr;
+                              return _nl_msg_cat_cntr
+; return 0; }
+EOF
+if { (eval echo configure:3579: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  CATOBJEXT=.gmo
+                  DATADIRNAME=share
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CATOBJEXT=.mo
+                  DATADIRNAME=lib
+fi
+rm -f conftest*
+               INSTOBJEXT=.mo
+             fi
+           fi
+       
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+               
+        if test "$CATOBJEXT" = "NONE"; then
+                         nls_cv_use_gnu_gettext=yes
+        fi
+      fi
+
+      if test "$nls_cv_use_gnu_gettext" = "yes"; then
+                INTLOBJS="\$(GETTOBJS)"
+        # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3611: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$MSGFMT" in
+  /*)
+  ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+       ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt"
+  ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+  echo "$ac_t""$MSGFMT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+        # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3645: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$GMSGFMT" in
+  /*)
+  ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+  ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+  echo "$ac_t""$GMSGFMT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+        # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3681: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$XGETTEXT" in
+  /*)
+  ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+       ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+  ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+  echo "$ac_t""$XGETTEXT" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+        
+       USE_INCLUDED_LIBINTL=yes
+        CATOBJEXT=.gmo
+        INSTOBJEXT=.mo
+        DATADIRNAME=share
+       INTLDEPS='$(top_builddir)/../intl/libintl.a'
+       INTLLIBS=$INTLDEPS
+       LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+        nls_cv_header_intl=libintl.h
+        nls_cv_header_libgt=libgettext.h
+      fi
+
+            if test "$XGETTEXT" != ":"; then
+                       if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+         : ;
+       else
+         echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6
+         XGETTEXT=":"
+       fi
+      fi
+
+      # We need to process the po/ directory.
+      POSUB=po
+    else
+      DATADIRNAME=share
+      nls_cv_header_intl=libintl.h
+      nls_cv_header_libgt=libgettext.h
+    fi
+
+    # If this is used in GNU gettext we have to set USE_NLS to `yes'
+    # because some of the sources are only built for this goal.
+    if test "$PACKAGE" = gettext; then
+      USE_NLS=yes
+      USE_INCLUDED_LIBINTL=yes
+    fi
+
+                for lang in $ALL_LINGUAS; do
+      GMOFILES="$GMOFILES $lang.gmo"
+      POFILES="$POFILES $lang.po"
+    done
+
+        
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  
+
+   if test "x$CATOBJEXT" != "x"; then
+     if test "x$ALL_LINGUAS" = "x"; then
+       LINGUAS=
+     else
+       echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
+echo "configure:3771: checking for catalogs to be installed" >&5
+       NEW_LINGUAS=
+       for lang in ${LINGUAS=$ALL_LINGUAS}; do
+         case "$ALL_LINGUAS" in
+          *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+         esac
+       done
+       LINGUAS=$NEW_LINGUAS
+       echo "$ac_t""$LINGUAS" 1>&6
+     fi
+
+          if test -n "$LINGUAS"; then
+       for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+     fi
+   fi
+
+            if test $ac_cv_header_locale_h = yes; then
+     INCLUDE_LOCALE_H="#include <locale.h>"
+   else
+     INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>.  Take care yourself.  */"
+   fi
+   
+
+            if test -f $srcdir/po2tbl.sed.in; then
+      if test "$CATOBJEXT" = ".cat"; then
+        ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6
+echo "configure:3799: checking for linux/version.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3804 "configure"
+#include "confdefs.h"
+#include <linux/version.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3809: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  msgformat=linux
+else
+  echo "$ac_t""no" 1>&6
+msgformat=xopen
+fi
+
+
+                        sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed
+      fi
+            sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+        $srcdir/po2tbl.sed.in > po2tbl.sed
+   fi
+
+            if test "$PACKAGE" = "gettext"; then
+     GT_NO="#NO#"
+     GT_YES=
+   else
+     GT_NO=
+     GT_YES="#YES#"
+   fi
+   
+   
+
+   MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs"
+   
+
+      l=
+   
+
+            if test -d $srcdir/po; then
+      test -d po || mkdir po
+      if test "x$srcdir" != "x."; then
+        if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+           posrcprefix="$srcdir/"
+        else
+           posrcprefix="../$srcdir/"
+        fi
+      else
+        posrcprefix="../"
+      fi
+      rm -f po/POTFILES
+      sed -e "/^#/d" -e "/^\$/d" -e "s,.*,     $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+        < $srcdir/po/POTFILES.in > po/POTFILES
+   fi
+  
+
+echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
+echo "configure:3872: checking whether to enable maintainer-specific portions of Makefiles" >&5
+    # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+  enableval="$enable_maintainer_mode"
+  USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6
+  
+
+if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+  MAINT=$MAINTAINER_MODE_TRUE
+  
+
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:3895: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3900 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:3911: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_cygwin=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:3928: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3933 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:3940: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_mingw32=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:3959: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+  ac_cv_exeext=.exe
+else
+  rm -f conftest*
+  echo 'int main () { return 0; }' > conftest.$ac_ext
+  ac_cv_exeext=
+  if { (eval echo configure:3969: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+    for file in conftest.*; do
+      case $file in
+      *.c | *.o | *.obj | *.ilk | *.pdb) ;;
+      *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+      esac
+    done
+  else
+    { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+  fi
+  rm -f conftest*
+  test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile po/Makefile.in:po/Make-in gconfig.h:gconfig.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@RANLIB@%$RANLIB%g
+s%@CC@%$CC%g
+s%@LD@%$LD%g
+s%@NM@%$NM%g
+s%@USE_SYMBOL_UNDERSCORE@%$USE_SYMBOL_UNDERSCORE%g
+s%@LN_S@%$LN_S%g
+s%@DLLTOOL@%$DLLTOOL%g
+s%@AS@%$AS%g
+s%@LIBTOOL@%$LIBTOOL%g
+s%@CPP@%$CPP%g
+s%@ALLOCA@%$ALLOCA%g
+s%@USE_NLS@%$USE_NLS%g
+s%@MSGFMT@%$MSGFMT%g
+s%@GMSGFMT@%$GMSGFMT%g
+s%@XGETTEXT@%$XGETTEXT%g
+s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g
+s%@CATALOGS@%$CATALOGS%g
+s%@CATOBJEXT@%$CATOBJEXT%g
+s%@DATADIRNAME@%$DATADIRNAME%g
+s%@GMOFILES@%$GMOFILES%g
+s%@INSTOBJEXT@%$INSTOBJEXT%g
+s%@INTLDEPS@%$INTLDEPS%g
+s%@INTLLIBS@%$INTLLIBS%g
+s%@INTLOBJS@%$INTLOBJS%g
+s%@POFILES@%$POFILES%g
+s%@POSUB@%$POSUB%g
+s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g
+s%@GT_NO@%$GT_NO%g
+s%@GT_YES@%$GT_YES%g
+s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g
+s%@l@%$l%g
+s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g
+s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g
+s%@MAINT@%$MAINT%g
+s%@EXEEXT@%$EXEEXT%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile po/Makefile.in:po/Make-in"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='\([     ][      ]*\)[^  ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="gconfig.h:gconfig.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
+sed -e '/POTFILES =/r po/POTFILES' po/Makefile.in > po/Makefile
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gprof/configure.bat b/gprof/configure.bat
new file mode 100644 (file)
index 0000000..22ef37e
--- /dev/null
@@ -0,0 +1,18 @@
+@echo off\r
+echo Configuring gprof for go32\r
+rem This batch file assumes a unix-type "sed" program\r
+\r
+echo # Makefile generated by "configure.bat"> Makefile\r
+\r
+if exist config.sed del config.sed\r
+\r
+echo "/^###$/ i\                               ">>config.sed\r
+echo "MY_MACHINE=i386\                         ">>config.sed\r
+echo "CC=gcc                                   ">>config.sed\r
+\r
+echo # >> config.sed\r
+\r
+sed -e "s/^\"//" -e "s/\"$//" -e "s/[  ]*$//" config.sed > config2.sed\r
+sed -f config2.sed Makefile.in >> Makefile\r
+del config.sed\r
+del config2.sed\r
diff --git a/gprof/configure.in b/gprof/configure.in
new file mode 100644 (file)
index 0000000..b50b55d
--- /dev/null
@@ -0,0 +1,29 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.13)
+AC_INIT(gprof.c)
+
+AC_CANONICAL_SYSTEM
+
+AM_INIT_AUTOMAKE(gprof, 2.9.4)
+
+AM_PROG_LIBTOOL
+
+dnl For simplicity, we use the BFD configuration file for most
+dnl things.  However, we also need our own configuration file for
+dnl the automake PACKAGE and VERSION macros.  We don't name it
+dnl config.h, to avoid any possible confusion with the bfd config.h.
+AM_CONFIG_HEADER(gconfig.h:gconfig.in)
+
+AC_PROG_CC
+AC_PROG_INSTALL
+
+AC_ISC_POSIX
+
+ALL_LINGUAS=
+CY_GNU_GETTEXT
+
+AM_MAINTAINER_MODE
+AC_EXEEXT
+
+AC_OUTPUT(Makefile po/Makefile.in:po/Make-in,
+[sed -e '/POTFILES =/r po/POTFILES' po/Makefile.in > po/Makefile])
diff --git a/gprof/corefile.c b/gprof/corefile.c
new file mode 100644 (file)
index 0000000..a6e6f83
--- /dev/null
@@ -0,0 +1,762 @@
+#include "libiberty.h"
+#include "gprof.h"
+#include "corefile.h"
+#include "symtab.h"
+
+bfd *core_bfd;
+int core_num_syms;
+asymbol **core_syms;
+asection *core_text_sect;
+PTR core_text_space;
+
+int min_insn_size;
+int offset_to_code;
+
+/* For mapping symbols to specific .o files during file ordering.  */
+struct function_map {
+  char *function_name;
+  char *file_name;
+};
+
+struct function_map *symbol_map;
+unsigned int symbol_map_count;
+
+extern void i386_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+extern void alpha_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+extern void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+extern void tahoe_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+extern void sparc_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+
+static void
+DEFUN (read_function_mappings, (filename), const char *filename)
+{
+  FILE *file = fopen (filename, "r");
+  char dummy[1024];
+  int count = 0;
+
+  if (!file)
+    {
+      fprintf (stderr, _("%s: could not open %s.\n"), whoami, filename);
+      done (1);
+    }
+
+  /* First parse the mapping file so we know how big we need to
+     make our tables.  We also do some sanity checks at this
+     time.  */
+  while (!feof (file))
+    {
+      int matches;
+
+      matches = fscanf (file, "%[^\n:]", dummy);
+      if (!matches)
+       {
+         fprintf (stderr, _("%s: unable to parse mapping file %s.\n"),
+                  whoami, filename);
+         done (1);
+       }
+
+      /* Just skip messages about files with no symbols.  */
+      if (!strncmp (dummy, "No symbols in ", 14))
+       {
+         fscanf (file, "\n");
+         continue;
+       }
+
+      /* Don't care what else is on this line at this point.  */
+      fscanf (file, "%[^\n]\n", dummy);
+      count++;
+    }
+
+  /* Now we know how big we need to make our table.  */
+  symbol_map = ((struct function_map *)
+               xmalloc (count * sizeof (struct function_map)));
+
+  /* Rewind the input file so we can read it again.  */
+  rewind (file);
+
+  /* Read each entry and put it into the table.  */
+  count = 0;
+  while (!feof (file))
+    {
+      int matches;
+      char *tmp;
+
+      matches = fscanf (file, "%[^\n:]", dummy);
+      if (!matches)
+       {
+         fprintf (stderr, _("%s: unable to parse mapping file %s.\n"),
+                  whoami, filename);
+         done (1);
+       }
+
+      /* Just skip messages about files with no symbols.  */
+      if (!strncmp (dummy, "No symbols in ", 14))
+       {
+         fscanf (file, "\n");
+         continue;
+       }
+
+      /* dummy has the filename, go ahead and copy it.  */
+      symbol_map[count].file_name = xmalloc (strlen (dummy) + 1);
+      strcpy (symbol_map[count].file_name, dummy);
+
+      /* Now we need the function name.  */
+      fscanf (file, "%[^\n]\n", dummy);
+      tmp = strrchr (dummy, ' ') + 1;
+      symbol_map[count].function_name = xmalloc (strlen (tmp) + 1);
+      strcpy (symbol_map[count].function_name, tmp);
+      count++;
+    }
+
+  /* Record the size of the map table for future reference.  */
+  symbol_map_count = count;
+}
+
+void
+DEFUN (core_init, (a_out_name), const char *a_out_name)
+{
+  core_bfd = bfd_openr (a_out_name, 0);
+
+  if (!core_bfd)
+    {
+      perror (a_out_name);
+      done (1);
+    }
+
+  if (!bfd_check_format (core_bfd, bfd_object))
+    {
+      fprintf (stderr, _("%s: %s: not in a.out format\n"), whoami, a_out_name);
+      done (1);
+    }
+
+  /* get core's text section: */
+  core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
+  if (!core_text_sect)
+    {
+      core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
+      if (!core_text_sect)
+       {
+         fprintf (stderr, _("%s: can't find .text section in %s\n"),
+                  whoami, a_out_name);
+         done (1);
+       }
+    }
+
+  /* read core's symbol table: */
+
+  /* this will probably give us more than we need, but that's ok:  */
+  core_num_syms = bfd_get_symtab_upper_bound (core_bfd);
+  if (core_num_syms < 0)
+    {
+      fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name,
+              bfd_errmsg (bfd_get_error ()));
+      done (1);
+    }
+
+  core_syms = (asymbol **) xmalloc (core_num_syms);
+  core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
+  if (core_num_syms < 0)
+    {
+      fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name,
+              bfd_errmsg (bfd_get_error ()));
+      done (1);
+    }
+
+  min_insn_size = 1;
+  offset_to_code = 0;
+
+  switch (bfd_get_arch (core_bfd))
+    {
+    case bfd_arch_vax:
+    case bfd_arch_tahoe:
+      offset_to_code = 2;
+      break;
+
+    case bfd_arch_alpha:
+      min_insn_size = 4;
+      break;
+
+    default:
+      break;
+    }
+
+  if (function_mapping_file)
+    read_function_mappings (function_mapping_file);
+}
+
+
+/*
+ * Read in the text space of an a.out file
+ */
+void
+DEFUN (core_get_text_space, (core_bfd), bfd * core_bfd)
+{
+  core_text_space = (PTR) malloc (core_text_sect->_raw_size);
+
+  if (!core_text_space)
+    {
+      fprintf (stderr, _("%s: ran out room for %ld bytes of text space\n"),
+              whoami, core_text_sect->_raw_size);
+      done (1);
+    }
+  if (!bfd_get_section_contents (core_bfd, core_text_sect, core_text_space,
+                                0, core_text_sect->_raw_size))
+    {
+      bfd_perror ("bfd_get_section_contents");
+      free (core_text_space);
+      core_text_space = 0;
+    }
+  if (!core_text_space)
+    {
+      fprintf (stderr, _("%s: can't do -c\n"), whoami);
+    }
+}
+
+
+void
+DEFUN (find_call, (parent, p_lowpc, p_highpc),
+       Sym * parent AND bfd_vma p_lowpc AND bfd_vma p_highpc)
+{
+  switch (bfd_get_arch (core_bfd))
+    {
+    case bfd_arch_i386:
+      i386_find_call (parent, p_lowpc, p_highpc);
+      break;
+
+    case bfd_arch_alpha:
+      alpha_find_call (parent, p_lowpc, p_highpc);
+      break;
+
+    case bfd_arch_vax:
+      vax_find_call (parent, p_lowpc, p_highpc);
+      break;
+
+    case bfd_arch_sparc:
+      sparc_find_call (parent, p_lowpc, p_highpc);
+      break;
+
+    case bfd_arch_tahoe:
+      tahoe_find_call (parent, p_lowpc, p_highpc);
+      break;
+
+    default:
+      fprintf (stderr, _("%s: -c not supported on architecture %s\n"),
+              whoami, bfd_printable_name(core_bfd));
+
+      /* Don't give the error more than once.  */
+      ignore_direct_calls = FALSE;
+    }
+}
+
+/*
+ * Return class of symbol SYM.  The returned class can be any of:
+ *      0   -> symbol is not interesting to us
+ *      'T' -> symbol is a global name
+ *      't' -> symbol is a local (static) name
+ */
+static int
+DEFUN (core_sym_class, (sym), asymbol * sym)
+{
+  symbol_info syminfo;
+  const char *name;
+  char sym_prefix;
+  int i;
+
+  if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
+    {
+      return 0;
+    }
+
+  /*
+   * Must be a text symbol, and static text symbols don't qualify if
+   * ignore_static_funcs set.
+   */
+  if (ignore_static_funcs && (sym->flags & BSF_LOCAL))
+    {
+      DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n",
+                             sym->name));
+      return 0;
+    }
+
+  bfd_get_symbol_info (core_bfd, sym, &syminfo);
+  i = syminfo.type;
+
+  if (i == 'T')
+    {
+      return i;                        /* it's a global symbol */
+    }
+
+  if (i == 'W')
+    {
+      /* Treat weak symbols as text symbols.  FIXME: a weak symbol may
+         also be a data symbol.  */
+      return 'T';
+    }
+
+  if (i != 't')
+    {
+      /* not a static text symbol */
+      DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
+                             sym->name, i));
+      return 0;
+    }
+
+  /* do some more filtering on static function-names: */
+
+  if (ignore_static_funcs)
+    {
+      return 0;
+    }
+  /*
+   * Can't zero-length name or funny characters in name, where
+   * `funny' includes: `.' (.o file names) and `$' (Pascal labels).
+   */
+  if (!sym->name || sym->name[0] == '\0')
+    {
+      return 0;
+    }
+
+  for (name = sym->name; *name; ++name)
+    {
+      if (*name == '.' || *name == '$')
+       {
+         return 0;
+       }
+    }
+  /*
+   * On systems where the C compiler adds an underscore to all
+   * names, static names without underscores seem usually to be
+   * labels in hand written assembler in the library.  We don't want
+   * these names.  This is certainly necessary on a Sparc running
+   * SunOS 4.1 (try profiling a program that does a lot of
+   * division). I don't know whether it has harmful side effects on
+   * other systems.  Perhaps it should be made configurable.
+   */
+  sym_prefix = bfd_get_symbol_leading_char (core_bfd);
+  if ((sym_prefix && sym_prefix != sym->name[0])
+  /*
+   * GCC may add special symbols to help gdb figure out the file
+   * language.  We want to ignore these, since sometimes they mask
+   * the real function.  (dj@ctron)
+   */
+      || !strncmp (sym->name, "__gnu_compiled", 14)
+      || !strncmp (sym->name, "___gnu_compiled", 15))
+    {
+      return 0;
+    }
+
+  /* If the object file supports marking of function symbols, then we can
+     zap anything that doesn't have BSF_FUNCTION set.  */
+  if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0)
+    return 0;
+
+  return 't';                  /* it's a static text symbol */
+}
+
+
+/*
+ * Get whatever source info we can get regarding address ADDR:
+ */
+static bool
+DEFUN (get_src_info, (addr, filename, name, line_num),
+       bfd_vma addr AND const char **filename AND const char **name
+       AND int *line_num)
+{
+  const char *fname = 0, *func_name = 0;
+  int l = 0;
+
+  if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
+                            addr - core_text_sect->vma,
+                            &fname, &func_name, (unsigned int *) &l)
+      && fname && func_name && l)
+    {
+      DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
+                             addr, fname, l, func_name));
+      *filename = fname;
+      *name = func_name;
+      *line_num = l;
+      return TRUE;
+    }
+  else
+    {
+      DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n",
+                             (long) addr, fname ? fname : "<unknown>", l,
+                             func_name ? func_name : "<unknown>"));
+      return FALSE;
+    }
+}
+
+
+/*
+ * Read in symbol table from core.  One symbol per function is
+ * entered.
+ */
+void
+DEFUN (core_create_function_syms, (core_bfd), bfd * core_bfd)
+{
+  bfd_vma min_vma = ~0, max_vma = 0;
+  int class;
+  long i, found, skip;
+  unsigned int j;
+
+  /* pass 1 - determine upper bound on number of function names: */
+  symtab.len = 0;
+  for (i = 0; i < core_num_syms; ++i)
+    {
+      if (!core_sym_class (core_syms[i]))
+       {
+         continue;
+       }
+
+      /* This should be replaced with a binary search or hashed
+        search.  Gross. 
+
+        Don't create a symtab entry for a function that has
+        a mapping to a file, unless it's the first function
+        in the file.  */
+      skip = 0;
+      for (j = 0; j < symbol_map_count; j++)
+       if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
+         {
+           if (j > 0 && ! strcmp (symbol_map [j].file_name,
+                                  symbol_map [j - 1].file_name))
+             skip = 1;
+           break;
+         }
+      if (!skip)
+        ++symtab.len;
+    }
+
+  if (symtab.len == 0)
+    {
+      fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name);
+      done (1);
+    }
+
+  /* the "+ 2" is for the sentinels: */
+  symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym));
+
+  /* pass 2 - create symbols: */
+
+  symtab.limit = symtab.base;
+  for (i = 0; i < core_num_syms; ++i)
+    {
+      class = core_sym_class (core_syms[i]);
+      if (!class)
+       {
+         DBG (AOUTDEBUG,
+              printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
+                      core_syms[i]->value, core_syms[i]->name));
+         continue;
+       }
+      /* This should be replaced with a binary search or hashed
+        search.  Gross.   */
+
+      skip = 0;
+      found = 0;
+      for (j = 0; j < symbol_map_count; j++)
+       if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
+         {
+           if (j > 0 && ! strcmp (symbol_map [j].file_name,
+                                  symbol_map [j - 1].file_name))
+             skip = 1;
+           else
+             found = j;
+           break;
+         }
+
+      if (skip)
+       continue;
+
+      sym_init (symtab.limit);
+
+      /* symbol offsets are always section-relative: */
+
+      symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma;
+      if (symbol_map_count
+         && !strcmp (core_syms[i]->name, symbol_map[found].function_name))
+       {
+         symtab.limit->name = symbol_map[found].file_name;
+         symtab.limit->mapped = 1;
+       }
+      else
+       {
+         symtab.limit->name = core_syms[i]->name;
+         symtab.limit->mapped = 0;
+       }
+
+      /* Lookup filename and line number, if we can */
+
+      {
+       const char *filename, *func_name;
+       
+       if (get_src_info (symtab.limit->addr, &filename, &func_name,
+                         &symtab.limit->line_num))
+         {
+           symtab.limit->file = source_file_lookup_path (filename);
+
+           /* FIXME: Checking __osf__ here does not work with a cross
+               gprof.  */
+#ifdef __osf__
+           /*
+            * Suppress symbols that are not function names.  This is
+            * useful to suppress code-labels and aliases.
+            *
+            * This is known to be useful under DEC's OSF/1.  Under SunOS 4.x,
+            * labels do not appear in the symbol table info, so this isn't
+            * necessary.
+            */
+
+           if (strcmp (symtab.limit->name, func_name) != 0)
+             {
+               /*
+                * The symbol's address maps to a different name, so
+                * it can't be a function-entry point.  This happens
+                * for labels, for example.
+                */
+               DBG (AOUTDEBUG,
+                    printf ("[core_create_function_syms: rej %s (maps to %s)\n",
+                            symtab.limit->name, func_name));
+               continue;
+             }
+#endif
+         }
+      }
+
+      symtab.limit->is_func = TRUE;
+      symtab.limit->is_bb_head = TRUE;
+      if (class == 't')
+       {
+         symtab.limit->is_static = TRUE;
+       }
+
+      min_vma = MIN (symtab.limit->addr, min_vma);
+      max_vma = MAX (symtab.limit->addr, max_vma);
+
+      /*
+       * If we see "main" without an initial '_', we assume names
+       * are *not* prefixed by '_'.
+       */
+      if (symtab.limit->name[0] == 'm' && discard_underscores
+         && strcmp (symtab.limit->name, "main") == 0)
+       {
+         discard_underscores = 0;
+       }
+
+      DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
+                             (long) (symtab.limit - symtab.base),
+                             symtab.limit->name, symtab.limit->addr));
+      ++symtab.limit;
+    }
+
+  /* create sentinels: */
+
+  sym_init (symtab.limit);
+  symtab.limit->name = "<locore>";
+  symtab.limit->addr = 0;
+  symtab.limit->end_addr = min_vma - 1;
+  ++symtab.limit;
+
+  sym_init (symtab.limit);
+  symtab.limit->name = "<hicore>";
+  symtab.limit->addr = max_vma + 1;
+  symtab.limit->end_addr = ~0;
+  ++symtab.limit;
+
+  symtab.len = symtab.limit - symtab.base;
+  symtab_finalize (&symtab);
+}
+
+
+/*
+ * Read in symbol table from core.  One symbol per line of source code
+ * is entered.
+ */
+void
+DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd)
+{
+  char *prev_name, *prev_filename;
+  int prev_name_len, prev_filename_len;
+  bfd_vma vma, min_vma = ~0, max_vma = 0;
+  bfd_vma offset;
+  Sym *prev, dummy, *sentinel, *sym;
+  const char *filename;
+  int prev_line_num;
+  Sym_Table ltab;
+  /*
+   * Create symbols for functions as usual.  This is necessary in
+   * cases where parts of a program were not compiled with -g.  For
+   * those parts we still want to get info at the function level:
+   */
+  core_create_function_syms (core_bfd);
+
+  /* pass 1 - counter number of symbols: */
+
+  /*
+   * To find all line information, walk through all possible
+   * text-space addresses (one by one!) and get the debugging
+   * info for each address.  When the debugging info changes,
+   * it is time to create a new symbol.
+   *
+   * Of course, this is rather slow and it would be better if
+   * bfd would provide an iterator for enumerating all line infos
+   */
+  prev_name_len = PATH_MAX;
+  prev_filename_len = PATH_MAX;
+  prev_name = xmalloc (prev_name_len);
+  prev_filename = xmalloc (prev_filename_len);
+  ltab.len = 0;
+  prev_line_num = 0;
+  for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size)
+    {
+      int len;
+
+      vma = core_text_sect->vma + offset;
+      if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
+         || (prev_line_num == dummy.line_num
+             && prev_name != NULL
+             && strcmp (prev_name, dummy.name) == 0
+             && strcmp (prev_filename, filename) == 0))
+       {
+         continue;
+       }
+
+      ++ltab.len;
+      prev_line_num = dummy.line_num;
+
+      len = strlen (dummy.name);
+      if (len >= prev_name_len)
+       {
+         prev_name_len = len + 1024;
+         free (prev_name);
+         prev_name = xmalloc (prev_name_len);
+       }
+      strcpy (prev_name, dummy.name);
+
+      len = strlen (filename);
+      if (len >= prev_filename_len)
+       {
+         prev_filename_len = len + 1024;
+         free (prev_filename);
+         prev_filename = xmalloc (prev_filename_len);
+       }
+      strcpy (prev_filename, filename);
+
+      min_vma = MIN (vma, min_vma);
+      max_vma = MAX (vma, max_vma);
+    }
+
+  free (prev_name);
+  free (prev_filename);
+
+  /* make room for function symbols, too: */
+  ltab.len += symtab.len;
+  ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
+  ltab.limit = ltab.base;
+
+  /* pass 2 - create symbols: */
+
+  /* We now set is_static as we go along, rather than by running
+     through the symbol table at the end.
+
+     The old way called symtab_finalize before the is_static pass,
+     causing a problem since symtab_finalize uses is_static as part of
+     its address conflict resolution algorithm.  Since global symbols
+     were prefered over static symbols, and all line symbols were
+     global at that point, static function names that conflicted with
+     their own line numbers (static, but labeled as global) were
+     rejected in favor of the line num.
+
+     This was not the desired functionality.  We always want to keep
+     our function symbols and discard any conflicting line symbols.
+     Perhaps symtab_finalize should be modified to make this
+     distinction as well, but the current fix works and the code is a
+     lot cleaner now.  */
+
+  prev = 0;
+  for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size)
+    {
+      sym_init (ltab.limit);
+      if (!get_src_info (core_text_sect->vma + offset, &filename,
+                        &ltab.limit->name, &ltab.limit->line_num)
+         || (prev && prev->line_num == ltab.limit->line_num
+             && strcmp (prev->name, ltab.limit->name) == 0
+             && strcmp (prev->file->name, filename) == 0))
+       {
+         continue;
+       }
+
+      /* make name pointer a malloc'ed string: */
+      ltab.limit->name = xstrdup (ltab.limit->name);
+      ltab.limit->file = source_file_lookup_path (filename);
+
+      ltab.limit->addr = core_text_sect->vma + offset;
+
+      /* Set is_static based on the enclosing function, using either:
+       * 1) the previous symbol, if it's from the same function, or
+       * 2) a symtab lookup
+       */
+
+      if (prev && ltab.limit->file == prev->file &&
+         strcmp (ltab.limit->name, prev->name) == 0)
+       {
+         ltab.limit->is_static = prev->is_static;
+       }
+      else
+       {
+         sym = sym_lookup(&symtab, ltab.limit->addr);
+         ltab.limit->is_static = sym->is_static;
+       }
+
+      prev = ltab.limit;
+
+      /*
+       * If we see "main" without an initial '_', we assume names
+       * are *not* prefixed by '_'.
+       */
+      if (ltab.limit->name[0] == 'm' && discard_underscores
+         && strcmp (ltab.limit->name, "main") == 0)
+       {
+         discard_underscores = 0;
+       }
+
+      DBG (AOUTDEBUG, printf ("[core_create_line_syms] %d %s 0x%lx\n",
+                             ltab.limit - ltab.base, ltab.limit->name,
+                             ltab.limit->addr));
+      ++ltab.limit;
+    }
+
+  /* update sentinels: */
+
+  sentinel = sym_lookup (&symtab, 0);
+  if (strcmp (sentinel->name, "<locore>") == 0
+      && min_vma <= sentinel->end_addr)
+    {
+      sentinel->end_addr = min_vma - 1;
+    }
+
+  sentinel = sym_lookup (&symtab, ~0);
+  if (strcmp (sentinel->name, "<hicore>") == 0 && max_vma >= sentinel->addr)
+    {
+      sentinel->addr = max_vma + 1;
+    }
+
+  /* copy in function symbols: */
+  memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
+  ltab.limit += symtab.len;
+
+  if ((unsigned int) (ltab.limit - ltab.base) != ltab.len)
+    {
+      fprintf (stderr,
+              _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"),
+              whoami, ltab.len, (long) (ltab.limit - ltab.base));
+      done (1);
+    }
+
+  /* finalize ltab and make it symbol table: */
+
+  symtab_finalize (&ltab);
+  free (symtab.base);
+  symtab = ltab;
+
+}
diff --git a/gprof/corefile.h b/gprof/corefile.h
new file mode 100644 (file)
index 0000000..b396f85
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef corefile_h
+#define corefile_h
+
+#include "bfd.h"
+
+extern bfd *core_bfd;          /* bfd for core-file */
+extern int core_num_syms;      /* # of entries in symbol-table */
+extern asymbol **core_syms;    /* symbol table in a.out */
+extern asection *core_text_sect;       /* core text section */
+extern PTR core_text_space;    /* text space of a.out in core */
+
+extern int min_insn_size;      /* size of smallest instruction, in bytes */
+extern int offset_to_code;     /* offset (in bytes) of code from entry
+                                  address of routine */
+
+extern void core_init PARAMS ((const char *a_out_name));
+extern void core_get_text_space PARAMS ((bfd * core_bfd));
+extern void core_create_function_syms PARAMS ((bfd * core_bfd));
+extern void core_create_line_syms PARAMS ((bfd * core_bfd));
+
+#endif /* corefile_h */
diff --git a/gprof/flat_bl.m b/gprof/flat_bl.m
new file mode 100644 (file)
index 0000000..db2871a
--- /dev/null
@@ -0,0 +1,27 @@
+
+ %         the percentage of the total running time of the
+time       program used by this function.
+
+cumulative a running sum of the number of seconds accounted
+ seconds   for by this function and those listed above it.
+
+ self      the number of seconds accounted for by this
+seconds    function alone.  This is the major sort for this
+           listing.
+
+calls      the number of times this function was invoked, if
+           this function is profiled, else blank.
+ self      the average number of milliseconds spent in this
+ms/call    function per call, if this function is profiled,
+          else blank.
+
+ total     the average number of milliseconds spent in this
+ms/call    function and its descendents per call, if this 
+          function is profiled, else blank.
+
+name       the name of the function.  This is the minor sort
+           for this listing. The index shows the location of
+          the function in the gprof listing. If the index is
+          in parenthesis it shows where it would appear in
+          the gprof listing if it were to be printed.
diff --git a/gprof/fsf_callg_bl.m b/gprof/fsf_callg_bl.m
new file mode 100644 (file)
index 0000000..7e16821
--- /dev/null
@@ -0,0 +1,83 @@
+
+ This table describes the call tree of the program, and was sorted by
+ the total amount of time spent in each function and its children.
+
+ Each entry in this table consists of several lines.  The line with the
+ index number at the left hand margin lists the current function.
+ The lines above it list the functions that called this function,
+ and the lines below it list the functions this one called.
+ This line lists:
+     index     A unique number given to each element of the table.
+               Index numbers are sorted numerically.
+               The index number is printed next to every function name so
+               it is easier to look up where the function in the table.
+
+     % time    This is the percentage of the `total' time that was spent
+               in this function and its children.  Note that due to
+               different viewpoints, functions excluded by options, etc,
+               these numbers will NOT add up to 100%.
+
+     self      This is the total amount of time spent in this function.
+
+     children  This is the total amount of time propagated into this
+               function by its children.
+
+     called    This is the number of times the function was called.
+               If the function called itself recursively, the number
+               only includes non-recursive calls, and is followed by
+               a `+' and the number of recursive calls.
+
+     name      The name of the current function.  The index number is
+               printed after it.  If the function is a member of a
+               cycle, the cycle number is printed between the
+               function's name and the index number.
+
+
+ For the function's parents, the fields have the following meanings:
+
+     self      This is the amount of time that was propagated directly
+               from the function into this parent.
+
+     children  This is the amount of time that was propagated from
+               the function's children into this parent.
+
+     called    This is the number of times this parent called the
+               function `/' the total number of times the function
+               was called.  Recursive calls to the function are not
+               included in the number after the `/'.
+
+     name      This is the name of the parent.  The parent's index
+               number is printed after it.  If the parent is a
+               member of a cycle, the cycle number is printed between
+               the name and the index number.
+
+ If the parents of the function cannot be determined, the word
+ `<spontaneous>' is printed in the `name' field, and all the other
+ fields are blank.
+
+ For the function's children, the fields have the following meanings:
+
+     self      This is the amount of time that was propagated directly
+               from the child into the function.
+
+     children  This is the amount of time that was propagated from the
+               child's children to the function.
+
+     called    This is the number of times the function called
+               this child `/' the total number of times the child
+               was called.  Recursive calls by the child are not
+               listed in the number after the `/'.
+
+     name      This is the name of the child.  The child's index
+               number is printed after it.  If the child is a
+               member of a cycle, the cycle number is printed
+               between the name and the index number.
+
+ If there are any cycles (circles) in the call graph, there is an
+ entry for the cycle-as-a-whole.  This entry shows who called the
+ cycle (as parents) and the members of the cycle (as children.)
+ The `+' recursive calls entry shows the number of function calls that
+ were internal to the cycle, and the calls entry for each member shows,
+ for that member, how many times it was called from other members of
+ the cycle.
+
diff --git a/gprof/gconfig.in b/gprof/gconfig.in
new file mode 100644 (file)
index 0000000..347e8e0
--- /dev/null
@@ -0,0 +1,129 @@
+/* gconfig.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if using alloca.c.  */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+   This function is required for alloca.c support on those systems.  */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro.  */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have a working `mmap' system call.  */
+#undef HAVE_MMAP
+
+/* Define as __inline if that's what the C compiler calls it.  */
+#undef inline
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if you have the __argz_count function.  */
+#undef HAVE___ARGZ_COUNT
+
+/* Define if you have the __argz_next function.  */
+#undef HAVE___ARGZ_NEXT
+
+/* Define if you have the __argz_stringify function.  */
+#undef HAVE___ARGZ_STRINGIFY
+
+/* Define if you have the dcgettext function.  */
+#undef HAVE_DCGETTEXT
+
+/* Define if you have the getcwd function.  */
+#undef HAVE_GETCWD
+
+/* Define if you have the getpagesize function.  */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the munmap function.  */
+#undef HAVE_MUNMAP
+
+/* Define if you have the putenv function.  */
+#undef HAVE_PUTENV
+
+/* Define if you have the setenv function.  */
+#undef HAVE_SETENV
+
+/* Define if you have the setlocale function.  */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the stpcpy function.  */
+#undef HAVE_STPCPY
+
+/* Define if you have the strcasecmp function.  */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the strchr function.  */
+#undef HAVE_STRCHR
+
+/* Define if you have the <argz.h> header file.  */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file.  */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file.  */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <nl_types.h> header file.  */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <sys/param.h> header file.  */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <values.h> header file.  */
+#undef HAVE_VALUES_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
+/* Define if you have the stpcpy function */
+#undef HAVE_STPCPY
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define to 1 if NLS is requested */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+#undef HAVE_GETTEXT
+
diff --git a/gprof/gen-c-prog.awk b/gprof/gen-c-prog.awk
new file mode 100644 (file)
index 0000000..b59c1f8
--- /dev/null
@@ -0,0 +1,26 @@
+NR == 1        {
+    FS="\"";
+    print "/* ==> Do not modify this file!!  It is created automatically"
+    printf "   from %s using the gen-c-prog.awk script.  <== */\n\n", FILE
+    print "#include <stdio.h>"
+}
+
+       {
+         if (curfun != FUNCTION)
+           {
+             if (curfun)
+               print "}"
+             curfun = FUNCTION
+             print ""
+             print "void";
+             printf "%s (file)\n", FUNCTION
+             print "     FILE *file;";
+             print "{";
+           }
+         printf "  fputs (\"";
+         for (i = 1; i < NF; i++)
+           printf "%s\\\"", $i;
+         printf "%s\\n\", file);\n", $NF;
+}
+
+END    { print "}" }
diff --git a/gprof/gmon.h b/gprof/gmon.h
new file mode 100644 (file)
index 0000000..541fa4d
--- /dev/null
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)gmon.h      5.2 (Berkeley) 5/6/91
+ */
+#ifndef gmon_h
+#define gmon_h
+
+struct raw_phdr
+  {
+    /* FIXME: Checking a host compiler define means that we can't use
+       a cross gprof to the alpha.  */
+#ifdef __alpha__
+    char low_pc[8];            /* base pc address of sample buffer */
+    char high_pc[8];           /* max pc address of sampled buffer */
+#else
+    char low_pc[4];            /* base pc address of sample buffer */
+    char high_pc[4];           /* max pc address of sampled buffer */
+#endif
+    char ncnt[4];              /* size of sample buffer (plus this header) */
+
+    char version[4];           /* version number */
+    char profrate[4];          /* profiling clock rate */
+    char spare[3*4];           /* reserved */
+  };
+
+#define GMONVERSION     0x00051879
+
+struct old_raw_phdr
+  {
+    /* FIXME: Checking a host compiler define means that we can't use
+       a cross gprof to the alpha.  */
+#ifdef __alpha__
+    char low_pc[8];            /* base pc address of sample buffer */
+    char high_pc[8];           /* max pc address of sampled buffer */
+#else
+    char low_pc[4];            /* base pc address of sample buffer */
+    char high_pc[4];           /* max pc address of sampled buffer */
+#endif
+    char ncnt[4];              /* size of sample buffer (plus this header) */
+
+    /* FIXME: Checking host compiler defines here means that we can't
+       use a cross gprof alpha OSF.  */
+#if defined (__alpha__) && defined (__osf__)
+    /*
+     * DEC's OSF v3.0 uses 4 bytes of padding to bring the header to
+     * a size that is a multiple of 8.
+     */
+    char pad[4];
+#endif
+  };
+
+/*
+ * Histogram counters are unsigned shorts:
+ */
+#define        HISTCOUNTER unsigned short
+
+/*
+ * Fraction of text space to allocate for histogram counters here, 1/2:
+ */
+#define        HISTFRACTION    2
+
+/*
+ * Fraction of text space to allocate for from hash buckets.  The
+ * value of HASHFRACTION is based on the minimum number of bytes of
+ * separation between two subroutine call points in the object code.
+ * Given MIN_SUBR_SEPARATION bytes of separation the value of
+ * HASHFRACTION is calculated as:
+ *
+ *      HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
+ *
+ * For the VAX, the shortest two call sequence is:
+ *
+ *      calls   $0,(r0)
+ *      calls   $0,(r0)
+ *
+ * which is separated by only three bytes, thus HASHFRACTION is 
+ * calculated as:
+ *
+ *      HASHFRACTION = 3 / (2 * 2 - 1) = 1
+ *
+ * Note that the division above rounds down, thus if MIN_SUBR_FRACTION
+ * is less than three, this algorithm will not work!
+ */
+#define        HASHFRACTION 1
+
+/*
+ * Percent of text space to allocate for tostructs with a minimum:
+ */
+#define ARCDENSITY     2
+#define MINARCS                50
+
+struct tostruct
+  {
+    char *selfpc;
+    int count;
+    unsigned short link;
+  };
+
+/*
+ * A raw arc, with pointers to the calling site and the called site
+ * and a count.  Everything is defined in terms of characters so
+ * as to get a packed representation (otherwise, different compilers
+ * might introduce different padding):
+ */
+struct raw_arc
+  {
+    /* FIXME: Checking a host compiler define means that we can't use
+       a cross gprof to the alpha.  */
+#ifdef __alpha__
+    char from_pc[8];
+    char self_pc[8];
+    char count[8];
+#else
+    char from_pc[4];
+    char self_pc[4];
+    char count[4];
+#endif
+  };
+
+/*
+ * General rounding functions:
+ */
+#define ROUNDDOWN(x,y) (((x)/(y))*(y))
+#define ROUNDUP(x,y)   ((((x)+(y)-1)/(y))*(y))
+
+#endif /* gmon_h */
diff --git a/gprof/gmon_io.c b/gprof/gmon_io.c
new file mode 100644 (file)
index 0000000..ff294f5
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * Input and output from/to gmon.out files.
+ */
+#include "cg_arcs.h"
+#include "basic_blocks.h"
+#include "bfd.h"
+#include "corefile.h"
+#include "call_graph.h"
+#include "gmon_io.h"
+#include "gmon_out.h"
+#include "gmon.h"              /* fetch header for old format */
+#include "gprof.h"
+#include "hertz.h"
+#include "hist.h"
+#include "libiberty.h"
+
+int gmon_input = 0;
+int gmon_file_version = 0;     /* 0 == old (non-versioned) file format */
+
+/*
+ * This probably ought to be in libbfd.
+ */
+bfd_vma
+DEFUN (get_vma, (abfd, addr), bfd * abfd AND bfd_byte * addr)
+{
+  switch (sizeof (char*))
+    {
+    case 4:
+      return bfd_get_32 (abfd, addr);
+    case 8:
+      return bfd_get_64 (abfd, addr);
+    default:
+      fprintf (stderr, _("%s: bfd_vma has unexpected size of %ld bytes\n"),
+              whoami, (long) sizeof (char*));
+      done (1);
+    }
+}
+
+
+/*
+ * This probably ought to be in libbfd.
+ */
+void
+DEFUN (put_vma, (abfd, val, addr), bfd * abfd AND bfd_vma val AND bfd_byte * addr)
+{
+  switch (sizeof (char*))
+    {
+    case 4:
+      bfd_put_32 (abfd, val, addr);
+      break;
+    case 8:
+      bfd_put_64 (abfd, val, addr);
+      break;
+    default:
+      fprintf (stderr, _("%s: bfd_vma has unexpected size of %ld bytes\n"),
+              whoami, (long) sizeof (char*));
+      done (1);
+    }
+}
+
+
+void
+DEFUN (gmon_out_read, (filename), const char *filename)
+{
+  FILE *ifp;
+  struct gmon_hdr ghdr;
+  unsigned char tag;
+  int nhist = 0, narcs = 0, nbbs = 0;
+
+  /* open gmon.out file: */
+
+  if (strcmp (filename, "-") == 0)
+    {
+      ifp = stdin;
+    }
+  else
+    {
+      ifp = fopen (filename, FOPEN_RB);
+      if (!ifp)
+       {
+         perror (filename);
+         done (1);
+       }
+    }
+  if (fread (&ghdr, sizeof (struct gmon_hdr), 1, ifp) != 1)
+    {
+      fprintf (stderr, _("%s: file too short to be a gmon file\n"),
+              filename);
+      done (1);
+    }
+
+  if ((file_format == FF_MAGIC) ||
+      (file_format == FF_AUTO && !strncmp (&ghdr.cookie[0], GMON_MAGIC, 4)))
+    {
+      if (file_format == FF_MAGIC && strncmp (&ghdr.cookie[0], GMON_MAGIC, 4))
+       {
+         fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
+                  whoami, filename);
+         done (1);
+       }
+
+      /* right magic, so it's probably really a new gmon.out file */
+
+      gmon_file_version = bfd_get_32 (core_bfd, (bfd_byte *) ghdr.version);
+      if (gmon_file_version != GMON_VERSION && gmon_file_version != 0)
+       {
+         fprintf (stderr,
+                  _("%s: file `%s' has unsupported version %d\n"),
+                  whoami, filename, gmon_file_version);
+         done (1);
+       }
+
+      /* read in all the records: */
+      while (fread (&tag, sizeof (tag), 1, ifp) == 1)
+       {
+         switch (tag)
+           {
+           case GMON_TAG_TIME_HIST:
+             ++nhist;
+             gmon_input |= INPUT_HISTOGRAM;
+             hist_read_rec (ifp, filename);
+             break;
+
+           case GMON_TAG_CG_ARC:
+             ++narcs;
+             gmon_input |= INPUT_CALL_GRAPH;
+             cg_read_rec (ifp, filename);
+             break;
+
+           case GMON_TAG_BB_COUNT:
+             ++nbbs;
+             gmon_input |= INPUT_BB_COUNTS;
+             bb_read_rec (ifp, filename);
+             break;
+
+           default:
+             fprintf (stderr,
+                      _("%s: %s: found bad tag %d (file corrupted?)\n"),
+                      whoami, filename, tag);
+             done (1);
+           }
+       }
+    }
+  else if (file_format == FF_AUTO
+          || file_format == FF_BSD
+          || file_format == FF_BSD44)
+    {
+      struct hdr
+      {
+       bfd_vma low_pc;
+       bfd_vma high_pc;
+       int ncnt;
+      };
+      int i, samp_bytes, header_size;
+      unsigned long count;
+      bfd_vma from_pc, self_pc;
+      struct raw_arc raw_arc;
+      struct raw_phdr raw;
+      static struct hdr h;
+      UNIT raw_bin_count;
+      struct hdr tmp;
+
+      /*
+       * Information from a gmon.out file is in two parts: an array of
+       * sampling hits within pc ranges, and the arcs.
+       */
+      gmon_input = INPUT_HISTOGRAM | INPUT_CALL_GRAPH;
+
+      /*
+       * This fseek() ought to work even on stdin as long as it's
+       * not an interactive device (heck, is there anybody who would
+       * want to type in a gmon.out at the terminal?).
+       */
+      if (fseek (ifp, 0, SEEK_SET) < 0)
+       {
+         perror (filename);
+         done (1);
+       }
+      if (fread (&raw, 1, sizeof (struct raw_phdr), ifp)
+         != sizeof (struct raw_phdr))
+       {
+         fprintf (stderr, _("%s: file too short to be a gmon file\n"),
+                  filename);
+         done (1);
+       }
+      tmp.low_pc = get_vma (core_bfd, (bfd_byte *) &raw.low_pc[0]);
+      tmp.high_pc = get_vma (core_bfd, (bfd_byte *) &raw.high_pc[0]);
+      tmp.ncnt = bfd_get_32 (core_bfd, (bfd_byte *) &raw.ncnt[0]);
+
+      if (bfd_get_32 (core_bfd, (bfd_byte *) &raw.version[0])
+         == GMONVERSION)
+       {
+         int profrate;
+
+         /* 4.4BSD format header.  */
+
+         profrate = bfd_get_32 (core_bfd, (bfd_byte *) &raw.profrate[0]);
+         if (!s_highpc)
+           hz = profrate;
+         else if (hz != profrate)
+           {
+             fprintf (stderr,
+                      _("%s: profiling rate incompatible with first gmon file\n"),
+                      filename);
+             done (1);
+           }
+
+         header_size = sizeof (struct raw_phdr);
+       }
+      else
+       {
+         /* old style BSD format.  */
+         if (file_format == FF_BSD44)
+           {
+             fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
+                      whoami, filename);
+             done (1);
+           }
+
+         if (fseek (ifp, sizeof (struct old_raw_phdr), SEEK_SET) < 0)
+           {
+             perror (filename);
+             done (1);
+           }
+
+         header_size = sizeof (struct old_raw_phdr);
+       }
+
+      if (s_highpc && (tmp.low_pc != h.low_pc ||
+                      tmp.high_pc != h.high_pc || tmp.ncnt != h.ncnt))
+       {
+         fprintf (stderr, _("%s: incompatible with first gmon file\n"),
+                  filename);
+         done (1);
+       }
+      h = tmp;
+      s_lowpc = (bfd_vma) h.low_pc;
+      s_highpc = (bfd_vma) h.high_pc;
+      lowpc = (bfd_vma) h.low_pc / sizeof (UNIT);
+      highpc = (bfd_vma) h.high_pc / sizeof (UNIT);
+      samp_bytes = h.ncnt - header_size;
+      hist_num_bins = samp_bytes / sizeof (UNIT);
+      DBG (SAMPLEDEBUG,
+          printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n",
+                  h.low_pc, h.high_pc, h.ncnt);
+          printf ("[gmon_out_read]   s_lowpc 0x%lx   s_highpc 0x%lx\n",
+                  s_lowpc, s_highpc);
+          printf ("[gmon_out_read]     lowpc 0x%lx     highpc 0x%lx\n",
+                  lowpc, highpc);
+          printf ("[gmon_out_read] samp_bytes %d hist_num_bins %d\n",
+                  samp_bytes, hist_num_bins));
+
+      if (hist_num_bins)
+       {
+         ++nhist;
+       }
+
+      if (!hist_sample)
+       {
+         hist_sample =
+           (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
+         memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
+       }
+
+      for (i = 0; i < hist_num_bins; ++i)
+       {
+         if (fread (raw_bin_count, sizeof (raw_bin_count), 1, ifp) != 1)
+           {
+             fprintf (stderr,
+                      _("%s: unexpected EOF after reading %d/%d bins\n"),
+                      whoami, --i, hist_num_bins);
+             done (1);
+           }
+         hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count);
+       }
+
+      /*
+       * The rest of the file consists of a bunch of <from,self,count>
+       * tuples:
+       */
+      while (fread (&raw_arc, sizeof (raw_arc), 1, ifp) == 1)
+       {
+         ++narcs;
+         from_pc = get_vma (core_bfd, (bfd_byte *) raw_arc.from_pc);
+         self_pc = get_vma (core_bfd, (bfd_byte *) raw_arc.self_pc);
+         count = bfd_get_32 (core_bfd, (bfd_byte *) raw_arc.count);
+         DBG (SAMPLEDEBUG,
+            printf ("[gmon_out_read] frompc 0x%lx selfpc 0x%lx count %lu\n",
+                    from_pc, self_pc, count));
+         /* add this arc: */
+         cg_tally (from_pc, self_pc, count);
+       }
+      fclose (ifp);
+
+      if (hz == HZ_WRONG)
+       {
+         /*
+          * How many ticks per second?  If we can't tell, report
+          * time in ticks.
+          */
+         hz = hertz ();
+         if (hz == HZ_WRONG)
+           {
+             hz = 1;
+             fprintf (stderr, _("time is in ticks, not seconds\n"));
+           }
+       }
+    }
+  else
+    {
+      fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
+              whoami, file_format);
+      done (1);
+    }
+
+  if (output_style & STYLE_GMON_INFO)
+    {
+      printf (_("File `%s' (version %d) contains:\n"),
+             filename, gmon_file_version);
+      printf (_("\t%d histogram record%s\n"),
+             nhist, nhist == 1 ? "" : "s");
+      printf (_("\t%d call-graph record%s\n"),
+             narcs, narcs == 1 ? "" : "s");
+      printf (_("\t%d basic-block count record%s\n"),
+             nbbs, nbbs == 1 ? "" : "s");
+      first_output = FALSE;
+    }
+}
+
+
+void
+DEFUN (gmon_out_write, (filename), const char *filename)
+{
+  FILE *ofp;
+  struct gmon_hdr ghdr;
+
+  ofp = fopen (filename, FOPEN_WB);
+  if (!ofp)
+    {
+      perror (filename);
+      done (1);
+    }
+
+  if (file_format == FF_AUTO || file_format == FF_MAGIC)
+    {
+      /* write gmon header: */
+
+      memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
+      bfd_put_32 (core_bfd, GMON_VERSION, (bfd_byte *) ghdr.version);
+      if (fwrite (&ghdr, sizeof (ghdr), 1, ofp) != 1)
+       {
+         perror (filename);
+         done (1);
+       }
+
+      /* write execution time histogram if we have one: */
+      if (gmon_input & INPUT_HISTOGRAM)
+       {
+         hist_write_hist (ofp, filename);
+       }
+
+      /* write call graph arcs if we have any: */
+      if (gmon_input & INPUT_CALL_GRAPH)
+       {
+         cg_write_arcs (ofp, filename);
+       }
+
+      /* write basic-block info if we have it: */
+      if (gmon_input & INPUT_BB_COUNTS)
+       {
+         bb_write_blocks (ofp, filename);
+       }
+    }
+  else if (file_format == FF_BSD || file_format == FF_BSD44)
+    {
+      struct raw_arc raw_arc;
+      UNIT raw_bin_count;
+      struct raw_phdr h;
+      int i;
+      Arc *arc;
+      Sym *sym;
+
+      memset (&h, 0, sizeof h);
+      put_vma (core_bfd, s_lowpc, (bfd_byte *) &h.low_pc);
+      put_vma (core_bfd, s_highpc, (bfd_byte *) &h.high_pc);
+      bfd_put_32 (core_bfd,
+                 hist_num_bins * sizeof (UNIT) + sizeof (struct raw_phdr),
+                 (bfd_byte *) &h.ncnt);
+
+      /* Write header.  Use new style BSD format is explicitly
+         specified, or if the profiling rate is non-standard;
+         otherwise, use the old BSD format.  */
+      if (file_format == FF_BSD44
+         || hz != hertz ())
+       {
+         bfd_put_32 (core_bfd, GMONVERSION, (bfd_byte *) &h.version);
+         bfd_put_32 (core_bfd, hz, (bfd_byte *) &h.profrate);
+         if (fwrite (&h, sizeof (struct raw_phdr), 1, ofp) != 1)
+           {
+             perror (filename);
+             done (1);
+           }
+       }
+      else
+       {
+         if (fwrite (&h, sizeof (struct old_raw_phdr), 1, ofp) != 1)
+           {
+             perror (filename);
+             done (1);
+           }
+       }
+
+      /* dump the samples: */
+
+      for (i = 0; i < hist_num_bins; ++i)
+       {
+         bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & raw_bin_count[0]);
+         if (fwrite (&raw_bin_count[0], sizeof (raw_bin_count), 1, ofp) != 1)
+           {
+             perror (filename);
+             done (1);
+           }
+       }
+
+      /* dump the normalized raw arc information: */
+
+      for (sym = symtab.base; sym < symtab.limit; ++sym)
+       {
+         for (arc = sym->cg.children; arc; arc = arc->next_child)
+           {
+             put_vma (core_bfd, arc->parent->addr,
+                      (bfd_byte *) raw_arc.from_pc);
+             put_vma (core_bfd, arc->child->addr,
+                      (bfd_byte *) raw_arc.self_pc);
+             bfd_put_32 (core_bfd, arc->count, (bfd_byte *) raw_arc.count);
+             if (fwrite (&raw_arc, sizeof (raw_arc), 1, ofp) != 1)
+               {
+                 perror (filename);
+                 done (1);
+               }
+             DBG (SAMPLEDEBUG,
+                  printf ("[dumpsum] frompc 0x%lx selfpc 0x%lx count %lu\n",
+                          arc->parent->addr, arc->child->addr, arc->count));
+           }
+       }
+      fclose (ofp);
+    }
+  else
+    {
+      fprintf (stderr, _("%s: don't know how to deal with file format %d\n"),
+              whoami, file_format);
+      done (1);
+    }
+}
diff --git a/gprof/gmon_io.h b/gprof/gmon_io.h
new file mode 100644 (file)
index 0000000..bf257a4
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef gmon_io_h
+#define gmon_io_h
+
+#include "bfd.h"
+#include "gmon.h"
+
+#define INPUT_HISTOGRAM                (1<<0)
+#define INPUT_CALL_GRAPH       (1<<1)
+#define INPUT_BB_COUNTS                (1<<2)
+
+extern int gmon_input;         /* what input did we see? */
+extern int gmon_file_version;  /* file version are we dealing with */
+
+extern bfd_vma get_vma PARAMS ((bfd * abfd, bfd_byte * addr));
+extern void put_vma PARAMS ((bfd * abfd, bfd_vma val, bfd_byte * addr));
+
+extern void gmon_out_read PARAMS ((const char *filename));
+extern void gmon_out_write PARAMS ((const char *filename));
+
+#endif /* gmon_io_h */
diff --git a/gprof/gmon_out.h b/gprof/gmon_out.h
new file mode 100644 (file)
index 0000000..2144fb5
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file specifies the format of gmon.out files.  It should have
+ * as few external dependencies as possible as it is going to be
+ * included in many different programs.  That is, minimize the
+ * number of #include's.
+ *
+ * A gmon.out file consists of a header (defined by gmon_hdr) followed
+ * by a sequence of records.  Each record starts with a one-byte tag
+ * identifying the type of records, followed by records specific data.
+ */
+#ifndef gmon_out_h
+#define gmon_out_h
+
+#define        GMON_MAGIC      "gmon"  /* magic cookie */
+#define GMON_VERSION   1       /* version number */
+
+/*
+ * Raw header as it appears on file (without padding):
+ */
+struct gmon_hdr
+  {
+    char cookie[4];
+    char version[4];
+    char spare[3 * 4];
+  };
+
+/* types of records in this file: */
+typedef enum
+  {
+    GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2
+  }
+GMON_Record_Tag;
+
+struct gmon_hist_hdr
+  {
+    char low_pc[sizeof (char*)];       /* base pc address of sample buffer */
+    char high_pc[sizeof (char*)];      /* max pc address of sampled buffer */
+    char hist_size[4];                 /* size of sample buffer */
+    char prof_rate[4];                 /* profiling clock rate */
+    char dimen[15];                    /* phys. dim., usually "seconds" */
+    char dimen_abbrev;                 /* usually 's' for "seconds" */
+  };
+
+struct gmon_cg_arc_record
+  {
+    char from_pc[sizeof (char*)];      /* address within caller's body */
+    char self_pc[sizeof (char*)];      /* address within callee's body */
+    char count[4];                     /* number of arc traversals */
+  };
+
+#endif /* gmon_out_h */
diff --git a/gprof/gprof.1 b/gprof/gprof.1
new file mode 100644 (file)
index 0000000..5a734da
--- /dev/null
@@ -0,0 +1,252 @@
+.\" Copyright (c) 1983, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted provided
+.\" that: (1) source distributions retain this entire copyright notice and
+.\" comment, and (2) distributions including binaries display the following
+.\" acknowledgement:  ``This product includes software developed by the
+.\" University of California, Berkeley and its contributors'' in the
+.\" documentation or other materials provided with the distribution and in
+.\" all advertising materials mentioning features or use of this software.
+.\" Neither the name of the University nor the names of its contributors may
+.\" be used to endorse or promote products derived from this software without
+.\" specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\"     @(#)gprof.1    6.6 (Berkeley) 7/24/90
+.\"
+.TH GPROF 1 "January 29, 1993"
+.SH NAME
+gprof \- display call graph profile data
+.SH SYNOPSIS
+.B gprof [ \-abcsz ] [ \-e|\-E
+.I name
+.B ] [ \-f|\-F 
+.I name
+.B ] 
+.B [ \-k
+.I fromname toname
+.B ] [ 
+.I objfile
+.B [ 
+.I gmon.out
+.B ] 
+.B ] 
+.SH DESCRIPTION
+.B gprof
+produces an execution profile of C, Pascal, or Fortran77 programs.
+The effect of called routines is incorporated in the profile of each caller.
+The profile data is taken from the call graph profile file
+\&(`gmon.out' default) which is created by programs
+that are compiled with the
+.B \-pg
+option of
+.BR cc ( 1 ) ,
+.BR pc ( 1 ) ,
+and
+.BR f77 ( 1 ) .
+The
+.B \-pg
+option also links in versions of the library routines
+that are compiled for profiling.
+.B Gprof
+reads the given object file (the default is `a.out')
+and establishes the relation between its symbol table
+and the call graph profile from `gmon.out'.
+If more than one profile file is specified,
+the
+.B gprof
+output shows the sum of the profile information in the given profile files.
+.PP
+.B Gprof
+calculates the amount of time spent in each routine.
+Next, these times are propagated along the edges of the call graph.
+Cycles are discovered, and calls into a cycle are made to share the time
+of the cycle.
+The first listing shows the functions
+sorted according to the time they represent
+including the time of their call graph descendants.
+Below each function entry is shown its (direct) call graph children,
+and how their times are propagated to this function.
+A similar display above the function shows how this function's time and the
+time of its descendants is propagated to its (direct) call graph parents.
+.PP
+Cycles are also shown, with an entry for the cycle as a whole and
+a listing of the members of the cycle and their contributions to the
+time and call counts of the cycle.
+.PP
+Second, a flat profile is given,
+similar to that provided by
+.BR prof ( 1 )  .
+This listing gives the total execution times, the call counts,
+the time in milliseconds the call spent in the routine itself, and
+the time in milliseconds the call spent in the routine itself including
+its descendants.
+.PP
+Finally, an index of the function names is provided.
+.SH OPTIONS
+The following options are available:
+.TP
+.B \-a
+suppresses the printing of statically declared functions.
+If this option is given, all relevant information about the static function
+(e.g., time samples, calls to other functions, calls from other functions)
+belongs to the function loaded just before the static function in the
+\&`objfile' file.
+.TP
+.B \-b
+suppresses the printing of a description of each field in the profile.
+.TP
+.B \-c
+the static call graph of the program is discovered by a heuristic
+that examines the text space of the object file.
+Static-only parents or children are shown
+with call counts of 0.
+.TP
+.BI "\-e " name
+suppresses the printing of the graph profile entry for routine
+.I name
+and all its descendants
+(unless they have other ancestors that aren't suppressed).
+More than one
+.B \-e
+option may be given.
+Only one
+.I name
+may be given with each
+.B \-e
+option.
+.TP
+.BI "\-E " name
+suppresses the printing of the graph profile entry for routine
+.I name
+(and its descendants) as
+.B \-e  ,
+above, and also excludes the time spent in
+.I name
+(and its descendants) from the total and percentage time computations.
+(For example,
+.BI "\-E " mcount
+.BI "\-E " mcleanup
+is the default.)
+.TP
+.BI "\-f " name
+prints the graph profile entry of only the specified routine
+.I name
+and its descendants.
+More than one
+.B \-f
+option may be given.
+Only one
+.I name
+may be given with each
+.B \-f
+option.
+.TP
+.BI "\-F " name
+prints the graph profile entry of only the routine
+.I name
+and its descendants (as
+.B \-f ,
+above) and also uses only the times of the printed routines
+in total time and percentage computations.
+More than one
+.B \-F
+option may be given.
+Only one
+.I name
+may be given with each
+.B \-F
+option.
+The
+.B \-F
+option
+overrides
+the
+.B \-E
+option.
+.TP
+.BI "\-k " "fromname toname"
+will delete any arcs from routine
+.I fromname
+to routine
+.IR toname  .
+This can be used to break undesired cycles.
+More than one
+.B \-k
+option may be given.
+Only one pair of routine names may be given with each
+.B \-k
+option.
+.TP
+.B \-s
+a profile file `gmon.sum' is produced that represents
+the sum of the profile information in all the specified profile files.
+This summary profile file may be given to later
+executions of gprof (probably also with a
+.BR \-s  )
+to accumulate profile data across several runs of an `objfile' file.
+.TP
+.B -v
+prints the version number for gprof, and then exits.
+.TP
+.B -z
+displays routines that have zero usage (as shown by call counts
+and accumulated time).
+This is useful with the
+.B \-c
+option for discovering which routines were never called.
+.PP
+.SH FILES
+.ta \w'gmon.sum 'u
+a.out  the namelist and text space.
+.br
+gmon.out       dynamic call graph and profile.
+.br
+gmon.sum summarized dynamic call graph and profile.
+.SH SEE ALSO
+.BR monitor ( 3 ) ,
+.BR profil ( 2 ) ,
+.BR cc ( 1 ) ,
+.BR prof ( 1 )
+.sp
+``An Execution Profiler for Modular Programs'',
+by S. Graham, P. Kessler, M. McKusick;
+.I
+Software \- Practice and Experience,
+Vol. 13, pp. 671-685, 1983.
+.sp
+``gprof: A Call Graph Execution Profiler'',
+by S. Graham, P. Kessler, M. McKusick;
+.I
+Proceedings of the SIGPLAN '82 Symposium on Compiler Construction,
+SIGPLAN Notices, Vol. 17, No  6, pp. 120-126, June 1982.
+.SH HISTORY
+.B Gprof
+appeared in 4.2 BSD.
+.SH BUGS
+The granularity of the sampling is shown, but remains
+statistical at best.
+We assume that the time for each execution of a function
+can be expressed by the total time for the function divided
+by the number of times the function is called.
+Thus the time propagated along the call graph arcs to the function's
+parents is directly proportional to the number of times that
+arc is traversed.
+.PP
+Parents that are not themselves profiled will have the time of
+their profiled children propagated to them, but they will appear
+to be spontaneously invoked in the call graph listing, and will
+not have their time propagated further.
+Similarly, signal catchers, even though profiled, will appear
+to be spontaneous (although for more obscure reasons).
+Any profiled children of signal catchers should have their times
+propagated properly, unless the signal catcher was invoked during
+the execution of the profiling routine, in which case all is lost.
+.PP
+The profiled program must call
+.BR exit ( 2 )
+or return normally for the profiling information to be saved
+in the `gmon.out' file.
diff --git a/gprof/gprof.c b/gprof/gprof.c
new file mode 100644 (file)
index 0000000..cb90487
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ * Copyright (c) 1983, 1998 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "getopt.h"
+#include "libiberty.h"
+#include "gprof.h"
+#include "basic_blocks.h"
+#include "call_graph.h"
+#include "cg_arcs.h"
+#include "cg_print.h"
+#include "corefile.h"
+#include "gmon_io.h"
+#include "hertz.h"
+#include "hist.h"
+#include "source.h"
+#include "sym_ids.h"
+
+const char *whoami;
+const char *function_mapping_file;
+const char *a_out_name = A_OUTNAME;
+long hz = HZ_WRONG;
+
+/*
+ * Default options values:
+ */
+int debug_level = 0;
+int output_style = 0;
+int output_width = 80;
+bool bsd_style_output = FALSE;
+bool demangle = TRUE;
+bool discard_underscores = TRUE;
+bool ignore_direct_calls = FALSE;
+bool ignore_static_funcs = FALSE;
+bool ignore_zeros = TRUE;
+bool line_granularity = FALSE;
+bool print_descriptions = TRUE;
+bool print_path = FALSE;
+bool ignore_non_functions = FALSE;
+File_Format file_format = FF_AUTO;
+
+bool first_output = TRUE;
+
+char copyright[] =
+ N_("@(#) Copyright (c) 1983 Regents of the University of California.\n\
+ All rights reserved.\n");
+
+static char *gmon_name = GMONNAME;     /* profile filename */
+
+bfd *abfd;
+
+/*
+ * Functions that get excluded by default:
+ */
+static char *default_excluded_list[] =
+{
+  "_gprof_mcount", "mcount", "_mcount", "__mcount", "__mcount_internal",
+  "__mcleanup",
+  "<locore>", "<hicore>",
+  0
+};
+
+/* Codes used for the long options with no short synonyms.  150 isn't
+   special; it's just an arbitrary non-ASCII char value.  */
+
+#define OPTION_DEMANGLE                (150)
+#define OPTION_NO_DEMANGLE     (OPTION_DEMANGLE + 1)
+
+static struct option long_options[] =
+{
+  {"line", no_argument, 0, 'l'},
+  {"no-static", no_argument, 0, 'a'},
+  {"ignore-non-functions", no_argument, 0, 'D'},
+
+    /* output styles: */
+
+  {"annotated-source", optional_argument, 0, 'A'},
+  {"no-annotated-source", optional_argument, 0, 'J'},
+  {"flat-profile", optional_argument, 0, 'p'},
+  {"no-flat-profile", optional_argument, 0, 'P'},
+  {"graph", optional_argument, 0, 'q'},
+  {"no-graph", optional_argument, 0, 'Q'},
+  {"exec-counts", optional_argument, 0, 'C'},
+  {"no-exec-counts", optional_argument, 0, 'Z'},
+  {"function-ordering", no_argument, 0, 'r'},
+  {"file-ordering", required_argument, 0, 'R'},
+  {"file-info", no_argument, 0, 'i'},
+  {"sum", no_argument, 0, 's'},
+
+    /* various options to affect output: */
+
+  {"all-lines", no_argument, 0, 'x'},
+  {"demangle", no_argument, 0, OPTION_DEMANGLE},
+  {"no-demangle", no_argument, 0, OPTION_NO_DEMANGLE},
+  {"directory-path", required_argument, 0, 'I'},
+  {"display-unused-functions", no_argument, 0, 'z'},
+  {"min-count", required_argument, 0, 'm'},
+  {"print-path", no_argument, 0, 'L'},
+  {"separate-files", no_argument, 0, 'y'},
+  {"static-call-graph", no_argument, 0, 'c'},
+  {"table-length", required_argument, 0, 't'},
+  {"time", required_argument, 0, 'n'},
+  {"no-time", required_argument, 0, 'N'},
+  {"width", required_argument, 0, 'w'},
+    /*
+     * These are for backwards-compatibility only.  Their functionality
+     * is provided by the output style options already:
+     */
+  {"", required_argument, 0, 'e'},
+  {"", required_argument, 0, 'E'},
+  {"", required_argument, 0, 'f'},
+  {"", required_argument, 0, 'F'},
+  {"", required_argument, 0, 'k'},
+
+    /* miscellaneous: */
+
+  {"brief", no_argument, 0, 'b'},
+  {"debug", optional_argument, 0, 'd'},
+  {"help", no_argument, 0, 'h'},
+  {"file-format", required_argument, 0, 'O'},
+  {"traditional", no_argument, 0, 'T'},
+  {"version", no_argument, 0, 'v'},
+  {0, no_argument, 0, 0}
+};
+
+
+static void
+DEFUN (usage, (stream, status), FILE * stream AND int status)
+{
+  fprintf (stream, _("\
+Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\
+       [-d[num]] [-k from/to] [-m min-count] [-t table-length]\n\
+       [--[no-]annotated-source[=name]] [--[no-]exec-counts[=name]]\n\
+       [--[no-]flat-profile[=name]] [--[no-]graph[=name]]\n\
+       [--[no-]time=name] [--all-lines] [--brief] [--debug[=level]]\n\
+       [--function-ordering] [--file-ordering]\n\
+       [--directory-path=dirs] [--display-unused-functions]\n\
+       [--file-format=name] [--file-info] [--help] [--line] [--min-count=n]\n\
+       [--no-static] [--print-path] [--separate-files]\n\
+       [--static-call-graph] [--sum] [--table-length=len] [--traditional]\n\
+       [--version] [--width=n] [--ignore-non-functions]\n\
+       [--demangle] [--no-demangle]\n\
+       [image-file] [profile-file...]\n"),
+          whoami);
+  if (status == 0)
+    fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
+  done (status);
+}
+
+
+int
+DEFUN (main, (argc, argv), int argc AND char **argv)
+{
+  char **sp, *str;
+  Sym **cg = 0;
+  int ch, user_specified = 0;
+
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
+  setlocale (LC_MESSAGES, "");
+#endif
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  whoami = argv[0];
+  xmalloc_set_program_name (whoami);
+
+  while ((ch = getopt_long (argc, argv,
+       "aA::bBcCdD::e:E:f:F:hiI:J::k:lLm:n::N::O:p::P::q::Q::st:Tvw:xyzZ::",
+                           long_options, 0))
+        != EOF)
+    {
+      switch (ch)
+       {
+       case 'a':
+         ignore_static_funcs = TRUE;
+         break;
+       case 'A':
+         if (optarg)
+           {
+             sym_id_add (optarg, INCL_ANNO);
+           }
+         output_style |= STYLE_ANNOTATED_SOURCE;
+         user_specified |= STYLE_ANNOTATED_SOURCE;
+         break;
+       case 'b':
+         print_descriptions = FALSE;
+         break;
+       case 'B':
+         output_style |= STYLE_CALL_GRAPH;
+         user_specified |= STYLE_CALL_GRAPH;
+         break;
+       case 'c':
+         ignore_direct_calls = TRUE;
+         break;
+       case 'C':
+         if (optarg)
+           {
+             sym_id_add (optarg, INCL_EXEC);
+           }
+         output_style |= STYLE_EXEC_COUNTS;
+         user_specified |= STYLE_EXEC_COUNTS;
+         break;
+       case 'd':
+         if (optarg)
+           {
+             debug_level |= atoi (optarg);
+             debug_level |= ANYDEBUG;
+           }
+         else
+           {
+             debug_level = ~0;
+           }
+         DBG (ANYDEBUG, printf ("[main] debug-level=0x%x\n", debug_level));
+#ifndef DEBUG
+         printf (_("%s: debugging not supported; -d ignored\n"), whoami);
+#endif /* DEBUG */
+         break;
+       case 'D':
+         ignore_non_functions = TRUE;
+         break;
+       case 'E':
+         sym_id_add (optarg, EXCL_TIME);
+       case 'e':
+         sym_id_add (optarg, EXCL_GRAPH);
+         break;
+       case 'F':
+         sym_id_add (optarg, INCL_TIME);
+       case 'f':
+         sym_id_add (optarg, INCL_GRAPH);
+         break;
+       case 'g':
+         sym_id_add (optarg, EXCL_FLAT);
+         break;
+       case 'G':
+         sym_id_add (optarg, INCL_FLAT);
+         break;
+       case 'h':
+         usage (stdout, 0);
+       case 'i':
+         output_style |= STYLE_GMON_INFO;
+         user_specified |= STYLE_GMON_INFO;
+         break;
+       case 'I':
+         search_list_append (&src_search_list, optarg);
+         break;
+       case 'J':
+         if (optarg)
+           {
+             sym_id_add (optarg, EXCL_ANNO);
+             output_style |= STYLE_ANNOTATED_SOURCE;
+           }
+         else
+           {
+             output_style &= ~STYLE_ANNOTATED_SOURCE;
+           }
+         user_specified |= STYLE_ANNOTATED_SOURCE;
+         break;
+       case 'k':
+         sym_id_add (optarg, EXCL_ARCS);
+         break;
+       case 'l':
+         line_granularity = TRUE;
+         break;
+       case 'L':
+         print_path = TRUE;
+         break;
+       case 'm':
+         bb_min_calls = (unsigned long) strtoul (optarg, (char **) NULL, 10);
+         break;
+       case 'n':
+         sym_id_add (optarg, INCL_TIME);
+         break;
+       case 'N':
+         sym_id_add (optarg, EXCL_TIME);
+         break;
+       case 'O':
+         switch (optarg[0])
+           {
+           case 'a':
+             file_format = FF_AUTO;
+             break;
+           case 'm':
+             file_format = FF_MAGIC;
+             break;
+           case 'b':
+             file_format = FF_BSD;
+             break;
+           case '4':
+             file_format = FF_BSD44;
+             break;
+           case 'p':
+             file_format = FF_PROF;
+             break;
+           default:
+             fprintf (stderr, _("%s: unknown file format %s\n"),
+                      optarg, whoami);
+             done (1);
+           }
+         break;
+       case 'p':
+         if (optarg)
+           {
+             sym_id_add (optarg, INCL_FLAT);
+           }
+         output_style |= STYLE_FLAT_PROFILE;
+         user_specified |= STYLE_FLAT_PROFILE;
+         break;
+       case 'P':
+         if (optarg)
+           {
+             sym_id_add (optarg, EXCL_FLAT);
+             output_style |= STYLE_FLAT_PROFILE;
+           }
+         else
+           {
+             output_style &= ~STYLE_FLAT_PROFILE;
+           }
+         user_specified |= STYLE_FLAT_PROFILE;
+         break;
+       case 'q':
+         if (optarg)
+           {
+             if (strchr (optarg, '/'))
+               {
+                 sym_id_add (optarg, INCL_ARCS);
+               }
+             else
+               {
+                 sym_id_add (optarg, INCL_GRAPH);
+               }
+           }
+         output_style |= STYLE_CALL_GRAPH;
+         user_specified |= STYLE_CALL_GRAPH;
+         break;
+       case 'r':
+         output_style |= STYLE_FUNCTION_ORDER;
+         user_specified |= STYLE_FUNCTION_ORDER;
+         break;
+       case 'R':
+         output_style |= STYLE_FILE_ORDER;
+         user_specified |= STYLE_FILE_ORDER;
+         function_mapping_file = optarg;
+         break;
+       case 'Q':
+         if (optarg)
+           {
+             if (strchr (optarg, '/'))
+               {
+                 sym_id_add (optarg, EXCL_ARCS);
+               }
+             else
+               {
+                 sym_id_add (optarg, EXCL_GRAPH);
+               }
+             output_style |= STYLE_CALL_GRAPH;
+           }
+         else
+           {
+             output_style &= ~STYLE_CALL_GRAPH;
+           }
+         user_specified |= STYLE_CALL_GRAPH;
+         break;
+       case 's':
+         output_style |= STYLE_SUMMARY_FILE;
+         user_specified |= STYLE_SUMMARY_FILE;
+         break;
+       case 't':
+         bb_table_length = atoi (optarg);
+         if (bb_table_length < 0)
+           {
+             bb_table_length = 0;
+           }
+         break;
+       case 'T':
+         bsd_style_output = TRUE;
+         break;
+       case 'v':
+         /* This output is intended to follow the GNU standards document.  */
+         printf (_("GNU gprof %s\n"), VERSION);
+         printf (_("Based on BSD gprof, copyright 1983 Regents of the University of California.\n"));
+         printf (_("\
+This program is free software.  This program has absolutely no warranty.\n"));
+         done (0);
+       case 'w':
+         output_width = atoi (optarg);
+         if (output_width < 1)
+           {
+             output_width = 1;
+           }
+         break;
+       case 'x':
+         bb_annotate_all_lines = TRUE;
+         break;
+       case 'y':
+         create_annotation_files = TRUE;
+         break;
+       case 'z':
+         ignore_zeros = FALSE;
+         break;
+       case 'Z':
+         if (optarg)
+           {
+             sym_id_add (optarg, EXCL_EXEC);
+             output_style |= STYLE_EXEC_COUNTS;
+           }
+         else
+           {
+             output_style &= ~STYLE_EXEC_COUNTS;
+           }
+         user_specified |= STYLE_ANNOTATED_SOURCE;
+         break;
+       case OPTION_DEMANGLE:
+         demangle = TRUE;
+         break;
+       case OPTION_NO_DEMANGLE:
+         demangle = FALSE;
+         break;
+       default:
+         usage (stderr, 1);
+       }
+    }
+
+  /* Don't allow both ordering options, they modify the arc data in-place.  */
+  if ((user_specified & STYLE_FUNCTION_ORDER)
+      && (user_specified & STYLE_FILE_ORDER))
+    {
+      fprintf (stderr,_("\
+%s: Only one of --function-ordering and --file-ordering may be specified.\n"),
+              whoami);
+      done (1);
+    }
+
+  /* --sum implies --line, otherwise we'd lose b-b counts in gmon.sum */
+  if (output_style & STYLE_SUMMARY_FILE)
+    {
+      line_granularity = 1;
+    }
+
+  /* append value of GPROF_PATH to source search list if set: */
+  str = (char *) getenv ("GPROF_PATH");
+  if (str)
+    {
+      search_list_append (&src_search_list, str);
+    }
+
+  if (optind < argc)
+    {
+      a_out_name = argv[optind++];
+    }
+  if (optind < argc)
+    {
+      gmon_name = argv[optind++];
+    }
+
+  /*
+   * Turn off default functions:
+   */
+  for (sp = &default_excluded_list[0]; *sp; sp++)
+    {
+      sym_id_add (*sp, EXCL_TIME);
+      sym_id_add (*sp, EXCL_GRAPH);
+#ifdef __alpha__
+      sym_id_add (*sp, EXCL_FLAT);
+#endif
+    }
+
+  /*
+   * For line-by-line profiling, also want to keep those
+   * functions off the flat profile:
+   */
+  if (line_granularity)
+    {
+      for (sp = &default_excluded_list[0]; *sp; sp++)
+       {
+         sym_id_add (*sp, EXCL_FLAT);
+       }
+    }
+
+  /*
+   * Read symbol table from core file:
+   */
+  core_init (a_out_name);
+
+  /*
+   * If we should ignore direct function calls, we need to load
+   * to core's text-space:
+   */
+  if (ignore_direct_calls)
+    {
+      core_get_text_space (core_bfd);
+    }
+
+  /*
+   * Create symbols from core image:
+   */
+  if (line_granularity)
+    {
+      core_create_line_syms (core_bfd);
+    }
+  else
+    {
+      core_create_function_syms (core_bfd);
+    }
+
+  /*
+   * Translate sym specs into syms:
+   */
+  sym_id_parse ();
+
+  if (file_format == FF_PROF)
+    {
+#ifdef PROF_SUPPORT_IMPLEMENTED
+      /*
+       * Get information about mon.out file(s):
+       */
+      do
+       {
+         mon_out_read (gmon_name);
+         if (optind < argc)
+           {
+             gmon_name = argv[optind];
+           }
+       }
+      while (optind++ < argc);
+#else
+      fprintf (stderr,
+              _("%s: sorry, file format `prof' is not yet supported\n"),
+              whoami);
+      done (1);
+#endif
+    }
+  else
+    {
+      /*
+       * Get information about gmon.out file(s):
+       */
+      do
+       {
+         gmon_out_read (gmon_name);
+         if (optind < argc)
+           {
+             gmon_name = argv[optind];
+           }
+       }
+      while (optind++ < argc);
+    }
+
+  /*
+   * If user did not specify output style, try to guess something
+   * reasonable:
+   */
+  if (output_style == 0)
+    {
+      if (gmon_input & (INPUT_HISTOGRAM | INPUT_CALL_GRAPH))
+       {
+         output_style = STYLE_FLAT_PROFILE | STYLE_CALL_GRAPH;
+       }
+      else
+       {
+         output_style = STYLE_EXEC_COUNTS;
+       }
+      output_style &= ~user_specified;
+    }
+
+  /*
+   * Dump a gmon.sum file if requested (before any other processing!):
+   */
+  if (output_style & STYLE_SUMMARY_FILE)
+    {
+      gmon_out_write (GMONSUM);
+    }
+
+  if (gmon_input & INPUT_HISTOGRAM)
+    {
+      hist_assign_samples ();
+    }
+
+  if (gmon_input & INPUT_CALL_GRAPH)
+    {
+      cg = cg_assemble ();
+    }
+
+  /* do some simple sanity checks: */
+
+  if ((output_style & STYLE_FLAT_PROFILE)
+      && !(gmon_input & INPUT_HISTOGRAM))
+    {
+      fprintf (stderr, _("%s: gmon.out file is missing histogram\n"), whoami);
+      done (1);
+    }
+
+  if ((output_style & STYLE_CALL_GRAPH) && !(gmon_input & INPUT_CALL_GRAPH))
+    {
+      fprintf (stderr,
+              _("%s: gmon.out file is missing call-graph data\n"), whoami);
+      done (1);
+    }
+
+  /* output whatever user whishes to see: */
+
+  if (cg && (output_style & STYLE_CALL_GRAPH) && bsd_style_output)
+    {
+      cg_print (cg);           /* print the dynamic profile */
+    }
+
+  if (output_style & STYLE_FLAT_PROFILE)
+    {
+      hist_print ();           /* print the flat profile */
+    }
+
+  if (cg && (output_style & STYLE_CALL_GRAPH))
+    {
+      if (!bsd_style_output)
+       {
+         cg_print (cg);        /* print the dynamic profile */
+       }
+      cg_print_index ();
+    }
+
+  if (output_style & STYLE_EXEC_COUNTS)
+    {
+      print_exec_counts ();
+    }
+
+  if (output_style & STYLE_ANNOTATED_SOURCE)
+    {
+      print_annotated_source ();
+    }
+  if (output_style & STYLE_FUNCTION_ORDER)
+    {
+      cg_print_function_ordering ();
+    }
+  if (output_style & STYLE_FILE_ORDER)
+    {
+      cg_print_file_ordering ();
+    }
+  return 0;
+}
+
+void
+done (status)
+     int status;
+{
+  exit (status);
+}
diff --git a/gprof/gprof.h b/gprof/gprof.h
new file mode 100644 (file)
index 0000000..8f62aee
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *      @(#)gprof.h     5.9 (Berkeley) 6/1/90
+ */
+#ifndef gprof_h
+#define gprof_h
+
+#include <ansidecl.h>
+
+/* Include the BFD sysdep.h file.  */
+#include "sysdep.h"
+
+/* Undefine the BFD PACKAGE and VERSION macros before including the
+   gprof config.h file.  */
+#undef PACKAGE
+#undef VERSION
+/* Also undefine BFD's `_' macro; we have our own definition.  */
+#undef _
+
+#include "gconfig.h"
+
+#ifndef MIN
+#define MIN(a,b)       ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b)       ((a) > (b) ? (a) : (b))
+#endif
+
+/* AIX defines hz as a macro.  */
+#undef hz
+
+#ifndef PATH_MAX
+#define PATH_MAX       1024
+#endif
+
+#define        A_OUTNAME       "a.out" /* default core filename */
+#define        GMONNAME        "gmon.out"      /* default profile filename */
+#define        GMONSUM         "gmon.sum"      /* profile summary filename */
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(String) gettext (String)
+# ifdef gettext_noop
+#  define N_(String) gettext_noop (String)
+# else
+#  define N_(String) (String)
+# endif
+#else
+/* Stubs that do something close enough.  */
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+# define bindtextdomain(Domain,Directory) (Domain)
+# define _(String) (String)
+# define N_(String) (String)
+#endif
+
+
+/*
+ * These may already be defined on some systems.  We could probably
+ * just use the BFD versions of these, since BFD has already dealt
+ * with this problem.
+ */
+#undef FALSE
+#define        FALSE   0
+#undef TRUE
+#define        TRUE    1
+
+#define STYLE_FLAT_PROFILE     (1<<0)
+#define STYLE_CALL_GRAPH       (1<<1)
+#define STYLE_SUMMARY_FILE     (1<<2)
+#define STYLE_EXEC_COUNTS      (1<<3)
+#define STYLE_ANNOTATED_SOURCE (1<<4)
+#define STYLE_GMON_INFO                (1<<5)
+#define STYLE_FUNCTION_ORDER   (1<<6)
+#define STYLE_FILE_ORDER       (1<<7)
+
+#define        ANYDEBUG        (1<<0)  /*    1 */
+#define        DFNDEBUG        (1<<1)  /*    2 */
+#define        CYCLEDEBUG      (1<<2)  /*    4 */
+#define        ARCDEBUG        (1<<3)  /*    8 */
+#define        TALLYDEBUG      (1<<4)  /*   16 */
+#define        TIMEDEBUG       (1<<5)  /*   32 */
+#define        SAMPLEDEBUG     (1<<6)  /*   64 */
+#define        AOUTDEBUG       (1<<7)  /*  128 */
+#define        CALLDEBUG       (1<<8)  /*  256 */
+#define        LOOKUPDEBUG     (1<<9)  /*  512 */
+#define        PROPDEBUG       (1<<10) /* 1024 */
+#define BBDEBUG                (1<<11) /* 2048 */
+#define IDDEBUG                (1<<12) /* 4096 */
+#define SRCDEBUG       (1<<13) /* 8192 */
+
+#ifdef DEBUG
+#define DBG(l,s)       if (debug_level & (l)) {s;}
+#else
+#define DBG(l,s)
+#endif
+
+typedef enum
+  {
+    FF_AUTO = 0, FF_MAGIC, FF_BSD, FF_BSD44, FF_PROF
+  }
+File_Format;
+
+typedef int bool;
+typedef unsigned char UNIT[2]; /* unit of profiling */
+
+extern const char *whoami;     /* command-name, for error messages */
+extern const char *function_mapping_file; /* file mapping functions to files */
+extern const char *a_out_name; /* core filename */
+extern long hz;                        /* ticks per second */
+
+/*
+ * Command-line options:
+ */
+extern int debug_level;                /* debug level */
+extern int output_style;
+extern int output_width;       /* controls column width in index */
+extern bool bsd_style_output;  /* as opposed to FSF style output */
+extern bool demangle;          /* demangle symbol names? */
+extern bool discard_underscores;       /* discard leading underscores? */
+extern bool ignore_direct_calls;       /* don't count direct calls */
+extern bool ignore_static_funcs;       /* suppress static functions */
+extern bool ignore_zeros;      /* ignore unused symbols/files */
+extern bool line_granularity;  /* function or line granularity? */
+extern bool print_descriptions;        /* output profile description */
+extern bool print_path;                /* print path or just filename? */
+extern bool ignore_non_functions;/* Ignore non-function symbols.  */
+
+extern File_Format file_format;        /* requested file format */
+
+extern bool first_output;      /* no output so far? */
+
+extern void done PARAMS ((int status));
+
+#endif /* gprof_h */
diff --git a/gprof/gprof.texi b/gprof/gprof.texi
new file mode 100644 (file)
index 0000000..43d8b9f
--- /dev/null
@@ -0,0 +1,2028 @@
+\input texinfo @c -*-texinfo-*-
+@setfilename gprof.info
+@settitle GNU gprof
+@setchapternewpage odd
+
+@ifinfo
+@c This is a dir.info fragment to support semi-automated addition of
+@c manuals to an info tree.  zoo@cygnus.com is developing this facility.
+@format
+START-INFO-DIR-ENTRY
+* gprof: (gprof).                Profiling your program's execution
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+This file documents the gprof profiler of the GNU system.
+
+Copyright (C) 1988, 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@finalout
+@smallbook
+
+@titlepage
+@title GNU gprof
+@subtitle The @sc{gnu} Profiler 
+@author Jay Fenlason and Richard Stallman
+
+@page
+
+This manual describes the @sc{gnu} profiler, @code{gprof}, and how you
+can use it to determine which parts of a program are taking most of the
+execution time.  We assume that you know how to write, compile, and
+execute programs.  @sc{gnu} @code{gprof} was written by Jay Fenlason.
+
+This manual was edited January 1993 by Jeffrey Osier
+and updated September 1997 by Brent Baccala.
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988, 1992, 1997, 1998 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the same conditions as for modified versions.
+
+@end titlepage
+
+@ifinfo
+@node Top
+@top Profiling a Program: Where Does It Spend Its Time?
+
+This manual describes the @sc{gnu} profiler, @code{gprof}, and how you
+can use it to determine which parts of a program are taking most of the
+execution time.  We assume that you know how to write, compile, and
+execute programs.  @sc{gnu} @code{gprof} was written by Jay Fenlason.
+
+This manual was updated August 1997 by Brent Baccala.
+
+@menu
+* Introduction::        What profiling means, and why it is useful.
+
+* Compiling::           How to compile your program for profiling.
+* Executing::           Executing your program to generate profile data
+* Invoking::            How to run @code{gprof}, and its options
+
+* Output::             Interpreting @code{gprof}'s output
+
+* Inaccuracy::          Potential problems you should be aware of
+* How do I?::           Answers to common questions
+* Incompatibilities::   (between @sc{gnu} @code{gprof} and Unix @code{gprof}.)
+* Details::             Details of how profiling is done
+@end menu
+@end ifinfo
+
+@node Introduction
+@chapter Introduction to Profiling
+
+Profiling allows you to learn where your program spent its time and which
+functions called which other functions while it was executing.  This
+information can show you which pieces of your program are slower than you
+expected, and might be candidates for rewriting to make your program
+execute faster.  It can also tell you which functions are being called more
+or less often than you expected.  This may help you spot bugs that had
+otherwise been unnoticed.
+
+Since the profiler uses information collected during the actual execution
+of your program, it can be used on programs that are too large or too
+complex to analyze by reading the source.  However, how your program is run
+will affect the information that shows up in the profile data.  If you
+don't use some feature of your program while it is being profiled, no
+profile information will be generated for that feature.
+
+Profiling has several steps:
+
+@itemize @bullet
+@item
+You must compile and link your program with profiling enabled.
+@xref{Compiling}.
+
+@item
+You must execute your program to generate a profile data file.
+@xref{Executing}.
+
+@item
+You must run @code{gprof} to analyze the profile data.
+@xref{Invoking}.
+@end itemize
+
+The next three chapters explain these steps in greater detail.
+
+Several forms of output are available from the analysis.
+
+The @dfn{flat profile} shows how much time your program spent in each function,
+and how many times that function was called.  If you simply want to know
+which functions burn most of the cycles, it is stated concisely here.
+@xref{Flat Profile}.
+
+The @dfn{call graph} shows, for each function, which functions called it, which
+other functions it called, and how many times.  There is also an estimate
+of how much time was spent in the subroutines of each function.  This can
+suggest places where you might try to eliminate function calls that use a
+lot of time.  @xref{Call Graph}.
+
+The @dfn{annotated source} listing is a copy of the program's
+source code, labeled with the number of times each line of the
+program was executed.  @xref{Annotated Source}.
+
+To better understand how profiling works, you may wish to read
+a description of its implementation.
+@xref{Implementation}.
+
+@node Compiling
+@chapter Compiling a Program for Profiling
+
+The first step in generating profile information for your program is
+to compile and link it with profiling enabled.
+
+To compile a source file for profiling, specify the @samp{-pg} option when
+you run the compiler.  (This is in addition to the options you normally
+use.)
+
+To link the program for profiling, if you use a compiler such as @code{cc}
+to do the linking, simply specify @samp{-pg} in addition to your usual
+options.  The same option, @samp{-pg}, alters either compilation or linking
+to do what is necessary for profiling.  Here are examples:
+
+@example
+cc -g -c myprog.c utils.c -pg
+cc -o myprog myprog.o utils.o -pg
+@end example
+
+The @samp{-pg} option also works with a command that both compiles and links:
+
+@example
+cc -o myprog myprog.c utils.c -g -pg
+@end example
+
+If you run the linker @code{ld} directly instead of through a compiler
+such as @code{cc}, you may have to specify a profiling startup file
+@file{gcrt0.o} as the first input file instead of the usual startup
+file @file{crt0.o}.  In addition, you would probably want to
+specify the profiling C library, @file{libc_p.a}, by writing
+@samp{-lc_p} instead of the usual @samp{-lc}.  This is not absolutely
+necessary, but doing this gives you number-of-calls information for
+standard library functions such as @code{read} and @code{open}.  For
+example:
+
+@example
+ld -o myprog /lib/gcrt0.o myprog.o utils.o -lc_p
+@end example
+
+If you compile only some of the modules of the program with @samp{-pg}, you
+can still profile the program, but you won't get complete information about
+the modules that were compiled without @samp{-pg}.  The only information
+you get for the functions in those modules is the total time spent in them;
+there is no record of how many times they were called, or from where.  This
+will not affect the flat profile (except that the @code{calls} field for
+the functions will be blank), but will greatly reduce the usefulness of the
+call graph.
+
+If you wish to perform line-by-line profiling,
+you will also need to specify the @samp{-g} option,
+instructing the compiler to insert debugging symbols into the program
+that match program addresses to source code lines.
+@xref{Line-by-line}.
+
+In addition to the @samp{-pg} and @samp{-g} options,
+you may also wish to specify the @samp{-a} option when compiling.
+This will instrument
+the program to perform basic-block counting.  As the program runs,
+it will count how many times it executed each branch of each @samp{if}
+statement, each iteration of each @samp{do} loop, etc.  This will
+enable @code{gprof} to construct an annotated source code
+listing showing how many times each line of code was executed.
+
+@node Executing
+@chapter Executing the Program
+
+Once the program is compiled for profiling, you must run it in order to
+generate the information that @code{gprof} needs.  Simply run the program
+as usual, using the normal arguments, file names, etc.  The program should
+run normally, producing the same output as usual.  It will, however, run
+somewhat slower than normal because of the time spent collecting and the
+writing the profile data.
+
+The way you run the program---the arguments and input that you give
+it---may have a dramatic effect on what the profile information shows.  The
+profile data will describe the parts of the program that were activated for
+the particular input you use.  For example, if the first command you give
+to your program is to quit, the profile data will show the time used in
+initialization and in cleanup, but not much else.
+
+Your program will write the profile data into a file called @file{gmon.out}
+just before exiting.  If there is already a file called @file{gmon.out},
+its contents are overwritten.  There is currently no way to tell the
+program to write the profile data under a different name, but you can rename
+the file afterward if you are concerned that it may be overwritten.
+
+In order to write the @file{gmon.out} file properly, your program must exit
+normally: by returning from @code{main} or by calling @code{exit}.  Calling
+the low-level function @code{_exit} does not write the profile data, and
+neither does abnormal termination due to an unhandled signal.
+
+The @file{gmon.out} file is written in the program's @emph{current working
+directory} at the time it exits.  This means that if your program calls
+@code{chdir}, the @file{gmon.out} file will be left in the last directory
+your program @code{chdir}'d to.  If you don't have permission to write in
+this directory, the file is not written, and you will get an error message.
+
+Older versions of the @sc{gnu} profiling library may also write a file
+called @file{bb.out}.  This file, if present, contains an human-readable
+listing of the basic-block execution counts.  Unfortunately, the
+appearance of a human-readable @file{bb.out} means the basic-block
+counts didn't get written into @file{gmon.out}.
+The Perl script @code{bbconv.pl}, included with the @code{gprof}
+source distribution, will convert a @file{bb.out} file into
+a format readable by @code{gprof}.
+
+@node Invoking
+@chapter @code{gprof} Command Summary
+
+After you have a profile data file @file{gmon.out}, you can run @code{gprof}
+to interpret the information in it.  The @code{gprof} program prints a
+flat profile and a call graph on standard output.  Typically you would
+redirect the output of @code{gprof} into a file with @samp{>}.
+
+You run @code{gprof} like this:
+
+@smallexample
+gprof @var{options} [@var{executable-file} [@var{profile-data-files}@dots{}]] [> @var{outfile}]
+@end smallexample
+
+@noindent
+Here square-brackets indicate optional arguments.
+
+If you omit the executable file name, the file @file{a.out} is used.  If
+you give no profile data file name, the file @file{gmon.out} is used.  If
+any file is not in the proper format, or if the profile data file does not
+appear to belong to the executable file, an error message is printed.
+
+You can give more than one profile data file by entering all their names
+after the executable file name; then the statistics in all the data files
+are summed together.
+
+The order of these options does not matter.
+
+@menu
+* Output Options::      Controlling @code{gprof}'s output style
+* Analysis Options::    Controlling how @code{gprof} analyses its data
+* Miscellaneous Options::
+* Depricated Options::  Options you no longer need to use, but which
+                            have been retained for compatibility
+* Symspecs::            Specifying functions to include or exclude
+@end menu
+
+@node Output Options,Analysis Options,,Invoking
+@section Output Options
+
+These options specify which of several output formats
+@code{gprof} should produce.
+
+Many of these options take an optional @dfn{symspec} to specify
+functions to be included or excluded.  These options can be
+specified multiple times, with different symspecs, to include
+or exclude sets of symbols.  @xref{Symspecs}.
+
+Specifying any of these options overrides the default (@samp{-p -q}),
+which prints a flat profile and call graph analysis
+for all functions.
+
+@table @code
+
+@item -A[@var{symspec}]
+@itemx --annotated-source[=@var{symspec}]
+The @samp{-A} option causes @code{gprof} to print annotated source code.
+If @var{symspec} is specified, print output only for matching symbols.
+@xref{Annotated Source}.
+
+@item -b
+@itemx --brief
+If the @samp{-b} option is given, @code{gprof} doesn't print the
+verbose blurbs that try to explain the meaning of all of the fields in
+the tables.  This is useful if you intend to print out the output, or
+are tired of seeing the blurbs.
+
+@item -C[@var{symspec}]
+@itemx --exec-counts[=@var{symspec}]
+The @samp{-C} option causes @code{gprof} to
+print a tally of functions and the number of times each was called.
+If @var{symspec} is specified, print tally only for matching symbols.
+
+If the profile data file contains basic-block count records, specifing
+the @samp{-l} option, along with @samp{-C}, will cause basic-block
+execution counts to be tallied and displayed.
+
+@item -i
+@itemx --file-info
+The @samp{-i} option causes @code{gprof} to display summary information
+about the profile data file(s) and then exit.  The number of histogram,
+call graph, and basic-block count records is displayed.
+
+@item -I @var{dirs}
+@itemx --directory-path=@var{dirs}
+The @samp{-I} option specifies a list of search directories in
+which to find source files.  Environment variable @var{GPROF_PATH}
+can also be used to convery this information.
+Used mostly for annotated source output.
+
+@item -J[@var{symspec}]
+@itemx --no-annotated-source[=@var{symspec}]
+The @samp{-J} option causes @code{gprof} not to
+print annotated source code.
+If @var{symspec} is specified, @code{gprof} prints annotated source,
+but excludes matching symbols.
+
+@item -L
+@itemx --print-path
+Normally, source filenames are printed with the path
+component suppressed.  The @samp{-L} option causes @code{gprof}
+to print the full pathname of
+source filenames, which is determined
+from symbolic debugging information in the image file
+and is relative to the directory in which the compiler
+was invoked.
+
+@item -p[@var{symspec}]
+@itemx --flat-profile[=@var{symspec}]
+The @samp{-p} option causes @code{gprof} to print a flat profile.
+If @var{symspec} is specified, print flat profile only for matching symbols.
+@xref{Flat Profile}.
+
+@item -P[@var{symspec}]
+@itemx --no-flat-profile[=@var{symspec}]
+The @samp{-P} option causes @code{gprof} to suppress printing a flat profile.
+If @var{symspec} is specified, @code{gprof} prints a flat profile,
+but excludes matching symbols.
+
+@item -q[@var{symspec}]
+@itemx --graph[=@var{symspec}]
+The @samp{-q} option causes @code{gprof} to print the call graph analysis.
+If @var{symspec} is specified, print call graph only for matching symbols
+and their children.
+@xref{Call Graph}.
+
+@item -Q[@var{symspec}]
+@itemx --no-graph[=@var{symspec}]
+The @samp{-Q} option causes @code{gprof} to suppress printing the
+call graph.
+If @var{symspec} is specified, @code{gprof} prints a call graph,
+but excludes matching symbols.
+
+@item -y
+@itemx --separate-files
+This option affects annotated source output only.
+Normally, gprof prints annotated source files
+to standard-output.  If this option is specified,
+annotated source for a file named @file{path/filename}
+is generated in the file @file{filename-ann}.
+
+@item -Z[@var{symspec}]
+@itemx --no-exec-counts[=@var{symspec}]
+The @samp{-Z} option causes @code{gprof} not to
+print a tally of functions and the number of times each was called.
+If @var{symspec} is specified, print tally, but exclude matching symbols.
+
+@item --function-ordering
+The @samp{--function-ordering} option causes @code{gprof} to print a
+suggested function ordering for the program based on profiling data.
+This option suggests an ordering which may improve paging, tlb and
+cache behavior for the program on systems which support arbitrary
+ordering of functions in an executable.
+
+The exact details of how to force the linker to place functions
+in a particular order is system dependent and out of the scope of this
+manual.
+
+@item --file-ordering @var{map_file}
+The @samp{--file-ordering} option causes @code{gprof} to print a
+suggested .o link line ordering for the program based on profiling data.
+This option suggests an ordering which may improve paging, tlb and
+cache behavior for the program on systems which do not support arbitrary
+ordering of functions in an executable.
+
+Use of the @samp{-a} argument is highly recommended with this option.
+
+The @var{map_file} argument is a pathname to a file which provides
+function name to object file mappings.  The format of the file is similar to
+the output of the program @code{nm}.
+
+@smallexample
+@group
+c-parse.o:00000000 T yyparse
+c-parse.o:00000004 C yyerrflag
+c-lang.o:00000000 T maybe_objc_method_name
+c-lang.o:00000000 T print_lang_statistics
+c-lang.o:00000000 T recognize_objc_keyword
+c-decl.o:00000000 T print_lang_identifier
+c-decl.o:00000000 T print_lang_type
+@dots{}
+
+@end group
+@end smallexample
+
+GNU @code{nm} @samp{--extern-only} @samp{--defined-only} @samp{-v} @samp{--print-file-name} can be used to create @var{map_file}.
+
+@item -T
+@itemx --traditional
+The @samp{-T} option causes @code{gprof} to print its output in
+``traditional'' BSD style.
+
+@item -w @var{width}
+@itemx --width=@var{width}
+Sets width of output lines to @var{width}.
+Currently only used when printing the function index at the bottom
+of the call graph.
+
+@item -x
+@itemx --all-lines
+This option affects annotated source output only.
+By default, only the lines at the beginning of a basic-block
+are annotated.  If this option is specified, every line in
+a basic-block is annotated by repeating the annotation for the
+first line.  This behavior is similar to @code{tcov}'s @samp{-a}.
+
+@item --demangle
+@itemx --no-demangle
+These options control whether C++ symbol names should be demangled when
+printing output.  The default is to demangle symbols.  The
+@code{--no-demangle} option may be used to turn off demangling.
+
+@end table
+
+@node Analysis Options,Miscellaneous Options,Output Options,Invoking
+@section Analysis Options
+
+@table @code
+
+@item -a
+@itemx --no-static
+The @samp{-a} option causes @code{gprof} to suppress the printing of
+statically declared (private) functions.  (These are functions whose
+names are not listed as global, and which are not visible outside the
+file/function/block where they were defined.)  Time spent in these
+functions, calls to/from them, etc, will all be attributed to the
+function that was loaded directly before it in the executable file.
+@c This is compatible with Unix @code{gprof}, but a bad idea.  
+This option affects both the flat profile and the call graph.
+
+@item -c
+@itemx --static-call-graph
+The @samp{-c} option causes the call graph of the program to be
+augmented by a heuristic which examines the text space of the object
+file and identifies function calls in the binary machine code.
+Since normal call graph records are only generated when functions are
+entered, this option identifies children that could have been called,
+but never were.  Calls to functions that were not compiled with
+profiling enabled are also identified, but only if symbol table
+entries are present for them.
+Calls to dynamic library routines are typically @emph{not} found
+by this option.
+Parents or children identified via this heuristic
+are indicated in the call graph with call counts of @samp{0}.
+
+@item -D
+@itemx --ignore-non-functions
+The @samp{-D} option causes @code{gprof} to ignore symbols which
+are not known to be functions.  This option will give more accurate
+profile data on systems where it is supported (Solaris and HPUX for
+example).
+
+@item -k @var{from}/@var{to}
+The @samp{-k} option allows you to delete from the call graph any arcs from
+symbols matching symspec @var{from} to those matching symspec @var{to}.
+
+@item -l
+@itemx --line
+The @samp{-l} option enables line-by-line profiling, which causes
+histogram hits to be charged to individual source code lines,
+instead of functions.
+If the program was compiled with basic-block counting enabled,
+this option will also identify how many times each line of
+code was executed.
+While line-by-line profiling can help isolate where in a large function
+a program is spending its time, it also significantly increases
+the running time of @code{gprof}, and magnifies statistical
+inaccuracies.
+@xref{Sampling Error}.
+
+@item -m @var{num}
+@itemx --min-count=@var{num}
+This option affects execution count output only.
+Symbols that are executed less than @var{num} times are suppressed.
+
+@item -n[@var{symspec}]
+@itemx --time[=@var{symspec}]
+The @samp{-n} option causes @code{gprof}, in its call graph analysis,
+to only propagate times for symbols matching @var{symspec}.
+
+@item -N[@var{symspec}]
+@itemx --no-time[=@var{symspec}]
+The @samp{-n} option causes @code{gprof}, in its call graph analysis,
+not to propagate times for symbols matching @var{symspec}.
+
+@item -z
+@itemx --display-unused-functions
+If you give the @samp{-z} option, @code{gprof} will mention all
+functions in the flat profile, even those that were never called, and
+that had no time spent in them.  This is useful in conjunction with the
+@samp{-c} option for discovering which routines were never called.
+
+@end table
+
+@node Miscellaneous Options,Depricated Options,Analysis Options,Invoking
+@section Miscellaneous Options
+
+@table @code
+
+@item -d[@var{num}]
+@itemx --debug[=@var{num}]
+The @samp{-d @var{num}} option specifies debugging options.
+If @var{num} is not specified, enable all debugging.
+@xref{Debugging}.
+
+@item -O@var{name}
+@itemx --file-format=@var{name}
+Selects the format of the profile data files.  Recognized formats are
+@samp{auto} (the default), @samp{bsd}, @samp{4.4bsd}, @samp{magic}, and
+@samp{prof} (not yet supported).
+
+@item -s
+@itemx --sum
+The @samp{-s} option causes @code{gprof} to summarize the information
+in the profile data files it read in, and write out a profile data
+file called @file{gmon.sum}, which contains all the information from
+the profile data files that @code{gprof} read in.  The file @file{gmon.sum}
+may be one of the specified input files; the effect of this is to
+merge the data in the other input files into @file{gmon.sum}.
+
+Eventually you can run @code{gprof} again without @samp{-s} to analyze the
+cumulative data in the file @file{gmon.sum}.
+
+@item -v
+@itemx --version
+The @samp{-v} flag causes @code{gprof} to print the current version
+number, and then exit.
+
+@end table
+
+@node Depricated Options,Symspecs,Miscellaneous Options,Invoking
+@section Depricated Options
+
+@table @code
+
+These options have been replaced with newer versions that use symspecs.
+
+@item -e @var{function_name}
+The @samp{-e @var{function}} option tells @code{gprof} to not print
+information about the function @var{function_name} (and its
+children@dots{}) in the call graph.  The function will still be listed
+as a child of any functions that call it, but its index number will be
+shown as @samp{[not printed]}.  More than one @samp{-e} option may be
+given; only one @var{function_name} may be indicated with each @samp{-e}
+option. 
+
+@item -E @var{function_name}
+The @code{-E @var{function}} option works like the @code{-e} option, but
+time spent in the function (and children who were not called from
+anywhere else), will not be used to compute the percentages-of-time for
+the call graph.  More than one @samp{-E} option may be given; only one
+@var{function_name} may be indicated with each @samp{-E} option.
+
+@item -f @var{function_name}
+The @samp{-f @var{function}} option causes @code{gprof} to limit the
+call graph to the function @var{function_name} and its children (and
+their children@dots{}).  More than one @samp{-f} option may be given;
+only one @var{function_name} may be indicated with each @samp{-f}
+option.  
+
+@item -F @var{function_name}
+The @samp{-F @var{function}} option works like the @code{-f} option, but
+only time spent in the function and its children (and their
+children@dots{}) will be used to determine total-time and
+percentages-of-time for the call graph.  More than one @samp{-F} option
+may be given; only one @var{function_name} may be indicated with each
+@samp{-F} option.  The @samp{-F} option overrides the @samp{-E} option.
+
+@end table
+
+Note that only one function can be specified with each @code{-e},
+@code{-E}, @code{-f} or @code{-F} option.  To specify more than one
+function, use multiple options.  For example, this command:
+
+@example
+gprof -e boring -f foo -f bar myprogram > gprof.output
+@end example
+
+@noindent
+lists in the call graph all functions that were reached from either
+@code{foo} or @code{bar} and were not reachable from @code{boring}.
+
+@node Symspecs,,Depricated Options,Invoking
+@section Symspecs
+
+Many of the output options allow functions to be included or excluded
+using @dfn{symspecs} (symbol specifications), which observe the
+following syntax:
+
+@example
+  filename_containing_a_dot
+| funcname_not_containing_a_dot
+| linenumber
+| ( [ any_filename ] `:' ( any_funcname | linenumber ) )
+@end example
+
+Here are some sample symspecs:
+
+@table @samp
+@item main.c
+Selects everything in file @file{main.c}---the
+dot in the string tells gprof to interpret
+the string as a filename, rather than as
+a function name.  To select a file whose
+name does not contain a dot, a trailing colon
+should be specified.  For example, @samp{odd:} is
+interpreted as the file named @file{odd}.
+
+@item main
+Selects all functions named @samp{main}.
+
+Note that there may be multiple instances of the same function name
+because some of the definitions may be local (i.e., static).  Unless a
+function name is unique in a program, you must use the colon notation
+explained below to specify a function from a specific source file.
+
+Sometimes, function names contain dots.  In such cases, it is necessar
+to add a leading colon to the name.  For example, @samp{:.mul} selects
+function @samp{.mul}.
+
+In some object file formats, symbols have a leading underscore.  gprof
+will normally not print these underscores.  However, you must use the
+underscore when you name a symbol in a symspec.  You can use the
+@code{nm} program to see whether symbols have underscores for the object
+file format you are using.
+
+@item main.c:main
+Selects function @samp{main} in file @file{main.c}.
+
+@item main.c:134
+Selects line 134 in file @file{main.c}.
+@end table
+
+@node Output
+@chapter Interpreting @code{gprof}'s Output
+
+@code{gprof} can produce several different output styles, the
+most important of which are described below.  The simplest output
+styles (file information, execution count, and function and file ordering)
+are not described here, but are documented with the respective options
+that trigger them.
+@xref{Output Options}.
+
+@menu
+* Flat Profile::        The flat profile shows how much time was spent
+                            executing directly in each function.
+* Call Graph::          The call graph shows which functions called which
+                            others, and how much time each function used
+                            when its subroutine calls are included.
+* Line-by-line::        @code{gprof} can analyze individual source code lines
+* Annotated Source::    The annotated source listing displays source code
+                            labeled with execution counts
+@end menu
+
+
+@node Flat Profile,Call Graph,,Output
+@section The Flat Profile
+@cindex flat profile
+
+The @dfn{flat profile} shows the total amount of time your program
+spent executing each function.  Unless the @samp{-z} option is given,
+functions with no apparent time spent in them, and no apparent calls
+to them, are not mentioned.  Note that if a function was not compiled
+for profiling, and didn't run long enough to show up on the program
+counter histogram, it will be indistinguishable from a function that
+was never called.
+
+This is part of a flat profile for a small program:
+
+@smallexample
+@group
+Flat profile:
+
+Each sample counts as 0.01 seconds.
+  %   cumulative   self              self     total           
+ time   seconds   seconds    calls  ms/call  ms/call  name    
+ 33.34      0.02     0.02     7208     0.00     0.00  open
+ 16.67      0.03     0.01      244     0.04     0.12  offtime
+ 16.67      0.04     0.01        8     1.25     1.25  memccpy
+ 16.67      0.05     0.01        7     1.43     1.43  write
+ 16.67      0.06     0.01                             mcount
+  0.00      0.06     0.00      236     0.00     0.00  tzset
+  0.00      0.06     0.00      192     0.00     0.00  tolower
+  0.00      0.06     0.00       47     0.00     0.00  strlen
+  0.00      0.06     0.00       45     0.00     0.00  strchr
+  0.00      0.06     0.00        1     0.00    50.00  main
+  0.00      0.06     0.00        1     0.00     0.00  memcpy
+  0.00      0.06     0.00        1     0.00    10.11  print
+  0.00      0.06     0.00        1     0.00     0.00  profil
+  0.00      0.06     0.00        1     0.00    50.00  report
+@dots{}
+@end group
+@end smallexample
+
+@noindent
+The functions are sorted by first by decreasing run-time spent in them,
+then by decreasing number of calls, then alphabetically by name.  The
+functions @samp{mcount} and @samp{profil} are part of the profiling
+aparatus and appear in every flat profile; their time gives a measure of
+the amount of overhead due to profiling.
+
+Just before the column headers, a statement appears indicating
+how much time each sample counted as.
+This @dfn{sampling period} estimates the margin of error in each of the time
+figures.  A time figure that is not much larger than this is not
+reliable.  In this example, each sample counted as 0.01 seconds,
+suggesting a 100 Hz sampling rate.
+The program's total execution time was 0.06
+seconds, as indicated by the @samp{cumulative seconds} field.  Since
+each sample counted for 0.01 seconds, this means only six samples
+were taken during the run.  Two of the samples occured while the
+program was in the @samp{open} function, as indicated by the
+@samp{self seconds} field.  Each of the other four samples
+occured one each in @samp{offtime}, @samp{memccpy}, @samp{write},
+and @samp{mcount}.
+Since only six samples were taken, none of these values can
+be regarded as particularly reliable.
+In another run,
+the @samp{self seconds} field for
+@samp{mcount} might well be @samp{0.00} or @samp{0.02}.
+@xref{Sampling Error}, for a complete discussion.
+
+The remaining functions in the listing (those whose
+@samp{self seconds} field is @samp{0.00}) didn't appear
+in the histogram samples at all.  However, the call graph
+indicated that they were called, so therefore they are listed,
+sorted in decreasing order by the @samp{calls} field.
+Clearly some time was spent executing these functions,
+but the paucity of histogram samples prevents any
+determination of how much time each took.
+
+Here is what the fields in each line mean:
+
+@table @code
+@item % time
+This is the percentage of the total execution time your program spent
+in this function.  These should all add up to 100%.
+
+@item cumulative seconds
+This is the cumulative total number of seconds the computer spent
+executing this functions, plus the time spent in all the functions
+above this one in this table.
+
+@item self seconds
+This is the number of seconds accounted for by this function alone.
+The flat profile listing is sorted first by this number.
+
+@item calls
+This is the total number of times the function was called.  If the
+function was never called, or the number of times it was called cannot
+be determined (probably because the function was not compiled with
+profiling enabled), the @dfn{calls} field is blank.
+
+@item self ms/call
+This represents the average number of milliseconds spent in this
+function per call, if this function is profiled.  Otherwise, this field
+is blank for this function.
+
+@item total ms/call
+This represents the average number of milliseconds spent in this
+function and its descendants per call, if this function is profiled.
+Otherwise, this field is blank for this function.
+This is the only field in the flat profile that uses call graph analysis.
+
+@item name
+This is the name of the function.   The flat profile is sorted by this
+field alphabetically after the @dfn{self seconds} and @dfn{calls}
+fields are sorted.
+@end table
+
+@node Call Graph,Line-by-line,Flat Profile,Output
+@section The Call Graph
+@cindex call graph
+
+The @dfn{call graph} shows how much time was spent in each function
+and its children.  From this information, you can find functions that,
+while they themselves may not have used much time, called other
+functions that did use unusual amounts of time.
+
+Here is a sample call from a small program.  This call came from the
+same @code{gprof} run as the flat profile example in the previous
+chapter.
+
+@smallexample
+@group
+granularity: each sample hit covers 2 byte(s) for 20.00% of 0.05 seconds
+
+index % time    self  children    called     name
+                                                 <spontaneous>
+[1]    100.0    0.00    0.05                 start [1]
+                0.00    0.05       1/1           main [2]
+                0.00    0.00       1/2           on_exit [28]
+                0.00    0.00       1/1           exit [59]
+-----------------------------------------------
+                0.00    0.05       1/1           start [1]
+[2]    100.0    0.00    0.05       1         main [2]
+                0.00    0.05       1/1           report [3]
+-----------------------------------------------
+                0.00    0.05       1/1           main [2]
+[3]    100.0    0.00    0.05       1         report [3]
+                0.00    0.03       8/8           timelocal [6]
+                0.00    0.01       1/1           print [9]
+                0.00    0.01       9/9           fgets [12]
+                0.00    0.00      12/34          strncmp <cycle 1> [40]
+                0.00    0.00       8/8           lookup [20]
+                0.00    0.00       1/1           fopen [21]
+                0.00    0.00       8/8           chewtime [24]
+                0.00    0.00       8/16          skipspace [44]
+-----------------------------------------------
+[4]     59.8    0.01        0.02       8+472     <cycle 2 as a whole>  [4]
+                0.01        0.02     244+260         offtime <cycle 2> [7]
+                0.00        0.00     236+1           tzset <cycle 2> [26]
+-----------------------------------------------
+@end group
+@end smallexample
+
+The lines full of dashes divide this table into @dfn{entries}, one for each
+function.  Each entry has one or more lines.
+
+In each entry, the primary line is the one that starts with an index number
+in square brackets.  The end of this line says which function the entry is
+for.  The preceding lines in the entry describe the callers of this
+function and the following lines describe its subroutines (also called
+@dfn{children} when we speak of the call graph).
+
+The entries are sorted by time spent in the function and its subroutines.
+
+The internal profiling function @code{mcount} (@pxref{Flat Profile})
+is never mentioned in the call graph.
+
+@menu
+* Primary::       Details of the primary line's contents.
+* Callers::       Details of caller-lines' contents.
+* Subroutines::   Details of subroutine-lines' contents.
+* Cycles::        When there are cycles of recursion,
+                   such as @code{a} calls @code{b} calls @code{a}@dots{}
+@end menu
+
+@node Primary
+@subsection The Primary Line
+
+The @dfn{primary line} in a call graph entry is the line that
+describes the function which the entry is about and gives the overall
+statistics for this function.
+
+For reference, we repeat the primary line from the entry for function
+@code{report} in our main example, together with the heading line that
+shows the names of the fields:
+
+@smallexample
+@group
+index  % time    self  children called     name
+@dots{}
+[3]    100.0    0.00    0.05       1         report [3]
+@end group
+@end smallexample
+
+Here is what the fields in the primary line mean:
+
+@table @code
+@item index
+Entries are numbered with consecutive integers.  Each function
+therefore has an index number, which appears at the beginning of its
+primary line.
+
+Each cross-reference to a function, as a caller or subroutine of
+another, gives its index number as well as its name.  The index number
+guides you if you wish to look for the entry for that function.
+
+@item % time
+This is the percentage of the total time that was spent in this
+function, including time spent in subroutines called from this
+function.
+
+The time spent in this function is counted again for the callers of
+this function.  Therefore, adding up these percentages is meaningless.
+
+@item self
+This is the total amount of time spent in this function.  This
+should be identical to the number printed in the @code{seconds} field
+for this function in the flat profile.
+
+@item children
+This is the total amount of time spent in the subroutine calls made by
+this function.  This should be equal to the sum of all the @code{self}
+and @code{children} entries of the children listed directly below this
+function.
+
+@item called
+This is the number of times the function was called.
+
+If the function called itself recursively, there are two numbers,
+separated by a @samp{+}.  The first number counts non-recursive calls,
+and the second counts recursive calls.
+
+In the example above, the function @code{report} was called once from
+@code{main}.
+
+@item name
+This is the name of the current function.  The index number is
+repeated after it.
+
+If the function is part of a cycle of recursion, the cycle number is
+printed between the function's name and the index number
+(@pxref{Cycles}).  For example, if function @code{gnurr} is part of
+cycle number one, and has index number twelve, its primary line would
+be end like this:
+
+@example
+gnurr <cycle 1> [12]
+@end example
+@end table
+
+@node Callers, Subroutines, Primary, Call Graph
+@subsection Lines for a Function's Callers
+
+A function's entry has a line for each function it was called by.
+These lines' fields correspond to the fields of the primary line, but
+their meanings are different because of the difference in context.
+
+For reference, we repeat two lines from the entry for the function
+@code{report}, the primary line and one caller-line preceding it, together
+with the heading line that shows the names of the fields:
+
+@smallexample
+index  % time    self  children called     name
+@dots{}
+                0.00    0.05       1/1           main [2]
+[3]    100.0    0.00    0.05       1         report [3]
+@end smallexample
+
+Here are the meanings of the fields in the caller-line for @code{report}
+called from @code{main}:
+
+@table @code
+@item self
+An estimate of the amount of time spent in @code{report} itself when it was
+called from @code{main}.
+
+@item children
+An estimate of the amount of time spent in subroutines of @code{report}
+when @code{report} was called from @code{main}.
+
+The sum of the @code{self} and @code{children} fields is an estimate
+of the amount of time spent within calls to @code{report} from @code{main}.
+
+@item called
+Two numbers: the number of times @code{report} was called from @code{main},
+followed by the total number of nonrecursive calls to @code{report} from
+all its callers.
+
+@item name and index number
+The name of the caller of @code{report} to which this line applies,
+followed by the caller's index number.
+
+Not all functions have entries in the call graph; some
+options to @code{gprof} request the omission of certain functions.
+When a caller has no entry of its own, it still has caller-lines
+in the entries of the functions it calls.
+
+If the caller is part of a recursion cycle, the cycle number is
+printed between the name and the index number.
+@end table
+
+If the identity of the callers of a function cannot be determined, a
+dummy caller-line is printed which has @samp{<spontaneous>} as the
+``caller's name'' and all other fields blank.  This can happen for
+signal handlers.
+@c What if some calls have determinable callers' names but not all?
+@c FIXME - still relevant?
+
+@node Subroutines, Cycles, Callers, Call Graph
+@subsection Lines for a Function's Subroutines
+
+A function's entry has a line for each of its subroutines---in other
+words, a line for each other function that it called.  These lines'
+fields correspond to the fields of the primary line, but their meanings
+are different because of the difference in context.
+
+For reference, we repeat two lines from the entry for the function
+@code{main}, the primary line and a line for a subroutine, together
+with the heading line that shows the names of the fields:
+
+@smallexample
+index  % time    self  children called     name
+@dots{}
+[2]    100.0    0.00    0.05       1         main [2]
+                0.00    0.05       1/1           report [3]
+@end smallexample
+
+Here are the meanings of the fields in the subroutine-line for @code{main}
+calling @code{report}:
+
+@table @code
+@item self
+An estimate of the amount of time spent directly within @code{report}
+when @code{report} was called from @code{main}.
+
+@item children
+An estimate of the amount of time spent in subroutines of @code{report}
+when @code{report} was called from @code{main}.
+
+The sum of the @code{self} and @code{children} fields is an estimate
+of the total time spent in calls to @code{report} from @code{main}.
+
+@item called
+Two numbers, the number of calls to @code{report} from @code{main}
+followed by the total number of nonrecursive calls to @code{report}.
+This ratio is used to determine how much of @code{report}'s @code{self}
+and @code{children} time gets credited to @code{main}.
+@xref{Assumptions}.
+
+@item name
+The name of the subroutine of @code{main} to which this line applies,
+followed by the subroutine's index number.
+
+If the caller is part of a recursion cycle, the cycle number is
+printed between the name and the index number.
+@end table
+
+@node Cycles,, Subroutines, Call Graph
+@subsection How Mutually Recursive Functions Are Described
+@cindex cycle
+@cindex recursion cycle
+
+The graph may be complicated by the presence of @dfn{cycles of
+recursion} in the call graph.  A cycle exists if a function calls
+another function that (directly or indirectly) calls (or appears to
+call) the original function.  For example: if @code{a} calls @code{b},
+and @code{b} calls @code{a}, then @code{a} and @code{b} form a cycle.
+
+Whenever there are call paths both ways between a pair of functions, they
+belong to the same cycle.  If @code{a} and @code{b} call each other and
+@code{b} and @code{c} call each other, all three make one cycle.  Note that
+even if @code{b} only calls @code{a} if it was not called from @code{a},
+@code{gprof} cannot determine this, so @code{a} and @code{b} are still
+considered a cycle.
+
+The cycles are numbered with consecutive integers.  When a function
+belongs to a cycle, each time the function name appears in the call graph
+it is followed by @samp{<cycle @var{number}>}.
+
+The reason cycles matter is that they make the time values in the call
+graph paradoxical.  The ``time spent in children'' of @code{a} should
+include the time spent in its subroutine @code{b} and in @code{b}'s
+subroutines---but one of @code{b}'s subroutines is @code{a}!  How much of
+@code{a}'s time should be included in the children of @code{a}, when
+@code{a} is indirectly recursive?
+
+The way @code{gprof} resolves this paradox is by creating a single entry
+for the cycle as a whole.  The primary line of this entry describes the
+total time spent directly in the functions of the cycle.  The
+``subroutines'' of the cycle are the individual functions of the cycle, and
+all other functions that were called directly by them.  The ``callers'' of
+the cycle are the functions, outside the cycle, that called functions in
+the cycle.
+
+Here is an example portion of a call graph which shows a cycle containing
+functions @code{a} and @code{b}.  The cycle was entered by a call to
+@code{a} from @code{main}; both @code{a} and @code{b} called @code{c}.
+
+@smallexample
+index  % time    self  children called     name
+----------------------------------------
+                 1.77        0    1/1        main [2]
+[3]     91.71    1.77        0    1+5    <cycle 1 as a whole> [3]
+                 1.02        0    3          b <cycle 1> [4]
+                 0.75        0    2          a <cycle 1> [5]
+----------------------------------------
+                                  3          a <cycle 1> [5]
+[4]     52.85    1.02        0    0      b <cycle 1> [4]
+                                  2          a <cycle 1> [5]
+                    0        0    3/6        c [6]
+----------------------------------------
+                 1.77        0    1/1        main [2]
+                                  2          b <cycle 1> [4]
+[5]     38.86    0.75        0    1      a <cycle 1> [5]
+                                  3          b <cycle 1> [4]
+                    0        0    3/6        c [6]
+----------------------------------------
+@end smallexample
+
+@noindent
+(The entire call graph for this program contains in addition an entry for
+@code{main}, which calls @code{a}, and an entry for @code{c}, with callers
+@code{a} and @code{b}.)
+
+@smallexample
+index  % time    self  children called     name
+                                             <spontaneous>
+[1]    100.00       0     1.93    0      start [1]
+                 0.16     1.77    1/1        main [2]
+----------------------------------------
+                 0.16     1.77    1/1        start [1]
+[2]    100.00    0.16     1.77    1      main [2]
+                 1.77        0    1/1        a <cycle 1> [5]
+----------------------------------------
+                 1.77        0    1/1        main [2]
+[3]     91.71    1.77        0    1+5    <cycle 1 as a whole> [3]
+                 1.02        0    3          b <cycle 1> [4]
+                 0.75        0    2          a <cycle 1> [5]
+                    0        0    6/6        c [6]
+----------------------------------------
+                                  3          a <cycle 1> [5]
+[4]     52.85    1.02        0    0      b <cycle 1> [4]
+                                  2          a <cycle 1> [5]
+                    0        0    3/6        c [6]
+----------------------------------------
+                 1.77        0    1/1        main [2]
+                                  2          b <cycle 1> [4]
+[5]     38.86    0.75        0    1      a <cycle 1> [5]
+                                  3          b <cycle 1> [4]
+                    0        0    3/6        c [6]
+----------------------------------------
+                    0        0    3/6        b <cycle 1> [4]
+                    0        0    3/6        a <cycle 1> [5]
+[6]      0.00       0        0    6      c [6]
+----------------------------------------
+@end smallexample
+
+The @code{self} field of the cycle's primary line is the total time
+spent in all the functions of the cycle.  It equals the sum of the
+@code{self} fields for the individual functions in the cycle, found
+in the entry in the subroutine lines for these functions.
+
+The @code{children} fields of the cycle's primary line and subroutine lines
+count only subroutines outside the cycle.  Even though @code{a} calls
+@code{b}, the time spent in those calls to @code{b} is not counted in
+@code{a}'s @code{children} time.  Thus, we do not encounter the problem of
+what to do when the time in those calls to @code{b} includes indirect
+recursive calls back to @code{a}.
+
+The @code{children} field of a caller-line in the cycle's entry estimates
+the amount of time spent @emph{in the whole cycle}, and its other
+subroutines, on the times when that caller called a function in the cycle.
+
+The @code{calls} field in the primary line for the cycle has two numbers:
+first, the number of times functions in the cycle were called by functions
+outside the cycle; second, the number of times they were called by
+functions in the cycle (including times when a function in the cycle calls
+itself).  This is a generalization of the usual split into nonrecursive and
+recursive calls.
+
+The @code{calls} field of a subroutine-line for a cycle member in the
+cycle's entry says how many time that function was called from functions in
+the cycle.  The total of all these is the second number in the primary line's
+@code{calls} field.
+
+In the individual entry for a function in a cycle, the other functions in
+the same cycle can appear as subroutines and as callers.  These lines show
+how many times each function in the cycle called or was called from each other
+function in the cycle.  The @code{self} and @code{children} fields in these
+lines are blank because of the difficulty of defining meanings for them
+when recursion is going on.
+
+@node Line-by-line,Annotated Source,Call Graph,Output
+@section Line-by-line Profiling
+
+@code{gprof}'s @samp{-l} option causes the program to perform
+@dfn{line-by-line} profiling.  In this mode, histogram
+samples are assigned not to functions, but to individual
+lines of source code.  The program usually must be compiled
+with a @samp{-g} option, in addition to @samp{-pg}, in order
+to generate debugging symbols for tracking source code lines.
+
+The flat profile is the most useful output table
+in line-by-line mode.
+The call graph isn't as useful as normal, since
+the current version of @code{gprof} does not propagate
+call graph arcs from source code lines to the enclosing function.
+The call graph does, however, show each line of code
+that called each function, along with a count.
+
+Here is a section of @code{gprof}'s output, without line-by-line profiling.
+Note that @code{ct_init} accounted for four histogram hits, and
+13327 calls to @code{init_block}.
+
+@smallexample
+Flat profile:
+
+Each sample counts as 0.01 seconds.
+  %   cumulative   self              self     total           
+ time   seconds   seconds    calls  us/call  us/call  name    
+ 30.77      0.13     0.04     6335     6.31     6.31  ct_init
+
+
+                    Call graph (explanation follows)
+
+
+granularity: each sample hit covers 4 byte(s) for 7.69% of 0.13 seconds
+
+index % time    self  children    called     name
+
+                0.00    0.00       1/13496       name_too_long
+                0.00    0.00      40/13496       deflate
+                0.00    0.00     128/13496       deflate_fast
+                0.00    0.00   13327/13496       ct_init
+[7]      0.0    0.00    0.00   13496         init_block
+
+@end smallexample
+
+Now let's look at some of @code{gprof}'s output from the same program run,
+this time with line-by-line profiling enabled.  Note that @code{ct_init}'s
+four histogram hits are broken down into four lines of source code - one hit
+occured on each of lines 349, 351, 382 and 385.  In the call graph,
+note how
+@code{ct_init}'s 13327 calls to @code{init_block} are broken down
+into one call from line 396, 3071 calls from line 384, 3730 calls
+from line 385, and 6525 calls from 387.
+
+@smallexample
+Flat profile:
+
+Each sample counts as 0.01 seconds.
+  %   cumulative   self                    
+ time   seconds   seconds    calls  name    
+  7.69      0.10     0.01           ct_init (trees.c:349)
+  7.69      0.11     0.01           ct_init (trees.c:351)
+  7.69      0.12     0.01           ct_init (trees.c:382)
+  7.69      0.13     0.01           ct_init (trees.c:385)
+
+
+                    Call graph (explanation follows)
+
+
+granularity: each sample hit covers 4 byte(s) for 7.69% of 0.13 seconds
+
+  % time    self  children    called     name
+
+            0.00    0.00       1/13496       name_too_long (gzip.c:1440)
+            0.00    0.00       1/13496       deflate (deflate.c:763)
+            0.00    0.00       1/13496       ct_init (trees.c:396)
+            0.00    0.00       2/13496       deflate (deflate.c:727)
+            0.00    0.00       4/13496       deflate (deflate.c:686)
+            0.00    0.00       5/13496       deflate (deflate.c:675)
+            0.00    0.00      12/13496       deflate (deflate.c:679)
+            0.00    0.00      16/13496       deflate (deflate.c:730)
+            0.00    0.00     128/13496       deflate_fast (deflate.c:654)
+            0.00    0.00    3071/13496       ct_init (trees.c:384)
+            0.00    0.00    3730/13496       ct_init (trees.c:385)
+            0.00    0.00    6525/13496       ct_init (trees.c:387)
+[6]  0.0    0.00    0.00   13496         init_block (trees.c:408)
+
+@end smallexample
+
+
+@node Annotated Source,,Line-by-line,Output
+@section The Annotated Source Listing
+
+@code{gprof}'s @samp{-A} option triggers an annotated source listing,
+which lists the program's source code, each function labeled with the
+number of times it was called.  You may also need to specify the
+@samp{-I} option, if @code{gprof} can't find the source code files.
+
+Compiling with @samp{gcc @dots{} -g -pg -a} augments your program
+with basic-block counting code, in addition to function counting code.
+This enables @code{gprof} to determine how many times each line
+of code was exeucted.
+For example, consider the following function, taken from gzip,
+with line numbers added:
+
+@smallexample
+ 1 ulg updcrc(s, n)
+ 2     uch *s;
+ 3     unsigned n;
+ 4 @{
+ 5     register ulg c;
+ 6
+ 7     static ulg crc = (ulg)0xffffffffL;
+ 8
+ 9     if (s == NULL) @{
+10         c = 0xffffffffL;
+11     @} else @{
+12         c = crc;
+13         if (n) do @{
+14             c = crc_32_tab[...];
+15         @} while (--n);
+16     @}
+17     crc = c;
+18     return c ^ 0xffffffffL;
+19 @}
+
+@end smallexample
+
+@code{updcrc} has at least five basic-blocks.
+One is the function itself.  The
+@code{if} statement on line 9 generates two more basic-blocks, one
+for each branch of the @code{if}.  A fourth basic-block results from
+the @code{if} on line 13, and the contents of the @code{do} loop form
+the fifth basic-block.  The compiler may also generate additional
+basic-blocks to handle various special cases.
+
+A program augmented for basic-block counting can be analyzed with
+@code{gprof -l -A}.  I also suggest use of the @samp{-x} option,
+which ensures that each line of code is labeled at least once.
+Here is @code{updcrc}'s
+annotated source listing for a sample @code{gzip} run:
+
+@smallexample
+                ulg updcrc(s, n)
+                    uch *s;
+                    unsigned n;
+            2 ->@{
+                    register ulg c;
+                
+                    static ulg crc = (ulg)0xffffffffL;
+                
+            2 ->    if (s == NULL) @{
+            1 ->       c = 0xffffffffL;
+            1 ->    @} else @{
+            1 ->       c = crc;
+            1 ->        if (n) do @{
+        26312 ->            c = crc_32_tab[...];
+26312,1,26311 ->        @} while (--n);
+                    @}
+            2 ->    crc = c;
+            2 ->    return c ^ 0xffffffffL;
+            2 ->@}
+@end smallexample
+
+In this example, the function was called twice, passing once through
+each branch of the @code{if} statement.  The body of the @code{do}
+loop was executed a total of 26312 times.  Note how the @code{while}
+statement is annotated.  It began execution 26312 times, once for
+each iteration through the loop.  One of those times (the last time)
+it exited, while it branched back to the beginning of the loop 26311 times.
+
+@node Inaccuracy
+@chapter Inaccuracy of @code{gprof} Output
+
+@menu
+* Sampling Error::      Statistical margins of error
+* Assumptions::         Estimating children times
+@end menu
+
+@node Sampling Error,Assumptions,,Inaccuracy
+@section Statistical Sampling Error
+
+The run-time figures that @code{gprof} gives you are based on a sampling
+process, so they are subject to statistical inaccuracy.  If a function runs
+only a small amount of time, so that on the average the sampling process
+ought to catch that function in the act only once, there is a pretty good
+chance it will actually find that function zero times, or twice.
+
+By contrast, the number-of-calls and basic-block figures
+are derived by counting, not
+sampling.  They are completely accurate and will not vary from run to run
+if your program is deterministic.
+
+The @dfn{sampling period} that is printed at the beginning of the flat
+profile says how often samples are taken.  The rule of thumb is that a
+run-time figure is accurate if it is considerably bigger than the sampling
+period.
+
+The actual amount of error can be predicted.
+For @var{n} samples, the @emph{expected} error
+is the square-root of @var{n}.  For example,
+if the sampling period is 0.01 seconds and @code{foo}'s run-time is 1 second,
+@var{n} is 100 samples (1 second/0.01 seconds), sqrt(@var{n}) is 10 samples, so
+the expected error in @code{foo}'s run-time is 0.1 seconds (10*0.01 seconds),
+or ten percent of the observed value.
+Again, if the sampling period is 0.01 seconds and @code{bar}'s run-time is
+100 seconds, @var{n} is 10000 samples, sqrt(@var{n}) is 100 samples, so
+the expected error in @code{bar}'s run-time is 1 second,
+or one percent of the observed value.
+It is likely to
+vary this much @emph{on the average} from one profiling run to the next.
+(@emph{Sometimes} it will vary more.)
+
+This does not mean that a small run-time figure is devoid of information.
+If the program's @emph{total} run-time is large, a small run-time for one
+function does tell you that that function used an insignificant fraction of
+the whole program's time.  Usually this means it is not worth optimizing.
+
+One way to get more accuracy is to give your program more (but similar)
+input data so it will take longer.  Another way is to combine the data from
+several runs, using the @samp{-s} option of @code{gprof}.  Here is how:
+
+@enumerate
+@item
+Run your program once.
+
+@item
+Issue the command @samp{mv gmon.out gmon.sum}.
+
+@item
+Run your program again, the same as before.
+
+@item
+Merge the new data in @file{gmon.out} into @file{gmon.sum} with this command:
+
+@example
+gprof -s @var{executable-file} gmon.out gmon.sum
+@end example
+
+@item
+Repeat the last two steps as often as you wish.
+
+@item
+Analyze the cumulative data using this command:
+
+@example
+gprof @var{executable-file} gmon.sum > @var{output-file}
+@end example
+@end enumerate
+
+@node Assumptions,,Sampling Error,Inaccuracy
+@section Estimating @code{children} Times
+
+Some of the figures in the call graph are estimates---for example, the
+@code{children} time values and all the the time figures in caller and
+subroutine lines.
+
+There is no direct information about these measurements in the profile
+data itself.  Instead, @code{gprof} estimates them by making an assumption
+about your program that might or might not be true.
+
+The assumption made is that the average time spent in each call to any
+function @code{foo} is not correlated with who called @code{foo}.  If
+@code{foo} used 5 seconds in all, and 2/5 of the calls to @code{foo} came
+from @code{a}, then @code{foo} contributes 2 seconds to @code{a}'s
+@code{children} time, by assumption.
+
+This assumption is usually true enough, but for some programs it is far
+from true.  Suppose that @code{foo} returns very quickly when its argument
+is zero; suppose that @code{a} always passes zero as an argument, while
+other callers of @code{foo} pass other arguments.  In this program, all the
+time spent in @code{foo} is in the calls from callers other than @code{a}.
+But @code{gprof} has no way of knowing this; it will blindly and
+incorrectly charge 2 seconds of time in @code{foo} to the children of
+@code{a}.
+
+@c FIXME - has this been fixed?
+We hope some day to put more complete data into @file{gmon.out}, so that
+this assumption is no longer needed, if we can figure out how.  For the
+nonce, the estimated figures are usually more useful than misleading.
+
+@node How do I?
+@chapter Answers to Common Questions
+
+@table @asis
+@item How do I find which lines in my program were executed the most times?
+
+Compile your program with basic-block counting enabled, run it, then
+use the following pipeline:
+
+@example
+gprof -l -C @var{objfile} | sort -k 3 -n -r
+@end example
+
+This listing will show you the lines in your code executed most often,
+but not necessarily those that consumed the most time.
+
+@item How do I find which lines in my program called a particular function?
+
+Use @code{gprof -l} and lookup the function in the call graph.
+The callers will be broken down by function and line number.
+
+@item How do I analyze a program that runs for less than a second?
+
+Try using a shell script like this one:
+
+@example
+for i in `seq 1 100`; do
+  fastprog
+  mv gmon.out gmon.out.$i
+done
+
+gprof -s fastprog gmon.out.*
+
+gprof fastprog gmon.sum
+@end example
+
+If your program is completely deterministic, all the call counts
+will be simple multiples of 100 (i.e. a function called once in
+each run will appear with a call count of 100).
+
+@end table
+
+@node Incompatibilities
+@chapter Incompatibilities with Unix @code{gprof}
+
+@sc{gnu} @code{gprof} and Berkeley Unix @code{gprof} use the same data
+file @file{gmon.out}, and provide essentially the same information.  But
+there are a few differences.
+
+@itemize @bullet
+@item
+@sc{gnu} @code{gprof} uses a new, generalized file format with support
+for basic-block execution counts and non-realtime histograms.  A magic
+cookie and version number allows @code{gprof} to easily identify
+new style files.  Old BSD-style files can still be read.
+@xref{File Format}.
+
+@item
+For a recursive function, Unix @code{gprof} lists the function as a
+parent and as a child, with a @code{calls} field that lists the number
+of recursive calls.  @sc{gnu} @code{gprof} omits these lines and puts
+the number of recursive calls in the primary line.
+
+@item
+When a function is suppressed from the call graph with @samp{-e}, @sc{gnu}
+@code{gprof} still lists it as a subroutine of functions that call it.
+
+@item
+@sc{gnu} @code{gprof} accepts the @samp{-k} with its argument
+in the form @samp{from/to}, instead of @samp{from to}.
+
+@item
+In the annotated source listing,
+if there are multiple basic blocks on the same line,
+@sc{gnu} @code{gprof} prints all of their counts, seperated by commas.
+
+@ignore - it does this now
+@item
+The function names printed in @sc{gnu} @code{gprof} output do not include
+the leading underscores that are added internally to the front of all
+C identifiers on many operating systems.
+@end ignore
+
+@item
+The blurbs, field widths, and output formats are different.  @sc{gnu}
+@code{gprof} prints blurbs after the tables, so that you can see the
+tables without skipping the blurbs.
+@end itemize
+
+@node Details
+@chapter Details of Profiling
+
+@menu
+* Implementation::      How a program collets profiling information
+* File Format::         Format of @samp{gmon.out} files
+* Internals::           @code{gprof}'s internal operation
+* Debugging::           Using @code{gprof}'s @samp{-d} option
+@end menu
+
+@node Implementation,File Format,,Details
+@section Implementation of Profiling
+
+Profiling works by changing how every function in your program is compiled
+so that when it is called, it will stash away some information about where
+it was called from.  From this, the profiler can figure out what function
+called it, and can count how many times it was called.  This change is made
+by the compiler when your program is compiled with the @samp{-pg} option,
+which causes every function to call @code{mcount}
+(or @code{_mcount}, or @code{__mcount}, depending on the OS and compiler)
+as one of its first operations.
+
+The @code{mcount} routine, included in the profiling library,
+is responsible for recording in an in-memory call graph table
+both its parent routine (the child) and its parent's parent.  This is
+typically done by examining the stack frame to find both
+the address of the child, and the return address in the original parent.
+Since this is a very machine-dependant operation, @code{mcount}
+itself is typically a short assembly-language stub routine
+that extracts the required
+information, and then calls @code{__mcount_internal}
+(a normal C function) with two arguments - @code{frompc} and @code{selfpc}.
+@code{__mcount_internal} is responsible for maintaining
+the in-memory call graph, which records @code{frompc}, @code{selfpc},
+and the number of times each of these call arcs was transversed.
+
+GCC Version 2 provides a magical function (@code{__builtin_return_address}),
+which allows a generic @code{mcount} function to extract the
+required information from the stack frame.  However, on some
+architectures, most notably the SPARC, using this builtin can be
+very computationally expensive, and an assembly language version
+of @code{mcount} is used for performance reasons.
+
+Number-of-calls information for library routines is collected by using a
+special version of the C library.  The programs in it are the same as in
+the usual C library, but they were compiled with @samp{-pg}.  If you
+link your program with @samp{gcc @dots{} -pg}, it automatically uses the
+profiling version of the library.
+
+Profiling also involves watching your program as it runs, and keeping a
+histogram of where the program counter happens to be every now and then.
+Typically the program counter is looked at around 100 times per second of
+run time, but the exact frequency may vary from system to system.
+
+This is done is one of two ways.  Most UNIX-like operating systems
+provide a @code{profil()} system call, which registers a memory
+array with the kernel, along with a scale
+factor that determines how the program's address space maps
+into the array.
+Typical scaling values cause every 2 to 8 bytes of address space
+to map into a single array slot.
+On every tick of the system clock
+(assuming the profiled program is running), the value of the
+program counter is examined and the corresponding slot in
+the memory array is incremented.  Since this is done in the kernel,
+which had to interrupt the process anyway to handle the clock
+interrupt, very little additional system overhead is required.
+
+However, some operating systems, most notably Linux 2.0 (and earlier),
+do not provide a @code{profil()} system call.  On such a system,
+arrangements are made for the kernel to periodically deliver
+a signal to the process (typically via @code{setitimer()}),
+which then performs the same operation of examining the
+program counter and incrementing a slot in the memory array.
+Since this method requires a signal to be delivered to
+user space every time a sample is taken, it uses considerably
+more overhead than kernel-based profiling.  Also, due to the
+added delay required to deliver the signal, this method is
+less accurate as well.
+
+A special startup routine allocates memory for the histogram and 
+either calls @code{profil()} or sets up
+a clock signal handler.
+This routine (@code{monstartup}) can be invoked in several ways.
+On Linux systems, a special profiling startup file @code{gcrt0.o},
+which invokes @code{monstartup} before @code{main},
+is used instead of the default @code{crt0.o}.
+Use of this special startup file is one of the effects
+of using @samp{gcc @dots{} -pg} to link.
+On SPARC systems, no special startup files are used.
+Rather, the @code{mcount} routine, when it is invoked for
+the first time (typically when @code{main} is called),
+calls @code{monstartup}.
+
+If the compiler's @samp{-a} option was used, basic-block counting
+is also enabled.  Each object file is then compiled with a static array
+of counts, initially zero.
+In the executable code, every time a new basic-block begins
+(i.e. when an @code{if} statement appears), an extra instruction
+is inserted to increment the corresponding count in the array.
+At compile time, a paired array was constructed that recorded
+the starting address of each basic-block.  Taken together,
+the two arrays record the starting address of every basic-block,
+along with the number of times it was executed.
+
+The profiling library also includes a function (@code{mcleanup}) which is
+typically registered using @code{atexit()} to be called as the
+program exits, and is responsible for writing the file @file{gmon.out}.
+Profiling is turned off, various headers are output, and the histogram
+is written, followed by the call-graph arcs and the basic-block counts.
+
+The output from @code{gprof} gives no indication of parts of your program that
+are limited by I/O or swapping bandwidth.  This is because samples of the
+program counter are taken at fixed intervals of the program's run time.
+Therefore, the
+time measurements in @code{gprof} output say nothing about time that your
+program was not running.  For example, a part of the program that creates
+so much data that it cannot all fit in physical memory at once may run very
+slowly due to thrashing, but @code{gprof} will say it uses little time.  On
+the other hand, sampling by run time has the advantage that the amount of
+load due to other users won't directly affect the output you get.
+
+@node File Format,Internals,Implementation,Details
+@section Profiling Data File Format
+
+The old BSD-derived file format used for profile data does not contain a
+magic cookie that allows to check whether a data file really is a
+gprof file.  Furthermore, it does not provide a version number, thus
+rendering changes to the file format almost impossible.  @sc{gnu} @code{gprof}
+uses a new file format that provides these features.  For backward
+compatibility, @sc{gnu} @code{gprof} continues to support the old BSD-derived
+format, but not all features are supported with it.  For example,
+basic-block execution counts cannot be accommodated by the old file
+format.
+
+The new file format is defined in header file @file{gmon_out.h}.  It
+consists of a header containing the magic cookie and a version number,
+as well as some spare bytes available for future extensions.  All data
+in a profile data file is in the native format of the host on which
+the profile was collected.  @sc{gnu} @code{gprof} adapts automatically to the
+byte-order in use.
+
+In the new file format, the header is followed by a sequence of
+records.  Currently, there are three different record types: histogram
+records, call-graph arc records, and basic-block execution count
+records.  Each file can contain any number of each record type.  When
+reading a file, @sc{gnu} @code{gprof} will ensure records of the same type are
+compatible with each other and compute the union of all records.  For
+example, for basic-block execution counts, the union is simply the sum
+of all execution counts for each basic-block.
+
+@subsection Histogram Records
+
+Histogram records consist of a header that is followed by an array of
+bins.  The header contains the text-segment range that the histogram
+spans, the size of the histogram in bytes (unlike in the old BSD
+format, this does not include the size of the header), the rate of the
+profiling clock, and the physical dimension that the bin counts
+represent after being scaled by the profiling clock rate.  The
+physical dimension is specified in two parts: a long name of up to 15
+characters and a single character abbreviation.  For example, a
+histogram representing real-time would specify the long name as
+"seconds" and the abbreviation as "s".  This feature is useful for
+architectures that support performance monitor hardware (which,
+fortunately, is becoming increasingly common).  For example, under DEC
+OSF/1, the "uprofile" command can be used to produce a histogram of,
+say, instruction cache misses.  In this case, the dimension in the
+histogram header could be set to "i-cache misses" and the abbreviation
+could be set to "1" (because it is simply a count, not a physical
+dimension).  Also, the profiling rate would have to be set to 1 in
+this case.
+
+Histogram bins are 16-bit numbers and each bin represent an equal
+amount of text-space.  For example, if the text-segment is one
+thousand bytes long and if there are ten bins in the histogram, each
+bin represents one hundred bytes.
+
+
+@subsection Call-Graph Records
+
+Call-graph records have a format that is identical to the one used in
+the BSD-derived file format.  It consists of an arc in the call graph
+and a count indicating the number of times the arc was traversed
+during program execution.  Arcs are specified by a pair of addresses:
+the first must be within caller's function and the second must be
+within the callee's function.  When performing profiling at the
+function level, these addresses can point anywhere within the
+respective function.  However, when profiling at the line-level, it is
+better if the addresses are as close to the call-site/entry-point as
+possible.  This will ensure that the line-level call-graph is able to
+identify exactly which line of source code performed calls to a
+function.
+
+@subsection Basic-Block Execution Count Records
+
+Basic-block execution count records consist of a header followed by a
+sequence of address/count pairs.  The header simply specifies the
+length of the sequence.  In an address/count pair, the address
+identifies a basic-block and the count specifies the number of times
+that basic-block was executed.  Any address within the basic-address can
+be used.
+
+@node Internals,Debugging,File Format,Details
+@section @code{gprof}'s Internal Operation
+
+Like most programs, @code{gprof} begins by processing its options.
+During this stage, it may building its symspec list
+(@code{sym_ids.c:sym_id_add}), if
+options are specified which use symspecs.
+@code{gprof} maintains a single linked list of symspecs,
+which will eventually get turned into 12 symbol tables,
+organized into six include/exclude pairs - one
+pair each for the flat profile (INCL_FLAT/EXCL_FLAT),
+the call graph arcs (INCL_ARCS/EXCL_ARCS),
+printing in the call graph (INCL_GRAPH/EXCL_GRAPH),
+timing propagation in the call graph (INCL_TIME/EXCL_TIME),
+the annotated source listing (INCL_ANNO/EXCL_ANNO),
+and the execution count listing (INCL_EXEC/EXCL_EXEC).
+
+After option processing, @code{gprof} finishes
+building the symspec list by adding all the symspecs in
+@code{default_excluded_list} to the exclude lists
+EXCL_TIME and EXCL_GRAPH, and if line-by-line profiling is specified,
+EXCL_FLAT as well.
+These default excludes are not added to EXCL_ANNO, EXCL_ARCS, and EXCL_EXEC.
+
+Next, the BFD library is called to open the object file,
+verify that it is an object file,
+and read its symbol table (@code{core.c:core_init}),
+using @code{bfd_canonicalize_symtab} after mallocing
+an appropiate sized array of asymbols.  At this point,
+function mappings are read (if the @samp{--file-ordering} option
+has been specified), and the core text space is read into
+memory (if the @samp{-c} option was given).
+
+@code{gprof}'s own symbol table, an array of Sym structures,
+is now built.
+This is done in one of two ways, by one of two routines, depending
+on whether line-by-line profiling (@samp{-l} option) has been
+enabled.
+For normal profiling, the BFD canonical symbol table is scanned.
+For line-by-line profiling, every
+text space address is examined, and a new symbol table entry
+gets created every time the line number changes.
+In either case, two passes are made through the symbol
+table - one to count the size of the symbol table required,
+and the other to actually read the symbols.  In between the
+two passes, a single array of type @code{Sym} is created of
+the appropiate length.
+Finally, @code{symtab.c:symtab_finalize}
+is called to sort the symbol table and remove duplicate entries
+(entries with the same memory address).
+
+The symbol table must be a contiguous array for two reasons.
+First, the @code{qsort} library function (which sorts an array)
+will be used to sort the symbol table.
+Also, the symbol lookup routine (@code{symtab.c:sym_lookup}),
+which finds symbols
+based on memory address, uses a binary search algorithm
+which requires the symbol table to be a sorted array.
+Function symbols are indicated with an @code{is_func} flag.
+Line number symbols have no special flags set.
+Additionally, a symbol can have an @code{is_static} flag
+to indicate that it is a local symbol.
+
+With the symbol table read, the symspecs can now be translated
+into Syms (@code{sym_ids.c:sym_id_parse}).  Remember that a single
+symspec can match multiple symbols.
+An array of symbol tables
+(@code{syms}) is created, each entry of which is a symbol table
+of Syms to be included or excluded from a particular listing.
+The master symbol table and the symspecs are examined by nested
+loops, and every symbol that matches a symspec is inserted
+into the appropriate syms table.  This is done twice, once to
+count the size of each required symbol table, and again to build
+the tables, which have been malloced between passes.
+From now on, to determine whether a symbol is on an include
+or exclude symspec list, @code{gprof} simply uses its
+standard symbol lookup routine on the appropriate table
+in the @code{syms} array.
+
+Now the profile data file(s) themselves are read
+(@code{gmon_io.c:gmon_out_read}),
+first by checking for a new-style @samp{gmon.out} header,
+then assuming this is an old-style BSD @samp{gmon.out}
+if the magic number test failed.
+
+New-style histogram records are read by @code{hist.c:hist_read_rec}.
+For the first histogram record, allocate a memory array to hold
+all the bins, and read them in.
+When multiple profile data files (or files with multiple histogram
+records) are read, the starting address, ending address, number
+of bins and sampling rate must match between the various histograms,
+or a fatal error will result.
+If everything matches, just sum the additional histograms into
+the existing in-memory array.
+
+As each call graph record is read (@code{call_graph.c:cg_read_rec}),
+the parent and child addresses
+are matched to symbol table entries, and a call graph arc is
+created by @code{cg_arcs.c:arc_add}, unless the arc fails a symspec
+check against INCL_ARCS/EXCL_ARCS.  As each arc is added,
+a linked list is maintained of the parent's child arcs, and of the child's
+parent arcs.
+Both the child's call count and the arc's call count are
+incremented by the record's call count.
+
+Basic-block records are read (@code{basic_blocks.c:bb_read_rec}),
+but only if line-by-line profiling has been selected.
+Each basic-block address is matched to a corresponding line
+symbol in the symbol table, and an entry made in the symbol's
+bb_addr and bb_calls arrays.  Again, if multiple basic-block
+records are present for the same address, the call counts
+are cumulative.
+
+A gmon.sum file is dumped, if requested (@code{gmon_io.c:gmon_out_write}).
+
+If histograms were present in the data files, assign them to symbols
+(@code{hist.c:hist_assign_samples}) by iterating over all the sample
+bins and assigning them to symbols.  Since the symbol table
+is sorted in order of ascending memory addresses, we can
+simple follow along in the symbol table as we make our pass
+over the sample bins.
+This step includes a symspec check against INCL_FLAT/EXCL_FLAT.
+Depending on the histogram
+scale factor, a sample bin may span multiple symbols,
+in which case a fraction of the sample count is allocated
+to each symbol, proportional to the degree of overlap.
+This effect is rare for normal profiling, but overlaps
+are more common during line-by-line profiling, and can
+cause each of two adjacent lines to be credited with half
+a hit, for example.
+
+If call graph data is present, @code{cg_arcs.c:cg_assemble} is called.
+First, if @samp{-c} was specified, a machine-dependant
+routine (@code{find_call}) scans through each symbol's machine code,
+looking for subroutine call instructions, and adding them
+to the call graph with a zero call count.
+A topological sort is performed by depth-first numbering
+all the symbols (@code{cg_dfn.c:cg_dfn}), so that
+children are always numbered less than their parents,
+then making a array of pointers into the symbol table and sorting it into
+numerical order, which is reverse topological
+order (children appear before parents).
+Cycles are also detected at this point, all members
+of which are assigned the same topological number.
+Two passes are now made through this sorted array of symbol pointers.
+The first pass, from end to beginning (parents to children),
+computes the fraction of child time to propogate to each parent
+and a print flag.
+The print flag reflects symspec handling of INCL_GRAPH/EXCL_GRAPH,
+with a parent's include or exclude (print or no print) property
+being propagated to its children, unless they themselves explicitly appear
+in INCL_GRAPH or EXCL_GRAPH.
+A second pass, from beginning to end (children to parents) actually
+propogates the timings along the call graph, subject
+to a check against INCL_TIME/EXCL_TIME.
+With the print flag, fractions, and timings now stored in the symbol
+structures, the topological sort array is now discarded, and a
+new array of pointers is assembled, this time sorted by propagated time.
+
+Finally, print the various outputs the user requested, which is now fairly
+straightforward.  The call graph (@code{cg_print.c:cg_print}) and
+flat profile (@code{hist.c:hist_print}) are regurgitations of values
+already computed.  The annotated source listing
+(@code{basic_blocks.c:print_annotated_source}) uses basic-block
+information, if present, to label each line of code with call counts,
+otherwise only the function call counts are presented.
+
+The function ordering code is marginally well documented
+in the source code itself (@code{cg_print.c}).  Basically,
+the functions with the most use and the most parents are
+placed first, followed by other functions with the most use,
+followed by lower use functions, followed by unused functions
+at the end.
+
+@node Debugging,,Internals,Details
+@subsection Debugging @code{gprof}
+
+If @code{gprof} was compiled with debugging enabled,
+the @samp{-d} option triggers debugging output
+(to stdout) which can be helpful in understanding its operation.
+The debugging number specified is interpreted as a sum of the following
+options:
+
+@table @asis
+@item 2 - Topological sort
+Monitor depth-first numbering of symbols during call graph analysis
+@item 4 - Cycles
+Shows symbols as they are identified as cycle heads
+@item 16 - Tallying
+As the call graph arcs are read, show each arc and how
+the total calls to each function are tallied
+@item 32 - Call graph arc sorting
+Details sorting individual parents/children within each call graph entry
+@item 64 - Reading histogram and call graph records
+Shows address ranges of histograms as they are read, and each
+call graph arc
+@item 128 - Symbol table
+Reading, classifying, and sorting the symbol table from the object file.
+For line-by-line profiling (@samp{-l} option), also shows line numbers
+being assigned to memory addresses.
+@item 256 - Static call graph
+Trace operation of @samp{-c} option
+@item 512 - Symbol table and arc table lookups
+Detail operation of lookup routines
+@item 1024 - Call graph propagation
+Shows how function times are propagated along the call graph
+@item 2048 - Basic-blocks
+Shows basic-block records as they are read from profile data
+(only meaningful with @samp{-l} option)
+@item 4096 - Symspecs
+Shows symspec-to-symbol pattern matching operation
+@item 8192 - Annotate source
+Tracks operation of @samp{-A} option
+@end table
+
+@contents
+@bye
+
+NEEDS AN INDEX
+
+-T - "traditional BSD style": How is it different?  Should the
+differences be documented?
+
+example flat file adds up to 100.01%...
+
+note: time estimates now only go out to one decimal place (0.0), where
+they used to extend two (78.67).
diff --git a/gprof/hertz.c b/gprof/hertz.c
new file mode 100644 (file)
index 0000000..75314ac
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "hertz.h"
+
+
+#ifdef __MSDOS__
+#define HERTZ 18
+#endif
+
+int
+hertz ()
+{
+#ifdef HERTZ
+  return HERTZ;
+#else /* ! defined (HERTZ) */
+#ifdef HAVE_SETITIMER
+  struct itimerval tim;
+
+  tim.it_interval.tv_sec = 0;
+  tim.it_interval.tv_usec = 1;
+  tim.it_value.tv_sec = 0;
+  tim.it_value.tv_usec = 0;
+  setitimer (ITIMER_REAL, &tim, 0);
+  setitimer (ITIMER_REAL, 0, &tim);
+  if (tim.it_interval.tv_usec < 2)
+    {
+      return HZ_WRONG;
+    }
+  return 1000000 / tim.it_interval.tv_usec;
+#else /* ! defined (HAVE_SETITIMER) */
+#if defined (HAVE_SYSCONF) && defined (_SC_CLK_TCK)
+  return sysconf (_SC_CLK_TCK);
+#else /* ! defined (HAVE_SYSCONF) || ! defined (_SC_CLK_TCK) */
+  return HZ_WRONG;
+#endif /* ! defined (HAVE_SYSCONF) || ! defined (_SC_CLK_TCK) */
+#endif /* ! defined (HAVE_SETITIMER) */
+#endif /* ! defined (HERTZ) */
+}
diff --git a/gprof/hertz.h b/gprof/hertz.h
new file mode 100644 (file)
index 0000000..2ea01ba
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef hertz_h
+#define hertz_h
+
+#include "gprof.h"
+
+#define        HZ_WRONG 0              /* impossible clock frequency */
+
+/*
+ * Discover the tick frequency of the machine if something goes wrong,
+ * we return HZ_WRONG, an impossible sampling frequency.
+ */
+
+/* FIXME: Checking for MACH here makes no sense when for a cross
+   gprof.  */
+#ifdef MACH
+#include <machine/mach_param.h>
+#define hertz() (HZ)
+#else
+extern int hertz PARAMS ((void));
+#endif
+
+#endif /* hertz_h */
diff --git a/gprof/hist.c b/gprof/hist.c
new file mode 100644 (file)
index 0000000..5cdbbbb
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ * Histogram related operations.
+ */
+#include <stdio.h>
+#include "libiberty.h"
+#include "gprof.h"
+#include "corefile.h"
+#include "gmon_io.h"
+#include "gmon_out.h"
+#include "hist.h"
+#include "symtab.h"
+#include "sym_ids.h"
+#include "utils.h"
+
+#define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
+
+static void scale_and_align_entries PARAMS ((void));
+
+/* declarations of automatically generated functions to output blurbs: */
+extern void flat_blurb PARAMS ((FILE * fp));
+
+bfd_vma s_lowpc;               /* lowest address in .text */
+bfd_vma s_highpc = 0;          /* highest address in .text */
+bfd_vma lowpc, highpc;         /* same, but expressed in UNITs */
+int hist_num_bins = 0;         /* number of histogram samples */
+int *hist_sample = 0;          /* histogram samples (shorts in the file!) */
+double hist_scale;
+char hist_dimension[sizeof (((struct gmon_hist_hdr *) 0)->dimen) + 1] =
+  "seconds";
+char hist_dimension_abbrev = 's';
+
+static double accum_time;      /* accumulated time so far for print_line() */
+static double total_time;      /* total time for all routines */
+/*
+ * Table of SI prefixes for powers of 10 (used to automatically
+ * scale some of the values in the flat profile).
+ */
+const struct
+  {
+    char prefix;
+    double scale;
+  }
+SItab[] =
+{
+  {
+    'T', 1e-12
+  }
+  ,                            /* tera */
+  {
+    'G', 1e-09
+  }
+  ,                            /* giga */
+  {
+    'M', 1e-06
+  }
+  ,                            /* mega */
+  {
+    'K', 1e-03
+  }
+  ,                            /* kilo */
+  {
+    ' ', 1e-00
+  }
+  ,
+  {
+    'm', 1e+03
+  }
+  ,                            /* milli */
+  {
+    'u', 1e+06
+  }
+  ,                            /* micro */
+  {
+    'n', 1e+09
+  }
+  ,                            /* nano */
+  {
+    'p', 1e+12
+  }
+  ,                            /* pico */
+  {
+    'f', 1e+15
+  }
+  ,                            /* femto */
+  {
+    'a', 1e+18
+  }
+  ,                            /* ato */
+};
+
+/*
+ * Read the histogram from file IFP.  FILENAME is the name of IFP and
+ * is provided for formatting error messages only.
+ */
+void
+DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
+{
+  struct gmon_hist_hdr hdr;
+  bfd_vma n_lowpc, n_highpc;
+  int i, ncnt, profrate;
+  UNIT count;
+
+  if (fread (&hdr, sizeof (hdr), 1, ifp) != 1)
+    {
+      fprintf (stderr, _("%s: %s: unexpected end of file\n"),
+              whoami, filename);
+      done (1);
+    }
+
+  n_lowpc = (bfd_vma) get_vma (core_bfd, (bfd_byte *) hdr.low_pc);
+  n_highpc = (bfd_vma) get_vma (core_bfd, (bfd_byte *) hdr.high_pc);
+  ncnt = bfd_get_32 (core_bfd, (bfd_byte *) hdr.hist_size);
+  profrate = bfd_get_32 (core_bfd, (bfd_byte *) hdr.prof_rate);
+  strncpy (hist_dimension, hdr.dimen, sizeof (hdr.dimen));
+  hist_dimension[sizeof (hdr.dimen)] = '\0';
+  hist_dimension_abbrev = hdr.dimen_abbrev;
+
+  if (!s_highpc)
+    {
+
+      /* this is the first histogram record: */
+
+      s_lowpc = n_lowpc;
+      s_highpc = n_highpc;
+      lowpc = (bfd_vma) n_lowpc / sizeof (UNIT);
+      highpc = (bfd_vma) n_highpc / sizeof (UNIT);
+      hist_num_bins = ncnt;
+      hz = profrate;
+    }
+
+  DBG (SAMPLEDEBUG,
+       printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n",
+              n_lowpc, n_highpc, ncnt);
+       printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n",
+              s_lowpc, s_highpc, hist_num_bins);
+       printf ("[hist_read_rec]   lowpc 0x%lx   highpc 0x%lx\n",
+              lowpc, highpc));
+
+  if (n_lowpc != s_lowpc || n_highpc != s_highpc
+      || ncnt != hist_num_bins || hz != profrate)
+    {
+      fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"),
+              whoami, filename);
+      done (1);
+    }
+
+  if (!hist_sample)
+    {
+      hist_sample = (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
+      memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
+    }
+
+  for (i = 0; i < hist_num_bins; ++i)
+    {
+      if (fread (&count[0], sizeof (count), 1, ifp) != 1)
+       {
+         fprintf (stderr,
+                  _("%s: %s: unexpected EOF after reading %d of %d samples\n"),
+                  whoami, filename, i, hist_num_bins);
+         done (1);
+       }
+      hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
+    }
+}
+
+
+/*
+ * Write execution histogram to file OFP.  FILENAME is the name
+ * of OFP and is provided for formatting error-messages only.
+ */
+void
+DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename)
+{
+  struct gmon_hist_hdr hdr;
+  unsigned char tag;
+  UNIT count;
+  int i;
+
+  /* write header: */
+
+  tag = GMON_TAG_TIME_HIST;
+  put_vma (core_bfd, s_lowpc, (bfd_byte *) hdr.low_pc);
+  put_vma (core_bfd, s_highpc, (bfd_byte *) hdr.high_pc);
+  bfd_put_32 (core_bfd, hist_num_bins, (bfd_byte *) hdr.hist_size);
+  bfd_put_32 (core_bfd, hz, (bfd_byte *) hdr.prof_rate);
+  strncpy (hdr.dimen, hist_dimension, sizeof (hdr.dimen));
+  hdr.dimen_abbrev = hist_dimension_abbrev;
+
+  if (fwrite (&tag, sizeof (tag), 1, ofp) != 1
+      || fwrite (&hdr, sizeof (hdr), 1, ofp) != 1)
+    {
+      perror (filename);
+      done (1);
+    }
+
+  for (i = 0; i < hist_num_bins; ++i)
+    {
+      bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & count[0]);
+      if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
+       {
+         perror (filename);
+         done (1);
+       }
+    }
+}
+
+
+/*
+ * Calculate scaled entry point addresses (to save time in
+ * hist_assign_samples), and, on architectures that have procedure
+ * entry masks at the start of a function, possibly push the scaled
+ * entry points over the procedure entry mask, if it turns out that
+ * the entry point is in one bin and the code for a routine is in the
+ * next bin.
+ */
+static void
+scale_and_align_entries ()
+{
+  Sym *sym;
+  bfd_vma bin_of_entry;
+  bfd_vma bin_of_code;
+
+  for (sym = symtab.base; sym < symtab.limit; sym++)
+    {
+      sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
+      bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale;
+      bin_of_code = (sym->hist.scaled_addr + UNITS_TO_CODE - lowpc) / hist_scale;
+      if (bin_of_entry < bin_of_code)
+       {
+         DBG (SAMPLEDEBUG,
+              printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n",
+                      sym->hist.scaled_addr,
+                      sym->hist.scaled_addr + UNITS_TO_CODE));
+         sym->hist.scaled_addr += UNITS_TO_CODE;
+       }
+    }
+}
+
+
+/*
+ * Assign samples to the symbol to which they belong.
+ *
+ * Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
+ * which may overlap one more symbol address ranges.  If a symbol
+ * overlaps with the bin's address range by O percent, then O percent
+ * of the bin's count is credited to that symbol.
+ *
+ * There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
+ * with respect to the symbol's address range [SYM_LOW_PC,
+ * SYM_HIGH_PC) as shown in the following diagram.  OVERLAP computes
+ * the distance (in UNITs) between the arrows, the fraction of the
+ * sample that is to be credited to the symbol which starts at
+ * SYM_LOW_PC.
+ *
+ *        sym_low_pc                                      sym_high_pc
+ *             |                                               |
+ *             v                                               v
+ *
+ *             +-----------------------------------------------+
+ *             |                                               |
+ *        |  ->|    |<-         ->|         |<-         ->|    |<-  |
+ *        |         |             |         |             |         |
+ *        +---------+             +---------+             +---------+
+ *
+ *        ^         ^             ^         ^             ^         ^
+ *        |         |             |         |             |         |
+ *   bin_low_pc bin_high_pc  bin_low_pc bin_high_pc  bin_low_pc bin_high_pc
+ *
+ * For the VAX we assert that samples will never fall in the first two
+ * bytes of any routine, since that is the entry mask, thus we call
+ * scale_and_align_entries() to adjust the entry points if the entry
+ * mask falls in one bin but the code for the routine doesn't start
+ * until the next bin.  In conjunction with the alignment of routine
+ * addresses, this should allow us to have only one sample for every
+ * four bytes of text space and never have any overlap (the two end
+ * cases, above).
+ */
+void
+DEFUN_VOID (hist_assign_samples)
+{
+  bfd_vma bin_low_pc, bin_high_pc;
+  bfd_vma sym_low_pc, sym_high_pc;
+  bfd_vma overlap, addr;
+  int bin_count, i;
+  unsigned int j;
+  double time, credit;
+
+  /* read samples and assign to symbols: */
+  hist_scale = highpc - lowpc;
+  hist_scale /= hist_num_bins;
+  scale_and_align_entries ();
+
+  /* iterate over all sample bins: */
+
+  for (i = 0, j = 1; i < hist_num_bins; ++i)
+    {
+      bin_count = hist_sample[i];
+      if (!bin_count)
+       {
+         continue;
+       }
+      bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
+      bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
+      time = bin_count;
+      DBG (SAMPLEDEBUG,
+          printf (
+      "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
+                   sizeof (UNIT) * bin_low_pc, sizeof (UNIT) * bin_high_pc,
+                   bin_count));
+      total_time += time;
+
+      /* credit all symbols that are covered by bin I: */
+
+      for (j = j - 1; j < symtab.len; ++j)
+       {
+         sym_low_pc = symtab.base[j].hist.scaled_addr;
+         sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
+         /*
+          * If high end of bin is below entry address, go for next
+          * bin:
+          */
+         if (bin_high_pc < sym_low_pc)
+           {
+             break;
+           }
+         /*
+          * If low end of bin is above high end of symbol, go for
+          * next symbol.
+          */
+         if (bin_low_pc >= sym_high_pc)
+           {
+             continue;
+           }
+         overlap =
+           MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
+         if (overlap > 0)
+           {
+             DBG (SAMPLEDEBUG,
+                  printf (
+                           "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
+                           symtab.base[j].addr, sizeof (UNIT) * sym_high_pc,
+                           symtab.base[j].name, overlap * time / hist_scale,
+                           overlap));
+             addr = symtab.base[j].addr;
+             credit = overlap * time / hist_scale;
+             /*
+              * Credit symbol if it appears in INCL_FLAT or that
+              * table is empty and it does not appear it in
+              * EXCL_FLAT.
+              */
+             if (sym_lookup (&syms[INCL_FLAT], addr)
+                 || (syms[INCL_FLAT].len == 0
+                     && !sym_lookup (&syms[EXCL_FLAT], addr)))
+               {
+                 symtab.base[j].hist.time += credit;
+               }
+             else
+               {
+                 total_time -= credit;
+               }
+           }
+       }
+    }
+  DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
+                           total_time));
+}
+
+
+/*
+ * Print header for flag histogram profile:
+ */
+static void
+DEFUN (print_header, (prefix), const char prefix)
+{
+  char unit[64];
+
+  sprintf (unit, _("%c%c/call"), prefix, hist_dimension_abbrev);
+
+  if (bsd_style_output)
+    {
+      printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
+             (long) hist_scale * sizeof (UNIT));
+      if (total_time > 0.0)
+       {
+         printf (_(" for %.2f%% of %.2f %s\n\n"),
+                 100.0 / total_time, total_time / hz, hist_dimension);
+       }
+    }
+  else
+    {
+      printf (_("\nEach sample counts as %g %s.\n"), 1.0 / hz, hist_dimension);
+    }
+
+  if (total_time <= 0.0)
+    {
+      printf (_(" no time accumulated\n\n"));
+      /* this doesn't hurt since all the numerators will be zero: */
+      total_time = 1.0;
+    }
+
+  printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n",
+         "%  ", _("cumulative"), _("self  "), "", _("self  "), _("total "), "");
+  printf ("%5.5s %9.9s  %8.8s %8.8s %8.8s %8.8s  %-8.8s\n",
+         _("time"), hist_dimension, hist_dimension, _("calls"), unit, unit,
+         _("name"));
+}
+
+
+static void
+DEFUN (print_line, (sym, scale), Sym * sym AND double scale)
+{
+  if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
+    {
+      return;
+    }
+
+  accum_time += sym->hist.time;
+  if (bsd_style_output)
+    {
+      printf ("%5.1f %10.2f %8.2f",
+             total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
+             accum_time / hz, sym->hist.time / hz);
+    }
+  else
+    {
+      printf ("%6.2f %9.2f %8.2f",
+             total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
+             accum_time / hz, sym->hist.time / hz);
+    }
+  if (sym->ncalls != 0)
+    {
+      printf (" %8lu %8.2f %8.2f  ",
+             sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
+         scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
+    }
+  else
+    {
+      printf (" %8.8s %8.8s %8.8s  ", "", "", "");
+    }
+  if (bsd_style_output)
+    {
+      print_name (sym);
+    }
+  else
+    {
+      print_name_only (sym);
+    }
+  printf ("\n");
+}
+
+
+/*
+ * Compare LP and RP.  The primary comparison key is execution time,
+ * the secondary is number of invocation, and the tertiary is the
+ * lexicographic order of the function names.
+ */
+static int
+DEFUN (cmp_time, (lp, rp), const PTR lp AND const PTR rp)
+{
+  const Sym *left = *(const Sym **) lp;
+  const Sym *right = *(const Sym **) rp;
+  double time_diff;
+
+  time_diff = right->hist.time - left->hist.time;
+  if (time_diff > 0.0)
+    {
+      return 1;
+    }
+  if (time_diff < 0.0)
+    {
+      return -1;
+    }
+
+  if (right->ncalls > left->ncalls)
+    {
+      return 1;
+    }
+  if (right->ncalls < left->ncalls)
+    {
+      return -1;
+    }
+
+  return strcmp (left->name, right->name);
+}
+
+
+/*
+ * Print the flat histogram profile.
+ */
+void
+DEFUN_VOID (hist_print)
+{
+  Sym **time_sorted_syms, *top_dog, *sym;
+  unsigned int index;
+  int log_scale;
+  double top_time, time;
+  bfd_vma addr;
+
+  if (first_output)
+    {
+      first_output = FALSE;
+    }
+  else
+    {
+      printf ("\f\n");
+    }
+
+  accum_time = 0.0;
+  if (bsd_style_output)
+    {
+      if (print_descriptions)
+       {
+         printf (_("\n\n\nflat profile:\n"));
+         flat_blurb (stdout);
+       }
+    }
+  else
+    {
+      printf (_("Flat profile:\n"));
+    }
+  /*
+   * Sort the symbol table by time (call-count and name as secondary
+   * and tertiary keys):
+   */
+  time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+  for (index = 0; index < symtab.len; ++index)
+    {
+      time_sorted_syms[index] = &symtab.base[index];
+    }
+  qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
+
+  if (bsd_style_output)
+    {
+      log_scale = 5;           /* milli-seconds is BSD-default */
+    }
+  else
+    {
+      /*
+       * Search for symbol with highest per-call execution time and
+       * scale accordingly:
+       */
+      log_scale = 0;
+      top_dog = 0;
+      top_time = 0.0;
+      for (index = 0; index < symtab.len; ++index)
+       {
+         sym = time_sorted_syms[index];
+         if (sym->ncalls != 0)
+           {
+             time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
+             if (time > top_time)
+               {
+                 top_dog = sym;
+                 top_time = time;
+               }
+           }
+       }
+      if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
+       {
+         top_time /= hz;
+         while (SItab[log_scale].scale * top_time < 1000.0
+                && ((size_t) log_scale
+                    < sizeof (SItab) / sizeof (SItab[0]) - 1))
+           {
+             ++log_scale;
+           }
+       }
+    }
+
+  /*
+   * For now, the dimension is always seconds.  In the future, we
+   * may also want to support other (pseudo-)dimensions (such as
+   * I-cache misses etc.).
+   */
+  print_header (SItab[log_scale].prefix);
+  for (index = 0; index < symtab.len; ++index)
+    {
+      addr = time_sorted_syms[index]->addr;
+      /*
+       * Print symbol if its in INCL_FLAT table or that table
+       * is empty and the symbol is not in EXCL_FLAT.
+       */
+      if (sym_lookup (&syms[INCL_FLAT], addr)
+         || (syms[INCL_FLAT].len == 0
+             && !sym_lookup (&syms[EXCL_FLAT], addr)))
+       {
+         print_line (time_sorted_syms[index], SItab[log_scale].scale);
+       }
+    }
+  free (time_sorted_syms);
+
+  if (print_descriptions && !bsd_style_output)
+    {
+      flat_blurb (stdout);
+    }
+}
diff --git a/gprof/hist.h b/gprof/hist.h
new file mode 100644 (file)
index 0000000..df62ef7
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef hist_h
+#define hist_h
+
+#include "bfd.h"
+
+extern bfd_vma s_lowpc;                /* lowpc from the profile file */
+extern bfd_vma s_highpc;       /* highpc from the profile file */
+extern bfd_vma lowpc, highpc;  /* range profiled, in UNIT's */
+extern int hist_num_bins;      /* number of histogram bins */
+extern int *hist_sample;       /* code histogram */
+/*
+ * Scale factor converting samples to pc values: each sample covers
+ * HIST_SCALE bytes:
+ */
+extern double hist_scale;
+
+
+extern void hist_read_rec PARAMS ((FILE * ifp, const char *filename));
+extern void hist_write_hist PARAMS ((FILE * ofp, const char *filename));
+extern void hist_assign_samples PARAMS ((void));
+extern void hist_print PARAMS ((void));
+
+#endif /* hist_h */
diff --git a/gprof/i386.c b/gprof/i386.c
new file mode 100644 (file)
index 0000000..18aad1c
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "gprof.h"
+#include "cg_arcs.h"
+#include "corefile.h"
+#include "hist.h"
+#include "symtab.h"
+
+
+int
+DEFUN (i386_iscall, (ip), unsigned char *ip)
+{
+  if (*ip == 0xe8)
+    return 1;
+  return 0;
+}
+
+
+void
+i386_find_call (parent, p_lowpc, p_highpc)
+     Sym *parent;
+     bfd_vma p_lowpc;
+     bfd_vma p_highpc;
+{
+  unsigned char *instructp;
+  Sym *child;
+  bfd_vma destpc, delta;
+
+  if (core_text_space == 0)
+    {
+      return;
+    }
+  if (p_lowpc < s_lowpc)
+    {
+      p_lowpc = s_lowpc;
+    }
+  if (p_highpc > s_highpc)
+    {
+      p_highpc = s_highpc;
+    }
+  DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
+                         parent->name, p_lowpc, p_highpc));
+
+  delta = (bfd_vma) core_text_space - core_text_sect->vma;
+
+  for (instructp = (unsigned char *) (p_lowpc + delta);
+       instructp < (unsigned char *) (p_highpc + delta);
+       instructp ++)
+    {
+      if (i386_iscall (instructp))
+       {
+         DBG (CALLDEBUG,
+              printf ("[findcall]\t0x%x:call",
+                      instructp - (unsigned char *) delta));
+         /*
+          *  regular pc relative addressing
+          *    check that this is the address of 
+          *    a function.
+          */
+
+         destpc = ((bfd_vma) bfd_get_32 (core_bfd, instructp + 1)
+                   + (bfd_vma) instructp - (bfd_vma) delta + 5);
+         if (destpc >= s_lowpc && destpc <= s_highpc)
+           {
+             child = sym_lookup (&symtab, destpc);
+             if (child && child->addr == destpc)
+               {
+                 /*
+                  *      a hit
+                  */
+                 DBG (CALLDEBUG,
+                      printf ("\tdestpc 0x%lx (%s)\n", destpc, child->name));
+                 arc_add (parent, child, (unsigned long) 0);
+                 instructp += 4;       /* call is a 5 byte instruction */
+                 continue;
+               }
+           }
+         /*
+          *  else:
+          *    it looked like a callf, but it:
+          *      a) wasn't actually a callf, or
+          *      b) didn't point to a known function in the symtab, or
+          *      c) something funny is going on.
+          */
+         DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
+       }
+    }
+}
diff --git a/gprof/po/Make-in b/gprof/po/Make-in
new file mode 100644 (file)
index 0000000..0552db1
--- /dev/null
@@ -0,0 +1,251 @@
+# Makefile for program source directory in GNU NLS utilities package.
+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+#
+# This file file be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = $(prefix)/@DATADIRNAME@
+localedir = $(datadir)/locale
+gnulocaledir = $(prefix)/share/locale
+gettextsrcdir = $(prefix)/share/gettext/po
+subdir = po
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+
+CC = @CC@
+GENCAT = @GENCAT@
+GMSGFMT = PATH=../src:$$PATH @GMSGFMT@
+MSGFMT = @MSGFMT@
+XGETTEXT = PATH=../src:$$PATH @XGETTEXT@
+MSGMERGE = PATH=../src:$$PATH msgmerge
+
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+
+INCLUDES = -I.. -I$(top_srcdir)/intl
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+SOURCES = cat-id-tbl.c
+POFILES = @POFILES@
+GMOFILES = @GMOFILES@
+DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \
+stamp-cat-id $(POFILES) $(GMOFILES) $(SOURCES)
+
+POTFILES = \
+
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+INSTOBJEXT = @INSTOBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat
+
+.c.o:
+       $(COMPILE) $<
+
+.po.pox:
+       $(MAKE) $(PACKAGE).pot
+       $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
+
+.po.mo:
+       $(MSGFMT) -o $@ $<
+
+.po.gmo:
+       file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
+         && rm -f $$file && $(GMSGFMT) -o $$file $<
+
+.po.cat:
+       sed -f ../intl/po2msg.sed < $< > $*.msg \
+         && rm -f $@ && $(GENCAT) $@ $*.msg
+
+
+all: all-@USE_NLS@
+
+all-yes: $(CATALOGS) @MAINT@ $(PACKAGE).pot
+all-no:
+
+$(srcdir)/$(PACKAGE).pot: $(POTFILES)
+       $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
+         --add-comments --keyword=_ --keyword=N_ \
+         --files-from=$(srcdir)/POTFILES.in
+       rm -f $(srcdir)/$(PACKAGE).pot
+       mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot
+
+$(srcdir)/cat-id-tbl.c: stamp-cat-id; @:
+$(srcdir)/stamp-cat-id: $(PACKAGE).pot
+       rm -f cat-id-tbl.tmp
+       sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \
+               | sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp
+       if cmp -s cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; then \
+         rm cat-id-tbl.tmp; \
+       else \
+         echo cat-id-tbl.c changed; \
+         rm -f $(srcdir)/cat-id-tbl.c; \
+         mv cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; \
+       fi
+       cd $(srcdir) && rm -f stamp-cat-id && echo timestamp > stamp-cat-id
+
+
+install: install-exec install-data
+install-exec:
+install-info:
+install-data: install-data-@USE_NLS@
+install-data-no: all
+install-data-yes: all
+       if test -r $(MKINSTALLDIRS); then \
+         $(MKINSTALLDIRS) $(datadir); \
+       else \
+         $(top_srcdir)/mkinstalldirs $(datadir); \
+       fi
+       @catalogs='$(CATALOGS)'; \
+       for cat in $$catalogs; do \
+         cat=`basename $$cat`; \
+         case "$$cat" in \
+           *.gmo) destdir=$(gnulocaledir);; \
+           *)     destdir=$(localedir);; \
+         esac; \
+         lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+         dir=$$destdir/$$lang/LC_MESSAGES; \
+         if test -r $(MKINSTALLDIRS); then \
+           $(MKINSTALLDIRS) $$dir; \
+         else \
+           $(top_srcdir)/mkinstalldirs $$dir; \
+         fi; \
+         if test -r $$cat; then \
+           $(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
+           echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \
+         else \
+           $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
+           echo "installing $(srcdir)/$$cat as" \
+                "$$dir/$(PACKAGE)$(INSTOBJEXT)"; \
+         fi; \
+         if test -r $$cat.m; then \
+           $(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
+           echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
+         else \
+           if test -r $(srcdir)/$$cat.m ; then \
+             $(INSTALL_DATA) $(srcdir)/$$cat.m \
+               $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
+             echo "installing $(srcdir)/$$cat as" \
+                  "$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
+           else \
+             true; \
+           fi; \
+         fi; \
+       done
+       if test "$(PACKAGE)" = "gettext"; then \
+         if test -r $(MKINSTALLDIRS); then \
+           $(MKINSTALLDIRS) $(gettextsrcdir); \
+         else \
+           $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \
+         fi; \
+         $(INSTALL_DATA) $(srcdir)/Makefile.in.in \
+                         $(gettextsrcdir)/Makefile.in.in; \
+       else \
+         : ; \
+       fi
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+       catalogs='$(CATALOGS)'; \
+       for cat in $$catalogs; do \
+         cat=`basename $$cat`; \
+         lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+         rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
+         rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
+         rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
+         rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
+       done
+       rm -f $(gettextsrcdir)/po-Makefile.in.in
+
+check: all
+
+cat-id-tbl.o: ../intl/libgettext.h
+
+dvi info tags TAGS ID:
+
+mostlyclean:
+       rm -f core core.* *.pox $(PACKAGE).po *.old.po cat-id-tbl.tmp
+       rm -fr *.o
+
+clean: mostlyclean
+
+distclean: clean
+       rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m
+
+maintainer-clean: distclean
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+       rm -f $(GMOFILES)
+
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: update-po $(DISTFILES)
+       dists="$(DISTFILES)"; \
+       for file in $$dists; do \
+         ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+           || cp -p $(srcdir)/$$file $(distdir); \
+       done
+
+update-po: Makefile
+       $(MAKE) $(PACKAGE).pot
+       PATH=`pwd`/../src:$$PATH; \
+       cd $(srcdir); \
+       catalogs='$(CATALOGS)'; \
+       for cat in $$catalogs; do \
+         cat=`basename $$cat`; \
+         lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+         mv $$lang.po $$lang.old.po; \
+         echo "$$lang:"; \
+         if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \
+           rm -f $$lang.old.po; \
+         else \
+           echo "msgmerge for $$cat failed!"; \
+           rm -f $$lang.po; \
+           mv $$lang.old.po $$lang.po; \
+         fi; \
+       done
+
+POTFILES: POTFILES.in
+       ( if test 'x$(srcdir)' != 'x.'; then \
+           posrcprefix='$(top_srcdir)/'; \
+         else \
+           posrcprefix="../"; \
+         fi; \
+         rm -f $@-t $@ \
+           && (sed -e '/^#/d' -e '/^[  ]*$$/d' \
+                   -e "s@.*@   $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
+               | sed -e '$$s/\\$$//') > $@-t \
+           && chmod a-w $@-t \
+           && mv $@-t $@ )
+
+POTFILES.in: @MAINT@ ../Makefile
+       cd .. && $(MAKE) po/POTFILES.in
+
+Makefile: Make-in ../config.status POTFILES
+       cd .. \
+         && CONFIG_FILES=$(subdir)/Makefile.in:$(subdir)/Make-in \
+            CONFIG_HEADERS= $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gprof/po/POTFILES.in b/gprof/po/POTFILES.in
new file mode 100644 (file)
index 0000000..56d8641
--- /dev/null
@@ -0,0 +1,38 @@
+alpha.c
+basic_blocks.c
+basic_blocks.h
+bb_exit_func.c
+call_graph.c
+call_graph.h
+cg_arcs.c
+cg_arcs.h
+cg_dfn.c
+cg_dfn.h
+cg_print.c
+cg_print.h
+corefile.c
+corefile.h
+gmon.h
+gmon_io.c
+gmon_io.h
+gmon_out.h
+gprof.c
+gprof.h
+hertz.c
+hertz.h
+hist.c
+hist.h
+i386.c
+search_list.c
+search_list.h
+source.c
+source.h
+sparc.c
+sym_ids.c
+sym_ids.h
+symtab.c
+symtab.h
+tahoe.c
+utils.c
+utils.h
+vax.c
diff --git a/gprof/po/gprof.pot b/gprof/po/gprof.pot
new file mode 100644 (file)
index 0000000..36bf787
--- /dev/null
@@ -0,0 +1,470 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 1998-06-12 19:33-0400\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+
+#: alpha.c:89
+msgid "<indirect child>"
+msgstr ""
+
+#: alpha.c:106
+#, c-format
+msgid "[find_call] %s: 0x%lx to 0x%lx\n"
+msgstr ""
+
+#: alpha.c:127
+#, c-format
+msgid "[find_call] 0x%lx: jsr%s <indirect_child>\n"
+msgstr ""
+
+#: alpha.c:136
+#, c-format
+msgid "[find_call] 0x%lx: bsr"
+msgstr ""
+
+#: basic_blocks.c:134 call_graph.c:70 hist.c:105
+#, c-format
+msgid "%s: %s: unexpected end of file\n"
+msgstr ""
+
+#: basic_blocks.c:214
+#, c-format
+msgid "%s: warning: ignoring basic-block exec counts (use -l or --line)\n"
+msgstr ""
+
+#: basic_blocks.c:322 basic_blocks.c:330
+#, c-format
+msgid "%s:%d: (%s:0x%lx) %d executions\n"
+msgstr ""
+
+#: basic_blocks.c:323 basic_blocks.c:331
+msgid "<unknown>"
+msgstr ""
+
+#: basic_blocks.c:584
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Top %d Lines:\n"
+"\n"
+"     Line      Count\n"
+"\n"
+msgstr ""
+
+#: basic_blocks.c:608
+msgid ""
+"\n"
+"Execution Summary:\n"
+"\n"
+msgstr ""
+
+#: basic_blocks.c:609
+#, c-format
+msgid "%9ld   Executable lines in this file\n"
+msgstr ""
+
+#: basic_blocks.c:611
+#, c-format
+msgid "%9ld   Lines executed\n"
+msgstr ""
+
+#: basic_blocks.c:612
+#, c-format
+msgid "%9.2f   Percent of the file executed\n"
+msgstr ""
+
+#: basic_blocks.c:616
+#, c-format
+msgid ""
+"\n"
+"%9d   Total number of line executions\n"
+msgstr ""
+
+#: basic_blocks.c:617
+#, c-format
+msgid "%9.2f   Average executions per line\n"
+msgstr ""
+
+#: call_graph.c:48
+#, c-format
+msgid "[cg_tally] arc from %s to %s traversed %d times\n"
+msgstr ""
+
+#: cg_print.c:39
+msgid ""
+"\t\t     Call graph (explanation follows)\n"
+"\n"
+msgstr ""
+
+#: cg_print.c:43
+msgid ""
+"\t\t\tCall graph\n"
+"\n"
+msgstr ""
+
+#: cg_print.c:46 hist.c:381
+#, c-format
+msgid ""
+"\n"
+"granularity: each sample hit covers %ld byte(s)"
+msgstr ""
+
+#: cg_print.c:50
+msgid ""
+" for %.2f%% of %.2f seconds\n"
+"\n"
+msgstr ""
+
+#: cg_print.c:55
+msgid ""
+" no time propagated\n"
+"\n"
+msgstr ""
+
+#: cg_print.c:64 cg_print.c:67 cg_print.c:69
+msgid "called"
+msgstr ""
+
+#: cg_print.c:64 cg_print.c:69
+msgid "total"
+msgstr ""
+
+#: cg_print.c:64
+msgid "parents"
+msgstr ""
+
+#: cg_print.c:66 cg_print.c:67
+msgid "index"
+msgstr ""
+
+#: cg_print.c:66
+msgid "%time"
+msgstr ""
+
+#: cg_print.c:66 cg_print.c:67
+msgid "self"
+msgstr ""
+
+#: cg_print.c:66
+msgid "descendents"
+msgstr ""
+
+#: cg_print.c:67 hist.c:405
+msgid "name"
+msgstr ""
+
+#: cg_print.c:69
+msgid "children"
+msgstr ""
+
+#: cg_print.c:74
+msgid "index %% time    self  children    called     name\n"
+msgstr ""
+
+#: cg_print.c:101
+#, c-format
+msgid " <cycle %d as a whole> [%d]\n"
+msgstr ""
+
+#: cg_print.c:353
+#, c-format
+msgid "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n"
+msgstr ""
+
+#: cg_print.c:354
+#, c-format
+msgid "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s     <spontaneous>\n"
+msgstr ""
+
+#: cg_print.c:587
+msgid ""
+"Index by function name\n"
+"\n"
+msgstr ""
+
+#: cg_print.c:644 cg_print.c:653
+#, c-format
+msgid "<cycle %d>"
+msgstr ""
+
+#: corefile.c:39
+#, c-format
+msgid "%s: could not open %s.\n"
+msgstr ""
+
+#: corefile.c:53 corefile.c:87
+#, c-format
+msgid "%s: unable to parse mapping file %s.\n"
+msgstr ""
+
+#: corefile.c:128
+#, c-format
+msgid "%s: %s: not in a.out format\n"
+msgstr ""
+
+#: corefile.c:139
+#, c-format
+msgid "%s: can't find .text section in %s\n"
+msgstr ""
+
+#: corefile.c:198
+#, c-format
+msgid "%s: ran out room for %ld bytes of text space\n"
+msgstr ""
+
+#: corefile.c:211
+#, c-format
+msgid "%s: can't do -c\n"
+msgstr ""
+
+#: corefile.c:243
+#, c-format
+msgid "%s: -c not supported on architecture %s\n"
+msgstr ""
+
+#: corefile.c:432
+#, c-format
+msgid "%s: file `%s' has no symbols\n"
+msgstr ""
+
+#: corefile.c:726
+#, c-format
+msgid "%s: somebody miscounted: ltab.len=%d instead of %ld\n"
+msgstr ""
+
+#: gmon_io.c:33 gmon_io.c:55
+#, c-format
+msgid "%s: bfd_vma has unexpected size of %ld bytes\n"
+msgstr ""
+
+#: gmon_io.c:87 gmon_io.c:179
+#, c-format
+msgid "%s: file too short to be a gmon file\n"
+msgstr ""
+
+#: gmon_io.c:97
+#, c-format
+msgid "%s: file `%s' has bad magic cookie\n"
+msgstr ""
+
+#: gmon_io.c:108
+#, c-format
+msgid "%s: file `%s' has unsupported version %d\n"
+msgstr ""
+
+#: gmon_io.c:138
+#, c-format
+msgid "%s: %s: found bad tag %d (file corrupted?)\n"
+msgstr ""
+
+#: gmon_io.c:197
+#, c-format
+msgid "%s: profiling rate incompatible with first gmon file\n"
+msgstr ""
+
+#: gmon_io.c:207
+#, c-format
+msgid "%s: incompatible with first gmon file\n"
+msgstr ""
+
+#: gmon_io.c:245
+#, c-format
+msgid "%s: unexpected EOF after reading %d/%d bins\n"
+msgstr ""
+
+#: gmon_io.c:280
+msgid "time is in ticks, not seconds\n"
+msgstr ""
+
+#: gmon_io.c:286 gmon_io.c:410
+#, c-format
+msgid "%s: don't know how to deal with file format %d\n"
+msgstr ""
+
+#: gmon_io.c:293
+#, c-format
+msgid "File `%s' (version %d) contains:\n"
+msgstr ""
+
+#: gmon_io.c:295
+#, c-format
+msgid "\t%d histogram record%s\n"
+msgstr ""
+
+#: gmon_io.c:297
+#, c-format
+msgid "\t%d call-graph record%s\n"
+msgstr ""
+
+#: gmon_io.c:299
+#, c-format
+msgid "\t%d basic-block count record%s\n"
+msgstr ""
+
+#: gprof.c:59
+msgid ""
+"@(#) Copyright (c) 1983 Regents of the University of California.\n"
+" All rights reserved.\n"
+msgstr ""
+
+#: gprof.c:144
+#, c-format
+msgid ""
+"Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n"
+"\t[-d[num]] [-k from/to] [-m min-count] [-t table-length]\n"
+"\t[--[no-]annotated-source[=name]] [--[no-]exec-counts[=name]]\n"
+"\t[--[no-]flat-profile[=name]] [--[no-]graph[=name]]\n"
+"\t[--[no-]time=name] [--all-lines] [--brief] [--debug[=level]]\n"
+"\t[--function-ordering] [--file-ordering]\n"
+"\t[--directory-path=dirs] [--display-unused-functions]\n"
+"\t[--file-format=name] [--file-info] [--help] [--line] [--min-count=n]\n"
+"\t[--no-static] [--print-path] [--separate-files]\n"
+"\t[--static-call-graph] [--sum] [--table-length=len] [--traditional]\n"
+"\t[--version] [--width=n] [--ignore-non-functions]\n"
+"\t[--demangle] [--no-demangle]\n"
+"\t[image-file] [profile-file...]\n"
+msgstr ""
+
+#: gprof.c:160
+msgid "Report bugs to bug-gnu-utils@gnu.org\n"
+msgstr ""
+
+#: gprof.c:229
+#, c-format
+msgid "%s: debugging not supported; -d ignored\n"
+msgstr ""
+
+#: gprof.c:306
+#, c-format
+msgid "%s: unknown file format %s\n"
+msgstr ""
+
+#. This output is intended to follow the GNU standards document.
+#: gprof.c:390
+#, c-format
+msgid "GNU gprof %s\n"
+msgstr ""
+
+#: gprof.c:391
+msgid ""
+"Based on BSD gprof, copyright 1983 Regents of the University of California.\n"
+msgstr ""
+
+#: gprof.c:392
+msgid ""
+"This program is free software.  This program has absolutely no warranty.\n"
+msgstr ""
+
+#: gprof.c:438
+#, c-format
+msgid ""
+"%s: Only one of --function-ordering and --file-ordering may be specified.\n"
+msgstr ""
+
+#: gprof.c:538
+#, c-format
+msgid "%s: sorry, file format `prof' is not yet supported\n"
+msgstr ""
+
+#: gprof.c:599
+#, c-format
+msgid "%s: gmon.out file is missing histogram\n"
+msgstr ""
+
+#: gprof.c:606
+#, c-format
+msgid "%s: gmon.out file is missing call-graph data\n"
+msgstr ""
+
+#: hist.c:142
+#, c-format
+msgid "%s: `%s' is incompatible with first gmon file\n"
+msgstr ""
+
+#: hist.c:158
+#, c-format
+msgid "%s: %s: unexpected EOF after reading %d of %d samples\n"
+msgstr ""
+
+#: hist.c:377
+#, c-format
+msgid "%c%c/call"
+msgstr ""
+
+#: hist.c:385
+msgid ""
+" for %.2f%% of %.2f %s\n"
+"\n"
+msgstr ""
+
+#: hist.c:391
+#, c-format
+msgid ""
+"\n"
+"Each sample counts as %g %s.\n"
+msgstr ""
+
+#: hist.c:396
+msgid ""
+" no time accumulated\n"
+"\n"
+msgstr ""
+
+#: hist.c:402
+msgid "cumulative"
+msgstr ""
+
+#: hist.c:402
+msgid "self  "
+msgstr ""
+
+#: hist.c:402
+msgid "total "
+msgstr ""
+
+#: hist.c:404
+msgid "time"
+msgstr ""
+
+#: hist.c:404
+msgid "calls"
+msgstr ""
+
+#: hist.c:515
+msgid ""
+"\n"
+"\n"
+"\n"
+"flat profile:\n"
+msgstr ""
+
+#: hist.c:521
+msgid "Flat profile:\n"
+msgstr ""
+
+#: source.c:140
+#, c-format
+msgid "%s: could not locate `%s'\n"
+msgstr ""
+
+#: source.c:200
+#, c-format
+msgid "*** File %s:\n"
+msgstr ""
+
+#: utils.c:93
+#, c-format
+msgid " <cycle %d>"
+msgstr ""
diff --git a/gprof/search_list.c b/gprof/search_list.c
new file mode 100644 (file)
index 0000000..d475dbf
--- /dev/null
@@ -0,0 +1,44 @@
+#include "libiberty.h"
+#include "gprof.h"
+#include "search_list.h"
+
+
+void
+DEFUN (search_list_append, (list, paths),
+       Search_List * list AND const char *paths)
+{
+  Search_List_Elem *new_el;
+  const char *beg, *colon;
+  int len;
+
+  colon = paths - 1;
+  do
+    {
+      beg = colon + 1;
+      colon = strchr (beg, ':');
+      if (colon)
+       {
+         len = colon - beg;
+       }
+      else
+       {
+         len = strlen (beg);
+       }
+      new_el = (Search_List_Elem *) xmalloc (sizeof (*new_el) + len);
+      memcpy (new_el->path, beg, len);
+      new_el->path[len] = '\0';
+
+      /* append new path at end of list: */
+      new_el->next = 0;
+      if (list->tail)
+       {
+         list->tail->next = new_el;
+       }
+      else
+       {
+         list->head = new_el;
+       }
+      list->tail = new_el;
+    }
+  while (colon);
+}
diff --git a/gprof/search_list.h b/gprof/search_list.h
new file mode 100644 (file)
index 0000000..54dfe35
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef search_list_h
+#define search_list_h
+
+typedef struct search_list_elem
+  {
+    struct search_list_elem *next;
+    char path[1];
+  }
+Search_List_Elem;
+
+typedef struct
+  {
+    struct search_list_elem *head;
+    struct search_list_elem *tail;
+  }
+Search_List;
+
+extern void search_list_append PARAMS ((Search_List * list, const char *paths));
+
+#endif /* search_list_h */
diff --git a/gprof/source.c b/gprof/source.c
new file mode 100644 (file)
index 0000000..4901a04
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Keeps track of source files.
+ */
+#include "gprof.h"
+#include "libiberty.h"
+#include "search_list.h"
+#include "source.h"
+
+#define EXT_ANNO "-ann"                /* postfix of annotated files */
+
+/*
+ * Default option values:
+ */
+bool create_annotation_files = FALSE;
+
+Search_List src_search_list =
+{0, 0};
+Source_File *first_src_file = 0;
+
+
+Source_File *
+DEFUN (source_file_lookup_path, (path), const char *path)
+{
+  Source_File *sf;
+
+  for (sf = first_src_file; sf; sf = sf->next)
+    {
+      if (strcmp (path, sf->name) == 0)
+       {
+         break;
+       }
+    }
+  if (!sf)
+    {
+      /* create a new source file descriptor: */
+
+      sf = (Source_File *) xmalloc (sizeof (*sf));
+      memset (sf, 0, sizeof (*sf));
+      sf->name = xstrdup (path);
+      sf->next = first_src_file;
+      first_src_file = sf;
+    }
+  return sf;
+}
+
+
+Source_File *
+DEFUN (source_file_lookup_name, (filename), const char *filename)
+{
+  const char *fname;
+  Source_File *sf;
+  /*
+   * The user cannot know exactly how a filename will be stored in
+   * the debugging info (e.g., ../include/foo.h
+   * vs. /usr/include/foo.h).  So we simply compare the filename
+   * component of a path only:
+   */
+  for (sf = first_src_file; sf; sf = sf->next)
+    {
+      fname = strrchr (sf->name, '/');
+      if (fname)
+       {
+         ++fname;
+       }
+      else
+       {
+         fname = sf->name;
+       }
+      if (strcmp (filename, fname) == 0)
+       {
+         break;
+       }
+    }
+  return sf;
+}
+
+
+FILE *
+DEFUN (annotate_source, (sf, max_width, annote, arg),
+       Source_File * sf AND int max_width
+       AND void (*annote) PARAMS ((char *buf, int w, int l, void *arg))
+       AND void *arg)
+{
+  static bool first_file = TRUE;
+  int i, line_num, nread;
+  bool new_line;
+  char buf[8192];
+  char fname[PATH_MAX];
+  char *annotation, *name_only;
+  FILE *ifp, *ofp;
+  Search_List_Elem *sle = src_search_list.head;
+
+  /*
+   * Open input file.  If open fails, walk along search-list until
+   * open succeeds or reaching end of list:
+   */
+  strcpy (fname, sf->name);
+  if (sf->name[0] == '/')
+    {
+      sle = 0;                 /* don't use search list for absolute paths */
+    }
+  name_only = 0;
+  while (TRUE)
+    {
+      DBG (SRCDEBUG, printf ("[annotate_source]: looking for %s, trying %s\n",
+                            sf->name, fname));
+      ifp = fopen (fname, FOPEN_RB);
+      if (ifp)
+       {
+         break;
+       }
+      if (!sle && !name_only)
+       {
+         name_only = strrchr (sf->name, '/');
+         if (name_only)
+           {
+             /* try search-list again, but this time with name only: */
+             ++name_only;
+             sle = src_search_list.head;
+           }
+       }
+      if (sle)
+       {
+         strcpy (fname, sle->path);
+         strcat (fname, "/");
+         if (name_only)
+           {
+             strcat (fname, name_only);
+           }
+         else
+           {
+             strcat (fname, sf->name);
+           }
+         sle = sle->next;
+       }
+      else
+       {
+         if (errno == ENOENT)
+           {
+             fprintf (stderr, _("%s: could not locate `%s'\n"),
+                      whoami, sf->name);
+           }
+         else
+           {
+             perror (sf->name);
+           }
+         return 0;
+       }
+    }
+
+  ofp = stdout;
+  if (create_annotation_files)
+    {
+      /* try to create annotated source file: */
+      const char *filename;
+
+      /* create annotation files in the current working directory: */
+      filename = strrchr (sf->name, '/');
+      if (filename)
+       {
+         ++filename;
+       }
+      else
+       {
+         filename = sf->name;
+       }
+
+      strcpy (fname, filename);
+      strcat (fname, EXT_ANNO);
+      ofp = fopen (fname, "w");
+      if (!ofp)
+       {
+         perror (fname);
+         return 0;
+       }
+    }
+
+  /*
+   * Print file names if output goes to stdout and there are
+   * more than one source file:
+   */
+  if (ofp == stdout)
+    {
+      if (first_file)
+       {
+         first_file = FALSE;
+       }
+      else
+       {
+         fputc ('\n', ofp);
+       }
+      if (first_output)
+       {
+         first_output = FALSE;
+       }
+      else
+       {
+         fprintf (ofp, "\f\n");
+       }
+      fprintf (ofp, _("*** File %s:\n"), sf->name);
+    }
+
+  annotation = xmalloc (max_width + 1);
+  line_num = 1;
+  new_line = TRUE;
+  while ((nread = fread (buf, 1, sizeof (buf), ifp)) > 0)
+    {
+      for (i = 0; i < nread; ++i)
+       {
+         if (new_line)
+           {
+             (*annote) (annotation, max_width, line_num, arg);
+             fputs (annotation, ofp);
+             ++line_num;
+             new_line = FALSE;
+           }
+         new_line = (buf[i] == '\n');
+         fputc (buf[i], ofp);
+       }
+    }
+  free (annotation);
+  return ofp;
+}
diff --git a/gprof/source.h b/gprof/source.h
new file mode 100644 (file)
index 0000000..b33bad3
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef source_h
+#define source_h
+
+#include <stdio.h>
+#include "gprof.h"
+#include "search_list.h"
+
+typedef struct source_file
+  {
+    struct source_file *next;
+    const char *name;          /* name of source file */
+    unsigned long ncalls;      /* # of "calls" to this file */
+    int num_lines;             /* # of lines in file */
+    int nalloced;              /* number of lines allocated */
+    void **line;               /* usage-dependent per-line data */
+  }
+Source_File;
+
+/*
+ * Options:
+ */
+extern bool create_annotation_files;   /* create annotated output files? */
+
+/*
+ * List of directories to search for source files:
+ */
+extern Search_List src_search_list;
+
+/*
+ * Chain of source-file descriptors:
+ */
+extern Source_File *first_src_file;
+
+/*
+ * Returns pointer to source file descriptor for PATH/FILENAME.
+ */
+extern Source_File *source_file_lookup_path PARAMS ((const char *path));
+extern Source_File *source_file_lookup_name PARAMS ((const char *filename));
+
+/*
+ * Read source file SF output annotated source.  The annotation is at
+ * MAX_WIDTH characters wide and for each source-line an annotation is
+ * obtained by invoking function ANNOTE.  ARG is an argument passed to
+ * ANNOTE that is left uninterpreted by annotate_source().
+ *
+ * Returns a pointer to the output file (which maybe stdout) such
+ * that summary statistics can be printed.  If the returned file
+ * is not stdout, it should be closed when done with it.
+ */
+extern FILE *annotate_source PARAMS ((Source_File * sf, int max_width,
+                                     void (*annote) (char *b, int w, int l,
+                                                     void *arg),
+                                     void *arg));
+
+#endif /* source_h */
diff --git a/gprof/sparc.c b/gprof/sparc.c
new file mode 100644 (file)
index 0000000..ad702b1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "gprof.h"
+#include "cg_arcs.h"
+#include "corefile.h"
+#include "hist.h"
+#include "symtab.h"
+
+    /*
+     *        opcode of the `callf' instruction
+     */
+#define        CALL    (0xc0000000)
+
+void
+sparc_find_call (parent, p_lowpc, p_highpc)
+     Sym *parent;
+     bfd_vma p_lowpc;
+     bfd_vma p_highpc;
+{
+  bfd_vma dest_pc, delta;
+  unsigned int *instr;
+  Sym *child;
+
+  delta = (bfd_vma) core_text_space - core_text_sect->vma;
+
+  if (core_text_space == 0)
+    {
+      return;
+    }
+  if (p_lowpc < s_lowpc)
+    {
+      p_lowpc = s_lowpc;
+    }
+  if (p_highpc > s_highpc)
+    {
+      p_highpc = s_highpc;
+    }
+  DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n",
+                         parent->name, p_lowpc, p_highpc));
+  for (instr = (unsigned int *) (((p_lowpc + delta) + 3) &~ 3);
+       instr < (unsigned int *) (p_highpc + delta);
+       ++instr)
+    {
+      if ((*instr & CALL))
+       {
+         DBG (CALLDEBUG,
+              printf ("[find_call] 0x%lx: callf", (bfd_vma) instr - delta));
+         /*
+          * Regular pc relative addressing check that this is the
+          * address of a function.
+          */
+         dest_pc = ((bfd_vma) (instr + (*instr & ~CALL))) - delta;
+         if (dest_pc >= s_lowpc && dest_pc <= s_highpc)
+           {
+             child = sym_lookup (&symtab, dest_pc);
+             DBG (CALLDEBUG,
+                  printf ("\tdest_pc=0x%lx, (name=%s, addr=0x%lx)\n",
+                          dest_pc, child->name, child->addr));
+             if (child->addr == dest_pc)
+               {
+                 /* a hit:  */
+                 arc_add (parent, child, (unsigned long) 0);
+                 continue;
+               }
+           }
+         /*
+          * Something funny going on.
+          */
+         DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
+       }
+    }
+}
diff --git a/gprof/stamp-h.in b/gprof/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/gprof/sym_ids.c b/gprof/sym_ids.c
new file mode 100644 (file)
index 0000000..ba3ca28
--- /dev/null
@@ -0,0 +1,372 @@
+#include <ctype.h>
+
+#include "libiberty.h"
+#include "cg_arcs.h"
+#include "sym_ids.h"
+
+struct sym_id
+  {
+    struct sym_id *next;
+    char *spec;                        /* parsing modifies this */
+    Table_Id which_table;
+    bool has_right;
+    struct match
+      {
+       int prev_index;         /* index of prev match */
+       Sym *prev_match;        /* previous match */
+       Sym *first_match;       /* chain of all matches */
+       Sym sym;
+      }
+    left, right;
+  }
+ *id_list;
+
+Sym_Table syms[NUM_TABLES];
+
+#ifdef DEBUG
+const char *table_name[] =
+{
+  "INCL_GRAPH", "EXCL_GRAPH",
+  "INCL_ARCS", "EXCL_ARCS",
+  "INCL_FLAT", "EXCL_FLAT",
+  "INCL_TIME", "EXCL_TIME",
+  "INCL_ANNO", "EXCL_ANNO",
+  "INCL_EXEC", "EXCL_EXEC"
+};
+#endif /* DEBUG */
+
+/*
+ * This is the table in which we keep all the syms that match
+ * the right half of an arc id.  It is NOT sorted according
+ * to the addresses, because it is accessed only through
+ * the left half's CHILDREN pointers (so it's crucial not
+ * to reorder this table once pointers into it exist).
+ */
+static Sym_Table right_ids;
+
+static Source_File non_existent_file =
+{
+  0, "<non-existent-file>"
+};
+
+
+void
+DEFUN (sym_id_add, (spec, which_table),
+       const char *spec AND Table_Id which_table)
+{
+  struct sym_id *id;
+  int len = strlen (spec);
+
+  id = (struct sym_id *) xmalloc (sizeof (*id) + len + 1);
+  memset (id, 0, sizeof (*id));
+
+  id->spec = (char *) id + sizeof (*id);
+  strcpy (id->spec, spec);
+  id->which_table = which_table;
+
+  id->next = id_list;
+  id_list = id;
+}
+
+
+/*
+ * A spec has the syntax FILENAME:(FUNCNAME|LINENUM).  As a convenience
+ * to the user, a spec without a colon is interpreted as:
+ *
+ *      (i)   a FILENAME if it contains a dot
+ *      (ii)  a FUNCNAME if it starts with a non-digit character
+ *      (iii) a LINENUM if it starts with a digit
+ *
+ * A FUNCNAME containing a dot can be specified by :FUNCNAME, a
+ * FILENAME not containing a dot can be specified by FILENAME:.
+ */
+static void
+DEFUN (parse_spec, (spec, sym), char *spec AND Sym * sym)
+{
+  char *colon;
+
+  sym_init (sym);
+  colon = strrchr (spec, ':');
+  if (colon)
+    {
+      *colon = '\0';
+      if (colon > spec)
+       {
+         sym->file = source_file_lookup_name (spec);
+         if (!sym->file)
+           {
+             sym->file = &non_existent_file;
+           }
+       }
+      spec = colon + 1;
+      if (strlen (spec))
+       {
+         if (isdigit ((unsigned char) spec[0]))
+           {
+             sym->line_num = atoi (spec);
+           }
+         else
+           {
+             sym->name = spec;
+           }
+       }
+    }
+  else if (strlen (spec))
+    {
+      /* no colon: spec is a filename if it contains a dot: */
+      if (strchr (spec, '.'))
+       {
+         sym->file = source_file_lookup_name (spec);
+         if (!sym->file)
+           {
+             sym->file = &non_existent_file;
+           }
+       }
+      else if (isdigit ((unsigned char) *spec))
+       {
+         sym->line_num = atoi (spec);
+       }
+      else if (strlen (spec))
+       {
+         sym->name = spec;
+       }
+    }
+}
+
+
+/*
+ * A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
+ * by parse_spec().
+ */
+static void
+DEFUN (parse_id, (id), struct sym_id *id)
+{
+  char *slash;
+
+  DBG (IDDEBUG, printf ("[parse_id] %s -> ", id->spec));
+
+  slash = strchr (id->spec, '/');
+  if (slash)
+    {
+      parse_spec (slash + 1, &id->right.sym);
+      *slash = '\0';
+      id->has_right = TRUE;
+    }
+  parse_spec (id->spec, &id->left.sym);
+
+#ifdef DEBUG
+  if (debug_level & IDDEBUG)
+    {
+      printf ("%s:", id->left.sym.file ? id->left.sym.file->name : "*");
+      if (id->left.sym.name)
+       {
+         printf ("%s", id->left.sym.name);
+       }
+      else if (id->left.sym.line_num)
+       {
+         printf ("%d", id->left.sym.line_num);
+       }
+      else
+       {
+         printf ("*");
+       }
+      if (id->has_right)
+       {
+         printf ("/%s:",
+                 id->right.sym.file ? id->right.sym.file->name : "*");
+         if (id->right.sym.name)
+           {
+             printf ("%s", id->right.sym.name);
+           }
+         else if (id->right.sym.line_num)
+           {
+             printf ("%d", id->right.sym.line_num);
+           }
+         else
+           {
+             printf ("*");
+           }
+       }
+      printf ("\n");
+    }
+#endif
+}
+
+
+/*
+ * Return TRUE iff PATTERN matches SYM.
+ */
+static bool
+DEFUN (match, (pattern, sym), Sym * pattern AND Sym * sym)
+{
+  return (pattern->file ? pattern->file == sym->file : TRUE)
+    && (pattern->line_num ? pattern->line_num == sym->line_num : TRUE)
+    && (pattern->name ? strcmp (pattern->name, sym->name) == 0 : TRUE);
+}
+
+
+static void
+DEFUN (extend_match, (m, sym, tab, second_pass),
+     struct match *m AND Sym * sym AND Sym_Table * tab AND bool second_pass)
+{
+  if (m->prev_match != sym - 1)
+    {
+      /* discontinuity: add new match to table: */
+      if (second_pass)
+       {
+         tab->base[tab->len] = *sym;
+         m->prev_index = tab->len;
+
+         /* link match into match's chain: */
+         tab->base[tab->len].next = m->first_match;
+         m->first_match = &tab->base[tab->len];
+       }
+      ++tab->len;
+    }
+
+  /* extend match to include this symbol: */
+  if (second_pass)
+    {
+      tab->base[m->prev_index].end_addr = sym->end_addr;
+    }
+  m->prev_match = sym;
+}
+
+
+/*
+ * Go through sym_id list produced by option processing and fill
+ * in the various symbol tables indicating what symbols should
+ * be displayed or suppressed for the various kinds of outputs.
+ *
+ * This can potentially produce huge tables and in particulars
+ * tons of arcs, but this happens only if the user makes silly
+ * requests---you get what you ask for!
+ */
+void
+DEFUN_VOID (sym_id_parse)
+{
+  Sym *sym, *left, *right;
+  struct sym_id *id;
+  Sym_Table *tab;
+
+  /*
+   * Convert symbol ids into Syms, so we can deal with them more easily:
+   */
+  for (id = id_list; id; id = id->next)
+    {
+      parse_id (id);
+    }
+
+  /* first determine size of each table: */
+
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      for (id = id_list; id; id = id->next)
+       {
+         if (match (&id->left.sym, sym))
+           {
+             extend_match (&id->left, sym, &syms[id->which_table], FALSE);
+           }
+         if (id->has_right && match (&id->right.sym, sym))
+           {
+             extend_match (&id->right, sym, &right_ids, FALSE);
+           }
+       }
+    }
+
+  /* create tables of appropriate size and reset lengths: */
+
+  for (tab = syms; tab < &syms[NUM_TABLES]; ++tab)
+    {
+      if (tab->len)
+       {
+         tab->base = (Sym *) xmalloc (tab->len * sizeof (Sym));
+         tab->limit = tab->base + tab->len;
+         tab->len = 0;
+       }
+    }
+  if (right_ids.len)
+    {
+      right_ids.base = (Sym *) xmalloc (right_ids.len * sizeof (Sym));
+      right_ids.limit = right_ids.base + right_ids.len;
+      right_ids.len = 0;
+    }
+
+  /* make a second pass through symtab, creating syms as necessary: */
+
+  for (sym = symtab.base; sym < symtab.limit; ++sym)
+    {
+      for (id = id_list; id; id = id->next)
+       {
+         if (match (&id->left.sym, sym))
+           {
+             extend_match (&id->left, sym, &syms[id->which_table], TRUE);
+           }
+         if (id->has_right && match (&id->right.sym, sym))
+           {
+             extend_match (&id->right, sym, &right_ids, TRUE);
+           }
+       }
+    }
+
+  /* go through ids creating arcs as needed: */
+
+  for (id = id_list; id; id = id->next)
+    {
+      if (id->has_right)
+       {
+         for (left = id->left.first_match; left; left = left->next)
+           {
+             for (right = id->right.first_match; right; right = right->next)
+               {
+                 DBG (IDDEBUG,
+                      printf (
+                               "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
+                               left->file ? left->file->name : "*",
+                               left->name ? left->name : "*", left->addr,
+                               left->end_addr,
+                               right->file ? right->file->name : "*",
+                               right->name ? right->name : "*", right->addr,
+                               right->end_addr,
+                               table_name[id->which_table]));
+                 arc_add (left, right, (unsigned long) 0);
+               }
+           }
+       }
+    }
+
+  /* finally, we can sort the tables and we're done: */
+
+  for (tab = &syms[0]; tab < &syms[NUM_TABLES]; ++tab)
+    {
+      DBG (IDDEBUG, printf ("[sym_id_parse] syms[%s]:\n",
+                           table_name[tab - &syms[0]]));
+      symtab_finalize (tab);
+    }
+}
+
+
+/*
+ * Symbol tables storing the FROM symbols of arcs do not necessarily
+ * have distinct address ranges.  For example, somebody might request
+ * -k /_mcount to suppress any arcs into _mcount, while at the same
+ * time requesting -k a/b.  Fortunately, those symbol tables don't get
+ * very big (the user has to type them!), so a linear search is probably
+ * tolerable.
+ */
+bool
+DEFUN (sym_id_arc_is_present, (symtab, from, to),
+       Sym_Table * symtab AND Sym * from AND Sym * to)
+{
+  Sym *sym;
+
+  for (sym = symtab->base; sym < symtab->limit; ++sym)
+    {
+      if (from->addr >= sym->addr && from->addr <= sym->end_addr
+         && arc_lookup (sym, to))
+       {
+         return TRUE;
+       }
+    }
+  return FALSE;
+}
diff --git a/gprof/sym_ids.h b/gprof/sym_ids.h
new file mode 100644 (file)
index 0000000..9096338
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef sym_ids_h
+#define sym_ids_h
+
+#include "symtab.h"
+
+typedef enum
+  {
+    INCL_GRAPH = 0, EXCL_GRAPH,
+    INCL_ARCS, EXCL_ARCS,
+    INCL_FLAT, EXCL_FLAT,
+    INCL_TIME, EXCL_TIME,
+    INCL_ANNO, EXCL_ANNO,
+    INCL_EXEC, EXCL_EXEC,
+    NUM_TABLES
+  }
+Table_Id;
+
+extern Sym_Table syms[NUM_TABLES];
+
+extern void sym_id_add PARAMS ((const char *spec, Table_Id which_table));
+extern void sym_id_parse PARAMS ((void));
+extern bool sym_id_arc_is_present PARAMS ((Sym_Table * symtab,
+                                          Sym * from, Sym * to));
+
+#endif /* sym_ids_h */
diff --git a/gprof/symtab.c b/gprof/symtab.c
new file mode 100644 (file)
index 0000000..182c657
--- /dev/null
@@ -0,0 +1,269 @@
+#include "gprof.h"
+#include "cg_arcs.h"
+#include "corefile.h"
+#include "symtab.h"
+
+Sym_Table symtab;
+
+
+/*
+ * Initialize a symbol (so it's empty).
+ */
+void
+DEFUN (sym_init, (sym), Sym * sym)
+{
+  memset (sym, 0, sizeof (*sym));
+  /*
+   * It is not safe to assume that a binary zero corresponds to
+   * a floating-point 0.0, so initialize floats explicitly:
+   */
+  sym->hist.time = 0.0;
+  sym->cg.child_time = 0.0;
+  sym->cg.prop.fract = 0.0;
+  sym->cg.prop.self = 0.0;
+  sym->cg.prop.child = 0.0;
+}
+
+
+/*
+ * Compare the function entry-point of two symbols and return <0, =0,
+ * or >0 depending on whether the left value is smaller than, equal
+ * to, or greater than the right value.  If two symbols are equal
+ * but one has is_func set and the other doesn't, we make the
+ * non-function symbol one "bigger" so that the function symbol will
+ * survive duplicate removal.  Finally, if both symbols have the
+ * same is_func value, we discriminate against is_static such that
+ * the global symbol survives.
+ */
+static int
+DEFUN (cmp_addr, (lp, rp), const PTR lp AND const PTR rp)
+{
+  Sym *left = (Sym *) lp;
+  Sym *right = (Sym *) rp;
+
+  if (left->addr > right->addr)
+    {
+      return 1;
+    }
+  else if (left->addr < right->addr)
+    {
+      return -1;
+    }
+
+  if (left->is_func != right->is_func)
+    {
+      return right->is_func - left->is_func;
+    }
+
+  return left->is_static - right->is_static;
+}
+
+
+void
+DEFUN (symtab_finalize, (tab), Sym_Table * tab)
+{
+  Sym *src, *dst;
+  bfd_vma prev_addr;
+
+  if (!tab->len)
+    {
+      return;
+    }
+
+  /*
+   * Sort symbol table in order of increasing function addresses:
+   */
+  qsort (tab->base, tab->len, sizeof (Sym), cmp_addr);
+
+  /*
+   * Remove duplicate entries to speed-up later processing and
+   * set end_addr if its not set yet:
+   */
+  prev_addr = tab->base[0].addr + 1;
+  for (src = dst = tab->base; src < tab->limit; ++src)
+    {
+      if (src->addr == prev_addr)
+       {
+         /*
+          * If same address, favor global symbol over static one,
+          * then function over line number.  If both symbols are
+          * either static or global and either function or line, check
+          * whether one has name beginning with underscore while
+          * the other doesn't.  In such cases, keep sym without
+          * underscore.  This takes cares of compiler generated
+          * symbols (such as __gnu_compiled, __c89_used, etc.).
+          */
+         if ((!src->is_static && dst[-1].is_static)
+             || ((src->is_static == dst[-1].is_static)
+                 && ((src->is_func && !dst[-1].is_func)
+                     || ((src->is_func == dst[-1].is_func)
+                         && ((src->name[0] != '_' && dst[-1].name[0] == '_')
+                             || (src->name[0]
+                                 && src->name[1] != '_'
+                                 && dst[-1].name[1] == '_'))))))
+           {
+             DBG (AOUTDEBUG | IDDEBUG,
+                  printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c",
+                          src->name, src->is_static ? 't' : 'T',
+                          src->is_func ? 'F' : 'f',
+                          dst[-1].name, dst[-1].is_static ? 't' : 'T',
+                          dst[-1].is_func ? 'F' : 'f');
+                  printf (" (addr=%lx)\n", src->addr));
+             dst[-1] = *src;
+           }
+         else
+           {
+             DBG (AOUTDEBUG | IDDEBUG,
+                  printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c",
+                          dst[-1].name, dst[-1].is_static ? 't' : 'T',
+                          dst[-1].is_func ? 'F' : 'f',
+                          src->name, src->is_static ? 't' : 'T',
+                          src->is_func ? 'F' : 'f');
+                  printf (" (addr=%lx)\n", src->addr));
+           }
+       }
+      else
+       {
+         if (dst > tab->base && dst[-1].end_addr == 0)
+           {
+             dst[-1].end_addr = src->addr - 1;
+           }
+
+         /* retain sym only if it has a non-empty address range: */
+         if (!src->end_addr || src->addr <= src->end_addr)
+           {
+             *dst++ = *src;
+             prev_addr = src->addr;
+           }
+       }
+    }
+  if (tab->len > 0 && dst[-1].end_addr == 0)
+    {
+      dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1;
+    }
+
+  DBG (AOUTDEBUG | IDDEBUG,
+       printf ("[symtab_finalize]: removed %d duplicate entries\n",
+              tab->len - (int) (dst - tab->base)));
+
+  tab->limit = dst;
+  tab->len = tab->limit - tab->base;
+
+  DBG (AOUTDEBUG | IDDEBUG,
+       unsigned int j;
+
+       for (j = 0; j < tab->len; ++j)
+       {
+       printf ("[symtab_finalize] 0x%lx-0x%lx\t%s\n",
+              (long) tab->base[j].addr, (long) tab->base[j].end_addr,
+              tab->base[j].name);
+       }
+  );
+}
+
+
+#ifdef DEBUG
+
+Sym *
+DEFUN (dbg_sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
+{
+  long low, mid, high;
+  Sym *sym;
+
+  fprintf (stderr, "[dbg_sym_lookup] address 0x%lx\n", address);
+
+  sym = symtab->base;
+  for (low = 0, high = symtab->len - 1; low != high;)
+    {
+      mid = (high + low) >> 1;
+      fprintf (stderr, "[dbg_sym_lookup] low=0x%lx, mid=0x%lx, high=0x%lx\n",
+              low, mid, high);
+      fprintf (stderr, "[dbg_sym_lookup] sym[m]=0x%lx sym[m + 1]=0x%lx\n",
+              sym[mid].addr, sym[mid + 1].addr);
+      if (sym[mid].addr <= address && sym[mid + 1].addr > address)
+       {
+         return &sym[mid];
+       }
+      if (sym[mid].addr > address)
+       {
+         high = mid;
+       }
+      else
+       {
+         low = mid + 1;
+       }
+    }
+  fprintf (stderr, "[dbg_sym_lookup] binary search fails???\n");
+  return 0;
+}
+
+#endif /* DEBUG */
+
+
+/*
+ * Look up an address in the symbol-table that is sorted by address.
+ * If address does not hit any symbol, 0 is returned.
+ */
+Sym *
+DEFUN (sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
+{
+  long low, high;
+  long mid = -1;
+  Sym *sym;
+#ifdef DEBUG
+  int probes = 0;
+#endif /* DEBUG */
+
+  if (!symtab->len)
+    {
+      return 0;
+    }
+
+  sym = symtab->base;
+  for (low = 0, high = symtab->len - 1; low != high;)
+    {
+      DBG (LOOKUPDEBUG, ++probes);
+      mid = (high + low) / 2;
+      if (sym[mid].addr <= address && sym[mid + 1].addr > address)
+       {
+         if (address > sym[mid].end_addr)
+           {
+             /*
+              * Address falls into gap between sym[mid] and
+              * sym[mid + 1]:
+              */
+             return 0;
+           }
+         else
+           {
+             DBG (LOOKUPDEBUG,
+                  printf ("[sym_lookup] %d probes (symtab->len=%u)\n",
+                          probes, symtab->len - 1));
+             return &sym[mid];
+           }
+       }
+      if (sym[mid].addr > address)
+       {
+         high = mid;
+       }
+      else
+       {
+         low = mid + 1;
+       }
+    }
+  if (sym[mid + 1].addr <= address)
+    {
+      if (address > sym[mid + 1].end_addr)
+       {
+         /* address is beyond end of sym[mid + 1]: */
+         return 0;
+       }
+      else
+       {
+         DBG (LOOKUPDEBUG, printf ("[sym_lookup] %d (%u) probes, fall off\n",
+                                   probes, symtab->len - 1));
+         return &sym[mid + 1];
+       }
+    }
+  return 0;
+}
diff --git a/gprof/symtab.h b/gprof/symtab.h
new file mode 100644 (file)
index 0000000..a6a450e
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef symtab_h
+#define symtab_h
+
+#include "bfd.h"
+#include "gprof.h"
+
+/*
+ * For a profile to be intelligible to a human user, it is necessary
+ * to map code-addresses into source-code information.  Source-code
+ * information can be any combination of: (i) function-name, (ii)
+ * source file-name, and (iii) source line number.
+ *
+ * The symbol table is used to map addresses into source-code
+ * information.
+ */
+
+#include "source.h"
+
+#define NBBS 10
+
+/*
+ * Symbol-entry.  For each external in the specified file we gather
+ * its address, the number of calls and compute its share of cpu time.
+ */
+typedef struct sym
+  {
+    /*
+     * Common information:
+     *
+     * In the symbol-table, fields ADDR and FUNC_NAME are guaranteed
+     * to contain valid information.  FILE may be 0, if unknown and
+     * LINE_NUM maybe 0 if unknown.
+     */
+    bfd_vma addr;              /* address of entry point */
+    bfd_vma end_addr;          /* end-address */
+    const char *name;          /* name of function this sym is from */
+    Source_File *file;         /* source file symbol comes from */
+    int line_num;              /* source line number */
+    unsigned int is_func:1,    /* is this a function entry point? */
+      is_static:1,             /* is this a local (static) symbol? */
+      is_bb_head:1,            /* is this the head of a basic-blk? */
+      mapped:1,                        /* this symbol was mapped to another name */
+      has_been_placed:1;       /* have we placed this symbol?  */
+    unsigned long ncalls;      /* how many times executed */
+    int nuses;                 /* how many times this symbol appears in
+                                  a particular context */
+    bfd_vma bb_addr[NBBS];     /* address of basic-block start */
+    unsigned long bb_calls[NBBS]; /* how many times basic-block was called */
+    struct sym *next;          /* for building chains of syms */
+    struct sym *prev;          /* for building chains of syms */
+
+    /* profile-specific information: */
+
+    /* histogram specific info: */
+    struct
+      {
+       double time;            /* (weighted) ticks in this routine */
+       bfd_vma scaled_addr;    /* scaled entry point */
+      }
+    hist;
+
+    /* call-graph specific info: */
+    struct
+      {
+       unsigned long self_calls; /* how many calls to self */
+       double child_time;      /* cumulative ticks in children */
+       int index;              /* index in the graph list */
+       int top_order;          /* graph call chain top-sort order */
+       bool print_flag;        /* should this be printed? */
+       struct
+         {
+           double fract;       /* what % of time propagates */
+           double self;        /* how much self time propagates */
+           double child;       /* how much child time propagates */
+         }
+       prop;
+       struct
+         {
+           int num;            /* internal number of cycle on */
+           struct sym *head;   /* head of cycle */
+           struct sym *next;   /* next member of cycle */
+         }
+       cyc;
+       struct arc *parents;    /* list of caller arcs */
+       struct arc *children;   /* list of callee arcs */
+      }
+    cg;
+  }
+Sym;
+
+/*
+ * Symbol-tables are always assumed to be sorted in increasing order
+ * of addresses:
+ */
+typedef struct
+  {
+    unsigned int len;          /* # of symbols in this table */
+    Sym *base;                 /* first element in symbol table */
+    Sym *limit;                        /* limit = base + len */
+  }
+Sym_Table;
+
+extern Sym_Table symtab;       /* the symbol table */
+
+extern void sym_init PARAMS ((Sym * sym));
+extern void symtab_finalize PARAMS ((Sym_Table * symtab));
+extern Sym *sym_lookup PARAMS ((Sym_Table * symtab, bfd_vma address));
+
+extern void find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+
+#endif /* symtab_h */
diff --git a/gprof/tahoe.c b/gprof/tahoe.c
new file mode 100644 (file)
index 0000000..d133c17
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "gprof.h"
+#include "cg_arcs.h"
+#include "corefile.h"
+#include "hist.h"
+#include "symtab.h"
+
+    /*
+     *        opcode of the `callf' instruction
+     */
+#define        CALLF   0xfe
+
+    /*
+     *        register for pc relative addressing
+     */
+#define        PC      0xf
+
+enum tahoe_opermodes
+  {
+    literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
+    bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
+    immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
+    longrel, longreldef
+  };
+typedef enum tahoe_opermodes tahoe_operandenum;
+
+/*
+ * A symbol to be the child of indirect callf:
+ */
+Sym indirectchild;
+
+
+tahoe_operandenum
+tahoe_operandmode (modep)
+     unsigned char *modep;
+{
+  long usesreg = ((long) *modep) & 0xf;
+
+  switch (((long) *modep) >> 4)
+    {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return literal;
+    case 4:
+      return indexed;
+    case 5:
+      return reg;
+    case 6:
+      return regdef;
+    case 7:
+      return autodec;
+    case 8:
+      return usesreg != 0xe ? autoinc : immediate;
+    case 9:
+      return usesreg != PC ? autoincdef : absolute;
+    case 10:
+      return usesreg != PC ? bytedisp : byterel;
+    case 11:
+      return usesreg != PC ? bytedispdef : bytereldef;
+    case 12:
+      return usesreg != PC ? worddisp : wordrel;
+    case 13:
+      return usesreg != PC ? worddispdef : wordreldef;
+    case 14:
+      return usesreg != PC ? longdisp : longrel;
+    case 15:
+      return usesreg != PC ? longdispdef : longreldef;
+    }
+  /* NOTREACHED */
+  abort ();
+}
+
+char *
+tahoe_operandname (mode)
+     tahoe_operandenum mode;
+{
+
+  switch (mode)
+    {
+    case literal:
+      return "literal";
+    case indexed:
+      return "indexed";
+    case reg:
+      return "register";
+    case regdef:
+      return "register deferred";
+    case autodec:
+      return "autodecrement";
+    case autoinc:
+      return "autoincrement";
+    case autoincdef:
+      return "autoincrement deferred";
+    case bytedisp:
+      return "byte displacement";
+    case bytedispdef:
+      return "byte displacement deferred";
+    case byterel:
+      return "byte relative";
+    case bytereldef:
+      return "byte relative deferred";
+    case worddisp:
+      return "word displacement";
+    case worddispdef:
+      return "word displacement deferred";
+    case wordrel:
+      return "word relative";
+    case wordreldef:
+      return "word relative deferred";
+    case immediate:
+      return "immediate";
+    case absolute:
+      return "absolute";
+    case longdisp:
+      return "long displacement";
+    case longdispdef:
+      return "long displacement deferred";
+    case longrel:
+      return "long relative";
+    case longreldef:
+      return "long relative deferred";
+    }
+  /* NOTREACHED */
+  abort ();
+}
+
+long
+tahoe_operandlength (modep)
+     unsigned char *modep;
+{
+
+  switch (tahoe_operandmode (modep))
+    {
+    case literal:
+    case reg:
+    case regdef:
+    case autodec:
+    case autoinc:
+    case autoincdef:
+      return 1;
+    case bytedisp:
+    case bytedispdef:
+    case byterel:
+    case bytereldef:
+      return 2;
+    case worddisp:
+    case worddispdef:
+    case wordrel:
+    case wordreldef:
+      return 3;
+    case immediate:
+    case absolute:
+    case longdisp:
+    case longdispdef:
+    case longrel:
+    case longreldef:
+      return 5;
+    case indexed:
+      return 1 + tahoe_operandlength (modep + 1);
+    }
+  /* NOTREACHED */
+  abort ();
+}
+
+bfd_vma
+tahoe_reladdr (modep)
+     char *modep;
+{
+  tahoe_operandenum mode = tahoe_operandmode (modep);
+  char *cp;
+  short *sp;
+  long *lp;
+  int i;
+  long value = 0;
+
+  cp = modep;
+  ++cp;                                /* skip over the mode */
+  switch (mode)
+    {
+    default:
+      fprintf (stderr, "[reladdr] not relative address\n");
+      return (bfd_vma) modep;
+    case byterel:
+      return (bfd_vma) (cp + sizeof *cp + *cp);
+    case wordrel:
+      for (i = 0; (size_t) i < sizeof *sp; i++)
+       value = (value << 8) + (cp[i] & 0xff);
+      return (bfd_vma) (cp + sizeof *sp + value);
+    case longrel:
+      for (i = 0; (size_t) i < sizeof *lp; i++)
+       value = (value << 8) + (cp[i] & 0xff);
+      return (bfd_vma) (cp + sizeof *lp + value);
+    }
+}
+
+void
+tahoe_find_call (parent, p_lowpc, p_highpc)
+     Sym *parent;
+     bfd_vma p_lowpc;
+     bfd_vma p_highpc;
+{
+  unsigned char *instructp;
+  long length;
+  Sym *child;
+  tahoe_operandenum mode;
+  tahoe_operandenum firstmode;
+  bfd_vma destpc;
+  static bool inited = FALSE;
+
+  if (!inited)
+    {
+      inited = TRUE;
+      sym_init (&indirectchild);
+      indirectchild.cg.prop.fract = 1.0;
+      indirectchild.cg.cyc.head = &indirectchild;
+    }
+
+  if (core_text_space == 0)
+    {
+      return;
+    }
+  if (p_lowpc < s_lowpc)
+    {
+      p_lowpc = s_lowpc;
+    }
+  if (p_highpc > s_highpc)
+    {
+      p_highpc = s_highpc;
+    }
+  DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
+                         parent->name, p_lowpc, p_highpc));
+  for (instructp = (unsigned char *) core_text_space + p_lowpc;
+       instructp < (unsigned char *) core_text_space + p_highpc;
+       instructp += length)
+    {
+      length = 1;
+      if (*instructp == CALLF)
+       {
+         /*
+          *    maybe a callf, better check it out.
+          *      skip the count of the number of arguments.
+          */
+         DBG (CALLDEBUG, printf ("[findcall]\t0x%x:callf",
+                                 instructp - (unsigned char *) core_text_space));
+         firstmode = tahoe_operandmode (instructp + length);
+         switch (firstmode)
+           {
+           case literal:
+           case immediate:
+             break;
+           default:
+             goto botched;
+           }
+         length += tahoe_operandlength (instructp + length);
+         mode = tahoe_operandmode (instructp + length);
+         DBG (CALLDEBUG,
+              printf ("\tfirst operand is %s", tahoe_operandname (firstmode));
+              printf ("\tsecond operand is %s\n", tahoe_operandname (mode));
+           );
+         switch (mode)
+           {
+           case regdef:
+           case bytedispdef:
+           case worddispdef:
+           case longdispdef:
+           case bytereldef:
+           case wordreldef:
+           case longreldef:
+             /*
+              *    indirect call: call through pointer
+              *      either  *d(r)   as a parameter or local
+              *              (r)     as a return value
+              *              *f      as a global pointer
+              *      [are there others that we miss?,
+              *       e.g. arrays of pointers to functions???]
+              */
+             arc_add (parent, &indirectchild, (unsigned long) 0);
+             length += tahoe_operandlength (instructp + length);
+             continue;
+           case byterel:
+           case wordrel:
+           case longrel:
+             /*
+              *    regular pc relative addressing
+              *      check that this is the address of 
+              *      a function.
+              */
+             destpc = tahoe_reladdr (instructp + length)
+               - (bfd_vma) core_text_space;
+             if (destpc >= s_lowpc && destpc <= s_highpc)
+               {
+                 child = sym_lookup (&symtab, destpc);
+                 DBG (CALLDEBUG,
+                      printf ("[findcall]\tdestpc 0x%lx", destpc);
+                      printf (" child->name %s", child->name);
+                      printf (" child->addr 0x%lx\n", child->addr);
+                   );
+                 if (child->addr == destpc)
+                   {
+                     /*
+                      *    a hit
+                      */
+                     arc_add (parent, child, (unsigned long) 0);
+                     length += tahoe_operandlength (instructp + length);
+                     continue;
+                   }
+                 goto botched;
+               }
+             /*
+              *    else:
+              *      it looked like a callf,
+              *      but it wasn't to anywhere.
+              */
+             goto botched;
+           default:
+           botched:
+             /*
+              *    something funny going on.
+              */
+             DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
+             length = 1;
+             continue;
+           }
+       }
+    }
+}
diff --git a/gprof/utils.c b/gprof/utils.c
new file mode 100644 (file)
index 0000000..e1f031d
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1983, 1998 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include <demangle.h>
+#include "gprof.h"
+#include "cg_arcs.h"
+#include "symtab.h"
+
+
+/*
+ * Print name of symbol.  Return number of characters printed.
+ */
+int
+DEFUN (print_name_only, (self), Sym * self)
+{
+  const char *name = self->name;
+  const char *filename;
+  char *demangled = 0;
+  char buf[PATH_MAX];
+  int size = 0;
+
+  if (name)
+    {
+      if (!bsd_style_output)
+       {
+         if (name[0] == '_' && name[1] && discard_underscores)
+           {
+             name++;
+           }
+         if (demangle)
+           {
+             demangled = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+             if (demangled)
+               {
+                 name = demangled;
+               }
+           }
+       }
+      printf ("%s", name);
+      size = strlen (name);
+      if (line_granularity && self->file)
+       {
+         filename = self->file->name;
+         if (!print_path)
+           {
+             filename = strrchr (filename, '/');
+             if (filename)
+               {
+                 ++filename;
+               }
+             else
+               {
+                 filename = self->file->name;
+               }
+           }
+         sprintf (buf, " (%s:%d)", filename, self->line_num);
+         printf (buf);
+         size += strlen (buf);
+       }
+      if (demangled)
+       {
+         free (demangled);
+       }
+      DBG (DFNDEBUG, printf ("{%d} ", self->cg.top_order));
+      DBG (PROPDEBUG, printf ("%4.0f%% ", 100.0 * self->cg.prop.fract));
+    }
+  return size;
+}
+
+
+void
+DEFUN (print_name, (self), Sym * self)
+{
+  print_name_only (self);
+
+  if (self->cg.cyc.num != 0)
+    {
+      printf (_(" <cycle %d>"), self->cg.cyc.num);
+    }
+  if (self->cg.index != 0)
+    {
+      if (self->cg.print_flag)
+       {
+         printf (" [%d]", self->cg.index);
+       }
+      else
+       {
+         printf (" (%d)", self->cg.index);
+       }
+    }
+}
diff --git a/gprof/utils.h b/gprof/utils.h
new file mode 100644 (file)
index 0000000..27fb9c6
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef utils_h
+#define utils_h
+
+extern int print_name_only PARAMS ((Sym * self));
+extern void print_name PARAMS ((Sym * self));
+
+#endif /* utils_h */
diff --git a/gprof/vax.c b/gprof/vax.c
new file mode 100644 (file)
index 0000000..1a7bd8d
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that: (1) source distributions retain this entire copyright
+ * notice and comment, and (2) distributions including binaries display
+ * the following acknowledgement:  ``This product includes software
+ * developed by the University of California, Berkeley and its contributors''
+ * in the documentation or other materials provided with the distribution
+ * and in all advertising materials mentioning features or use of this
+ * software. Neither the name of the University nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "gprof.h"
+#include "cg_arcs.h"
+#include "corefile.h"
+#include "hist.h"
+#include "symtab.h"
+
+    /*
+     *        opcode of the `calls' instruction
+     */
+#define        CALLS   0xfb
+
+    /*
+     *        register for pc relative addressing
+     */
+#define        PC      0xf
+
+enum opermodes
+  {
+    literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
+    bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
+    immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
+    longrel, longreldef
+  };
+typedef enum opermodes operandenum;
+
+struct modebyte
+  {
+    unsigned int regfield:4;
+    unsigned int modefield:4;
+  };
+
+/*
+ * A symbol to be the child of indirect calls:
+ */
+Sym indirectchild;
+
+
+static operandenum
+vax_operandmode (modep)
+     struct modebyte *modep;
+{
+  long usesreg = modep->regfield;
+
+  switch (modep->modefield)
+    {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return literal;
+    case 4:
+      return indexed;
+    case 5:
+      return reg;
+    case 6:
+      return regdef;
+    case 7:
+      return autodec;
+    case 8:
+      return usesreg != PC ? autoinc : immediate;
+    case 9:
+      return usesreg != PC ? autoincdef : absolute;
+    case 10:
+      return usesreg != PC ? bytedisp : byterel;
+    case 11:
+      return usesreg != PC ? bytedispdef : bytereldef;
+    case 12:
+      return usesreg != PC ? worddisp : wordrel;
+    case 13:
+      return usesreg != PC ? worddispdef : wordreldef;
+    case 14:
+      return usesreg != PC ? longdisp : longrel;
+    case 15:
+      return usesreg != PC ? longdispdef : longreldef;
+    }
+  /* NOTREACHED */
+  abort ();
+}
+
+static char *
+vax_operandname (mode)
+     operandenum mode;
+{
+
+  switch (mode)
+    {
+    case literal:
+      return "literal";
+    case indexed:
+      return "indexed";
+    case reg:
+      return "register";
+    case regdef:
+      return "register deferred";
+    case autodec:
+      return "autodecrement";
+    case autoinc:
+      return "autoincrement";
+    case autoincdef:
+      return "autoincrement deferred";
+    case bytedisp:
+      return "byte displacement";
+    case bytedispdef:
+      return "byte displacement deferred";
+    case byterel:
+      return "byte relative";
+    case bytereldef:
+      return "byte relative deferred";
+    case worddisp:
+      return "word displacement";
+    case worddispdef:
+      return "word displacement deferred";
+    case wordrel:
+      return "word relative";
+    case wordreldef:
+      return "word relative deferred";
+    case immediate:
+      return "immediate";
+    case absolute:
+      return "absolute";
+    case longdisp:
+      return "long displacement";
+    case longdispdef:
+      return "long displacement deferred";
+    case longrel:
+      return "long relative";
+    case longreldef:
+      return "long relative deferred";
+    }
+  /* NOTREACHED */
+  abort ();
+}
+
+static long
+vax_operandlength (modep)
+     struct modebyte *modep;
+{
+
+  switch (vax_operandmode (modep))
+    {
+    case literal:
+    case reg:
+    case regdef:
+    case autodec:
+    case autoinc:
+    case autoincdef:
+      return 1;
+    case bytedisp:
+    case bytedispdef:
+    case byterel:
+    case bytereldef:
+      return 2;
+    case worddisp:
+    case worddispdef:
+    case wordrel:
+    case wordreldef:
+      return 3;
+    case immediate:
+    case absolute:
+    case longdisp:
+    case longdispdef:
+    case longrel:
+    case longreldef:
+      return 5;
+    case indexed:
+      return 1 + vax_operandlength ((struct modebyte *) ((char *) modep) + 1);
+    }
+  /* NOTREACHED */
+  abort ();
+}
+
+static bfd_vma
+vax_reladdr (modep)
+     struct modebyte *modep;
+{
+  operandenum mode = vax_operandmode (modep);
+  char *cp;
+  short *sp;
+  long *lp;
+
+  cp = (char *) modep;
+  ++cp;                                /* skip over the mode */
+  switch (mode)
+    {
+    default:
+      fprintf (stderr, "[reladdr] not relative address\n");
+      return (bfd_vma) modep;
+    case byterel:
+      return (bfd_vma) (cp + sizeof *cp + *cp);
+    case wordrel:
+      sp = (short *) cp;
+      return (bfd_vma) (cp + sizeof *sp + *sp);
+    case longrel:
+      lp = (long *) cp;
+      return (bfd_vma) (cp + sizeof *lp + *lp);
+    }
+}
+
+
+void
+vax_find_call (parent, p_lowpc, p_highpc)
+     Sym *parent;
+     bfd_vma p_lowpc;
+     bfd_vma p_highpc;
+{
+  unsigned char *instructp;
+  long length;
+  Sym *child;
+  operandenum mode;
+  operandenum firstmode;
+  bfd_vma destpc;
+  static bool inited = FALSE;
+
+  if (!inited)
+    {
+      inited = TRUE;
+      sym_init (&indirectchild);
+      indirectchild.cg.prop.fract = 1.0;
+      indirectchild.cg.cyc.head = &indirectchild;
+    }
+
+  if (core_text_space == 0)
+    {
+      return;
+    }
+  if (p_lowpc < s_lowpc)
+    {
+      p_lowpc = s_lowpc;
+    }
+  if (p_highpc > s_highpc)
+    {
+      p_highpc = s_highpc;
+    }
+  DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
+                         parent->name, p_lowpc, p_highpc));
+  for (instructp = (unsigned char *) core_text_space + p_lowpc;
+       instructp < (unsigned char *) core_text_space + p_highpc;
+       instructp += length)
+    {
+      length = 1;
+      if (*instructp == CALLS)
+       {
+         /*
+          *    maybe a calls, better check it out.
+          *      skip the count of the number of arguments.
+          */
+         DBG (CALLDEBUG,
+              printf ("[findcall]\t0x%x:calls",
+                      instructp - (unsigned char *) core_text_space));
+         firstmode = vax_operandmode ((struct modebyte *) (instructp + length));
+         switch (firstmode)
+           {
+           case literal:
+           case immediate:
+             break;
+           default:
+             goto botched;
+           }
+         length += vax_operandlength ((struct modebyte *) (instructp + length));
+         mode = vax_operandmode ((struct modebyte *) (instructp + length));
+         DBG (CALLDEBUG,
+              printf ("\tfirst operand is %s", vax_operandname (firstmode));
+              printf ("\tsecond operand is %s\n", vax_operandname (mode)));
+         switch (mode)
+           {
+           case regdef:
+           case bytedispdef:
+           case worddispdef:
+           case longdispdef:
+           case bytereldef:
+           case wordreldef:
+           case longreldef:
+             /*
+              *    indirect call: call through pointer
+              *      either  *d(r)   as a parameter or local
+              *              (r)     as a return value
+              *              *f      as a global pointer
+              *      [are there others that we miss?,
+              *       e.g. arrays of pointers to functions???]
+              */
+             arc_add (parent, &indirectchild, (unsigned long) 0);
+             length += vax_operandlength (
+                                 (struct modebyte *) (instructp + length));
+             continue;
+           case byterel:
+           case wordrel:
+           case longrel:
+             /*
+              *    regular pc relative addressing
+              *      check that this is the address of 
+              *      a function.
+              */
+             destpc = vax_reladdr ((struct modebyte *) (instructp + length))
+               - (bfd_vma) core_text_space;
+             if (destpc >= s_lowpc && destpc <= s_highpc)
+               {
+                 child = sym_lookup (&symtab, destpc);
+                 DBG (CALLDEBUG,
+                      printf ("[findcall]\tdestpc 0x%lx", destpc);
+                      printf (" child->name %s", child->name);
+                      printf (" child->addr 0x%lx\n", child->addr);
+                   );
+                 if (child->addr == destpc)
+                   {
+                     /*
+                      *    a hit
+                      */
+                     arc_add (parent, child, (unsigned long) 0);
+                     length += vax_operandlength ((struct modebyte *)
+                                                  (instructp + length));
+                     continue;
+                   }
+                 goto botched;
+               }
+             /*
+              *    else:
+              *      it looked like a calls,
+              *      but it wasn't to anywhere.
+              */
+             goto botched;
+           default:
+           botched:
+             /*
+              *    something funny going on.
+              */
+             DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
+             length = 1;
+             continue;
+           }
+       }
+    }
+}