--- /dev/null
+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:
--- /dev/null
+## 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
--- /dev/null
+# 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:
--- /dev/null
+-*- 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:
--- /dev/null
+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.
--- /dev/null
+sinclude(../bfd/acinclude.m4)
--- /dev/null
+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])
+
--- /dev/null
+.\" 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).
--- /dev/null
+/* 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;
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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);
+}
--- /dev/null
+%{
+/* 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
--- /dev/null
+%{
+/* 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;
+}
--- /dev/null
+/* 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;
+ }
+ }
+}
--- /dev/null
+/* 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;
--- /dev/null
+\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
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+#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();
--- /dev/null
+/* 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
+
--- /dev/null
+#! /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
+
--- /dev/null
+@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
--- /dev/null
+$!
+$! 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'"
--- /dev/null
+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
+])
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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 = ⊤
+
+ 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;
+}
--- /dev/null
+/* 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 */
--- /dev/null
+%{/* 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
--- /dev/null
+%{ /* 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;}
+ ;
+
+
+
--- /dev/null
+: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
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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));
--- /dev/null
+/* 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
+}
--- /dev/null
+/* 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, §ype)
+ || ! 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;
+}
--- /dev/null
+/* Linked with ar.o to flag that this program is 'ranlib' (not 'ar'). */
+
+int is_ranlib = 1;
--- /dev/null
+/* Linked with objcopy.o to flag that this program is 'strip' (not
+ 'objcopy'). */
+
+int is_strip = 1;
--- /dev/null
+/* 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 */
--- /dev/null
+#
+# 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;
--- /dev/null
+/* 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;
--- /dev/null
+/* 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;
--- /dev/null
+# 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
--- /dev/null
+# 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//
+
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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 = ©right_hdr_struct;
+ memset ((PTR) ©right_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;
+}
--- /dev/null
+/* 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 *));
--- /dev/null
+%{/* 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;
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* Linked with ar.o to flag that this program is 'ar' (not 'ranlib'). */
+
+int is_ranlib = 0;
--- /dev/null
+/* Linked with objcopy.o to flag that this program is 'objcopy' (not
+ 'strip'). */
+
+int is_strip = 0;
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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;
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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;
+}
--- /dev/null
+# 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:
--- /dev/null
+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
--- /dev/null
+# 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 ""
--- /dev/null
+/* 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;
+}
--- /dev/null
+.\" 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.
--- /dev/null
+#!/bin/sh
+# A simple ranlib script, to use less disk space than a ranlib program.
+ar s $1
--- /dev/null
+%{ /* 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;
+}
--- /dev/null
+%{ /* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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);
+ }
+}
--- /dev/null
+/* 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");
+ }
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+#!/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
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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);
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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;
+}
--- /dev/null
+%{
+#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;
+}
--- /dev/null
+%{
+#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;}
--- /dev/null
+("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"))))
+
--- /dev/null
+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.
+
--- /dev/null
+# 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
--- /dev/null
+ .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
--- /dev/null
+ .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
--- /dev/null
+# 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"
+}
--- /dev/null
+# 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.
--- /dev/null
+# 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"
+ }
+}
--- /dev/null
+# 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.
--- /dev/null
+# 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*-*-*}
--- /dev/null
+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: .*
--- /dev/null
+
+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.*
--- /dev/null
+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
+
--- /dev/null
+
+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
--- /dev/null
+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: .\)
--- /dev/null
+# 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"
+ }
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+# 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
+}
--- /dev/null
+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/
--- /dev/null
+# 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};
+}
+}
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+/* 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));
--- /dev/null
+/* 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);
+ }
+}
--- /dev/null
+/* 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));
--- /dev/null
+/* 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);
+}
--- /dev/null
+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.
+
--- /dev/null
+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)
+])
--- /dev/null
+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
--- /dev/null
+RANLIB = @:
--- /dev/null
+# 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
--- /dev/null
+HDEFINES = -DUSG
+RANLIB=true
+CC= cc -A ansi -A runtype,any -A systype,any -U__STDC__ -DUSG
--- /dev/null
+PICFLAG=-fPIC
--- /dev/null
+# 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
--- /dev/null
+EXTRA_TARGET_HOST_ALL_MODULES=all-libtermcap
+EXTRA_TARGET_HOST_INSTALL_MODULES=install-libtermcap
+
+all-gdb: all-libtermcap
+
+install-gdb: all-libtermcap
--- /dev/null
+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"
--- /dev/null
+RANLIB = true
+
+
+
--- /dev/null
+HDEFINES=-DHOST_SYS=DGUX_SYS
+CC=gcc -Wall -ansi -D__using_DGUX
+RANLIB=true
+
--- /dev/null
+# 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
+
--- /dev/null
+# 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
--- /dev/null
+PICFLAG=-fPIC
--- /dev/null
+# 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 =
--- /dev/null
+# Define SYSV as -DSYSV if you are using a System V operating system.
+CC = cc -Wp,-H256000
+SYSV = -DSYSV
+RANLIB = true
--- /dev/null
+# Define SYSV as -DSYSV if you are using a System V operating system.
+CC = cc -Wp,-H256000
+SYSV = -DSYSV
+RANLIB = true
--- /dev/null
+# 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=
--- /dev/null
+# 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
--- /dev/null
+# Makefile changes for SGI's running IRIX-5.x.
+SYSV = -DSYSV
+RANLIB = true
--- /dev/null
+# 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
--- /dev/null
+# /bin/cc is less than useful for our purposes. Always use GCC
+CC = /bin/gcc
--- /dev/null
+# 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
--- /dev/null
+PICFLAG=-fpic
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+PICFLAG=-fPIC
--- /dev/null
+PICFLAG=-fPIC
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# Makefile changes for Suns running Solaris 2
+
+SYSV = -DSYSV
+RANLIB = true
+
+X11_EXTRA_LIBS = -lnsl -lsocket
--- /dev/null
+PICFLAG=`case "${LIBCFLAGS} ${LIBCXXFLAGS}" in *-fpic* ) echo -fpic ;; * ) echo -fPIC ;; esac`
--- /dev/null
+# 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
--- /dev/null
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV
+RANLIB = true
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# The old BSD pcc isn't up to compiling parts of gdb so use gcc
+CC = gcc
--- /dev/null
+PICFLAG=-fpic
--- /dev/null
+# 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
+
--- /dev/null
+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.
--- /dev/null
+# 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
--- /dev/null
+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".
--- /dev/null
+Echo '#include' ¶""{1}"¶" >"{2}".tem
+MoveIfChange "{2}".tem "{2}"
+
--- /dev/null
+# 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}"
+
--- /dev/null
+# "Touch" command.
+
+If "`Exists "{1}"`" != ""
+ SetFile -m . "{1}"
+Else
+ Echo ' ' > "{1}"
+End If
--- /dev/null
+# This command does nothing.
--- /dev/null
+# MPW makefiles seem not to have any way to get a literal open
+# brace into a rule anywhere, so this does the job.
+
+Echo '{'
--- /dev/null
+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}"
--- /dev/null
+PICFLAG_FOR_TARGET=-fPIC
--- /dev/null
+# 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
--- /dev/null
+PICFLAG_FOR_TARGET=-fPIC
--- /dev/null
+# When using glibc 2 on Linux we must always use vtable thunks.
+CXXFLAGS_FOR_TARGET = $(CXXFLAGS) -fvtable-thunks -D_GNU_SOURCE
--- /dev/null
+PICFLAG_FOR_TARGET=-fpic
--- /dev/null
+GDB_NLM_DEPS = all-gcc all-ld
--- /dev/null
+# Build libraries optimizing for space, not speed.
+ CFLAGS_FOR_TARGET = -g -Os
+ CXXFLAGS_FOR_TARGET = -g -Os
--- /dev/null
+PICFLAG_FOR_TARGET=-fPIC
--- /dev/null
+PICFLAG_FOR_TARGET=-fPIC
--- /dev/null
+PICFLAG_FOR_TARGET=`case "${LIBCFLAGS} ${LIBCXXFLAGS}" in *-fpic* ) echo -fpic ;; * ) echo -fPIC ;; esac`
--- /dev/null
+CC_FOR_TARGET = ca732 -ansi
+AS_FOR_TARGET = as732
+AR_FOR_TARGET = ar732
+RANLIB_FOR_TARGET = true
--- /dev/null
+PICFLAG_FOR_TARGET=-fpic
--- /dev/null
+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
+
--- /dev/null
+#
+# 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:
--- /dev/null
+;;; ============ 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
--- /dev/null
+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
--- /dev/null
+%!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
--- /dev/null
+#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
--- /dev/null
+ config.in *configure* Makefile.in
+ | | |
+ | v |
+ | config.status |
+ | | |
+ *config.status*<======+==========>*config.status*
+ | |
+ v v
+ config.h Makefile
--- /dev/null
+%!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
--- /dev/null
+#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
--- /dev/null
+ 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
--- /dev/null
+#! /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
+
--- /dev/null
+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)
--- /dev/null
+\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
--- /dev/null
+@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.
--- /dev/null
+\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:
--- /dev/null
+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.
--- /dev/null
+## 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
--- /dev/null
+# 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:
--- /dev/null
+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.
--- /dev/null
+- 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
--- /dev/null
+
+- 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
--- /dev/null
+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])
+
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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 ***/
--- /dev/null
+#! /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);
+ }
+}
--- /dev/null
+
+
+
+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
--- /dev/null
+#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));
+ }
+ }
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#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 */
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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 */
--- /dev/null
+#! /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
+
--- /dev/null
+@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
--- /dev/null
+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])
--- /dev/null
+#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,
+ <ab.limit->name, <ab.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 (<ab);
+ free (symtab.base);
+ symtab = ltab;
+
+}
--- /dev/null
+#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 */
--- /dev/null
+
+ % 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.
--- /dev/null
+
+ 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.
+
--- /dev/null
+/* 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
+
--- /dev/null
+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 "}" }
--- /dev/null
+/*-
+ * 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 */
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+.\" 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.
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+\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).
--- /dev/null
+/*
+ * 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) */
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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"));
+ }
+ }
+}
--- /dev/null
+# 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:
--- /dev/null
+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
--- /dev/null
+# 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 ""
--- /dev/null
+#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);
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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"));
+ }
+ }
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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 */
--- /dev/null
+#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;
+}
--- /dev/null
+#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 */
--- /dev/null
+/*
+ * 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;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+#ifndef utils_h
+#define utils_h
+
+extern int print_name_only PARAMS ((Sym * self));
+extern void print_name PARAMS ((Sym * self));
+
+#endif /* utils_h */
--- /dev/null
+/*
+ * 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;
+ }
+ }
+ }
+}